Repository: Project-MONAI/monai-deploy-app-sdk (language: python)

Issue:
Update README.md and CONTRIBUTION.md
Update documents in Github to reflect the current status of the repository with some existing examples.


Discussion / hints:

Fix patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ca40261d..bf8a42a8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,30 +1,27 @@
 - [Introduction](#introduction)
+  - [Communicate with us](#communicate-with-us)
 - [The contribution process](#the-contribution-process)
-  * [Preparing pull requests](#preparing-pull-requests)
-    1. [Checking the coding style](#checking-the-coding-style)
-    1. [Unit testing](#unit-testing)
-    1. [Building the documentation](#building-the-documentation)
-    1. [Automatic code formatting](#automatic-code-formatting)
-    1. [Signing your work](#signing-your-work)
-    1. [Utility functions](#utility-functions)
-  * [Submitting pull requests](#submitting-pull-requests)
-- [The code reviewing process (for the maintainers)](#the-code-reviewing-process)
-  * [Reviewing pull requests](#reviewing-pull-requests)
-- [Admin tasks (for the maintainers)](#admin-tasks)
-  * [Releasing a new version](#release-a-new-version)
+  - [Preparing pull requests](#preparing-pull-requests)
+    - [Checking the coding style](#checking-the-coding-style)
+      - [Exporting modules](#exporting-modules)
+    - [Unit testing](#unit-testing)
+    - [Building the documentation](#building-the-documentation)
+    - [Automatic code formatting](#automatic-code-formatting)
+    - [Signing your work](#signing-your-work)
+    - [Utility functions](#utility-functions)
+  - [Submitting pull requests](#submitting-pull-requests)
+- [The code reviewing process](#the-code-reviewing-process)
+  - [Reviewing pull requests](#reviewing-pull-requests)
+- [Admin tasks](#admin-tasks)
+  - [Release a new version](#release-a-new-version)
 
 ## Introduction
 
-
-Welcome to Project MONAI! We're excited you're here and want to contribute. This documentation is intended for individuals and institutions interested in contributing to MONAI. MONAI is an open-source project and, as such, its success relies on its community of contributors willing to keep improving it. Your contribution will be a valued addition to the code base; we simply ask that you read this page and understand our contribution process, whether you are a seasoned open-source contributor or whether you are a first-time contributor.
+Welcome to Project MONAI Deploy Application SDK (MONAI App SDK)! We're excited you're here and want to contribute. This documentation is intended for individuals and institutions interested in contributing to MONAI App SDK. MONAI App SDK is an open-source project and, as such, its success relies on its community of contributors willing to keep improving it. Your contribution will be a valued addition to the code base; we simply ask that you read this page and understand our contribution process, whether you are a seasoned open-source contributor or whether you are a first-time contributor.
 
 ### Communicate with us
 
-We are happy to talk with you about your needs for MONAI and your ideas for contributing to the project. One way to do this is to create an issue discussing your thoughts. It might be that a very similar feature is under development or already exists, so an issue is a great starting point. If you are looking for an issue to resolve that will help Project MONAI, see the [*good first issue*](https://github.com/Project-MONAI/MONAI/labels/good%20first%20issue) and [*Contribution wanted*](https://github.com/Project-MONAI/MONAI/labels/Contribution%20wanted) labels.
-
-### Does it belong in PyTorch instead of MONAI?
-
-MONAI is part of [PyTorch Ecosystem](https://pytorch.org/ecosystem/), and mainly based on the PyTorch and Numpy libraries. These libraries implement what we consider to be best practice for general scientific computing and deep learning functionality. MONAI builds on these with a strong focus on medical applications. As such, it is a good idea to consider whether your functionality is medical-application specific or not. General deep learning functionality may be better off in PyTorch; you can find their contribution guidelines [here](https://pytorch.org/docs/stable/community/contribution_guide.html).
+We are happy to talk with you about your needs for MONAI App SDK and your ideas for contributing to the project. One way to do this is to create an issue discussing your thoughts. It might be that a very similar feature is under development or already exists, so an issue is a great starting point. If you are looking for an issue to resolve that will help Project MONAI App SDK, see the [*good first issue*](https://github.com/Project-MONAI/monai-deploy-app-sdk/labels/good%20first%20issue) and [*Contribution wanted*](https://github.com/Project-MONAI/monai-deploy-app-sdk/labels/Contribution%20wanted) labels.
 
 ## The contribution process
 
@@ -32,39 +29,44 @@ _Pull request early_
 
 We encourage you to create pull requests early. It helps us track the contributions under development, whether they are ready to be merged or not. Change your pull request's title, to begin with `[WIP]` and/or [create a draft pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests) until it is ready for formal review.
 
-Please note that, as per PyTorch, MONAI uses American English spelling. This means classes and variables should be: normali**z**e, visuali**z**e, colo~~u~~r, etc.
+Please note that, as per PyTorch, MONAI App SDK uses American English spelling. This means classes and variables should be: normali**z**e, visuali**z**e, colo~~u~~r, etc.
 
 ### Preparing pull requests
-To ensure the code quality, MONAI relies on several linting tools ([flake8 and its plugins](https://gitlab.com/pycqa/flake8), [black](https://github.com/psf/black), [isort](https://github.com/timothycrosley/isort)),
-static type analysis tools ([mypy](https://github.com/python/mypy), [pytype](https://github.com/google/pytype)), as well as a set of unit/integration tests.
+
+To ensure the code quality, MONAI App SDK relies on several linting tools ([flake8 and its plugins](https://gitlab.com/pycqa/flake8), [black](https://github.com/psf/black), [isort](https://github.com/timothycrosley/isort)),
+static type analysis tools ([mypy](https://github.com/python/mypy), [pytype](https://github.com/google/pytype)), as well as a set of unit/integration/system tests.
 
 This section highlights all the necessary preparation steps required before sending a pull request.
 To collaborate efficiently, please read through this section and follow them.
 
-* [Checking the coding style](#checking-the-coding-style)
-* [Unit testing](#unit-testing)
-* [Building documentation](#building-the-documentation)
-* [Signing your work](#signing-your-work)
+- [Checking the coding style](#checking-the-coding-style)
+- [Unit testing](#unit-testing)
+- [Building documentation](#building-the-documentation)
+- [Signing your work](#signing-your-work)
 
 #### Checking the coding style
+
 Coding style is checked and enforced by flake8, black, and isort, using [a flake8 configuration](./setup.cfg) similar to [PyTorch's](https://github.com/pytorch/pytorch/blob/master/.flake8).
 Before submitting a pull request, we recommend that all linting should pass, by running the following command locally:
 
 ```bash
-# optionally update the dependencies and dev tools
-python -m pip install -U pip
-python -m pip install -U -r requirements-dev.txt
+# Setup development environment
+./run setup
 
-# run the linting and type checking tools
-./runtests.sh --codeformat
+# Run the linting and type checking tools
+./run check --codeformat  # or -f
 
-# try to fix the coding style errors automatically
-./runtests.sh --autofix
+# Try to fix the coding style errors automatically
+./run check --autofix
+
+# Show help
+./run check --help
 ```
 
 License information: all source code files should start with this paragraph:
-```
-# Copyright 2020 - 2021 MONAI Consortium
+
+```python
+# Copyright 2021 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
@@ -74,7 +76,6 @@ License information: all source code files should start with this paragraph:
 # 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.
-
 ```
 
 ##### Exporting modules
@@ -85,99 +86,71 @@ If you intend for any variables/functions/classes to be available outside of the
 - Add to the `__init__.py` file.
 
 #### Unit testing
-MONAI tests are located under `tests/`.
+
+MONAI App SDK tests are located under `tests/` (it has `unit`/`integration`/`performance`/`system` subfolders.)
 
 - The unit test's file name currently follows `test_[module_name].py` or `test_[module_name]_dist.py`.
 - The `test_[module_name]_dist.py` subset of unit tests requires a distributed environment to verify the module with distributed GPU-based computation.
-- The integration test's file name follows `test_integration_[workflow_name].py`.
+- The integration test's file name follows `test_[workflow_name].py`.
 
-A bash script (`runtests.sh`) is provided to run all tests locally.
-Please run ``./runtests.sh -h`` to see all options.
+A bash script (`run`) is provided to run all tests locally.
+Please run ``./run test -h`` to see all options.
 
-To run a particular test, for example `tests/test_dice_loss.py`:
-```
-python -m tests.test_dice_loss
+To run a particular test, for example, `tests/unit/test_sizeutil.py`:
+
+```bash
+./run pytest tests/unit/test_sizeutil.py
 ```
 
-Before submitting a pull request, we recommend that all linting and unit tests
+Before submitting a pull request, we recommend that all linting and tests
 should pass, by running the following command locally:
 
 ```bash
-./runtests.sh -f -u --net --coverage
+./run check -f
+./run test
 ```
+
 or (for new features that would not break existing functionality):
 
 ```bash
-./runtests.sh --quick --unittests
+./run check -f
+./run test all unit  # execute unit tests only
 ```
 
-It is recommended that the new test `test_[module_name].py` is constructed by using only
-python 3.6+ build-in functions, `torch`, `numpy`, `coverage` (for reporting code coverages) and `parameterized` (for organising test cases) packages.
-If it requires any other external packages, please make sure:
-- the packages are listed in [`requirements-dev.txt`](requirements-dev.txt)
-- the new test `test_[module_name].py` is added to the `exclude_cases` in [`./tests/min_tests.py`](./tests/min_tests.py) so that
-the minimal CI runner will not execute it.
-
 _If it's not tested, it's broken_
 
 All new functionality should be accompanied by an appropriate set of tests.
-MONAI functionality has plenty of unit tests from which you can draw inspiration,
+MONAI App SDK functionality has plenty of unit tests from which you can draw inspiration,
 and you can reach out to us if you are unsure of how to proceed with testing.
 
-MONAI's code coverage report is available at [CodeCov](https://codecov.io/gh/Project-MONAI/MONAI).
+MONAI APP SDK's code coverage report is available at [CodeCov](https://codecov.io/gh/Project-MONAI/monai-deploy-app-sdk).
 
 #### Building the documentation
-MONAI's documentation is located at `docs/`.
-
-```bash
-# install the doc-related dependencies
-pip install --upgrade pip
-pip install -r docs/requirements.txt
-
-# build the docs
-cd docs/
-make html
-```
-The above commands build html documentation, they are used to automatically generate [https://docs.monai.io](https://docs.monai.io).
-
-Before submitting a pull request, it is recommended to:
-- edit the relevant `.rst` files in [`docs/source`](./docs/source) accordingly.
-- build html documentation locally
-- check the auto-generated documentation (by browsing `./docs/build/html/index.html` with a web browser)
-- type `make clean` in `docs/` folder to remove the current build files.
-
-Please type `make help` in `docs/` folder for all supported format options.
 
 #### Automatic code formatting
-MONAI provides support of automatic Python code formatting via [a customised GitHub action](https://github.com/Project-MONAI/monai-code-formatter).
-This makes the project's Python coding style consistent and reduces maintenance burdens.
-Commenting a pull request with `/black` triggers the formatting action based on [`psf/Black`](https://github.com/psf/black) (this is implemented with [`slash command dispatch`](https://github.com/marketplace/actions/slash-command-dispatch)).
-
-Steps for the formatting process:
-- After submitting a pull request or push to an existing pull request,
-make a comment to the pull request to trigger the formatting action.
-The first line of the comment must be `/black` so that it will be interpreted by [the comment parser](https://github.com/marketplace/actions/slash-command-dispatch#how-are-comments-parsed-for-slash-commands).
-- [Auto] The GitHub action tries to format all Python files (using [`psf/Black`](https://github.com/psf/black)) in the branch and makes a commit under the name "MONAI bot" if there's code change. The actual formatting action is deployed at [project-monai/monai-code-formatter](https://github.com/Project-MONAI/monai-code-formatter).
-- [Auto] After the formatting commit, the GitHub action adds an emoji to the comment that triggered the process.
-- Repeat the above steps if necessary.
 
 #### Signing your work
+
 MONAI enforces the [Developer Certificate of Origin](https://developercertificate.org/) (DCO) on all pull requests.
 All commit messages should contain the `Signed-off-by` line with an email address. The [GitHub DCO app](https://github.com/apps/dco) is deployed on MONAI. The pull request's status will be `failed` if commits do not contain a valid `Signed-off-by` line.
 
 Git has a `-s` (or `--signoff`) command-line option to append this automatically to your commit message:
+
 ```bash
 git commit -s -m 'a new commit'
 ```
+
 The commit message will be:
-```
+
+```text
     a new commit
 
     Signed-off-by: Your Name <yourname@example.org>
 ```
 
 Full text of the DCO:
-```
+
+```text
 Developer Certificate of Origin
 Version 1.1
 
@@ -218,83 +191,22 @@ By making a contribution to this project, I certify that:
 ```
 
 #### Utility functions
-MONAI provides a set of generic utility functions and frequently used routines.
-These are located in [``monai/utils``](./monai/utils/) and in the module folders such as [``networks/utils.py``](./monai/networks/).
-Users are encouraged to use these common routines to improve code readability and reduce the code maintenance burdens.
 
-Notably,
-- ``monai.module.export`` decorator can make the module name shorter when importing,
-for example, ``import monai.transforms.Spacing`` is the equivalent of ``monai.transforms.spatial.array.Spacing`` if
-``class Spacing`` defined in file `monai/transforms/spatial/array.py` is decorated with ``@export("monai.transforms")``.
+MONAI provides a set of generic utility functions and frequently used routines.
+These are located in [``monai/deploy/utils``](./monai/deploy/utils/).
+Users are encouraged to use these common routines to improve code readability and reduce code maintenance burdens.
 
 For string definition, [f-string](https://www.python.org/dev/peps/pep-0498/) is recommended to use over `%-print` and `format-print` from python 3.6. So please try to use `f-string` if you need to define any string object.
 
-
 ### Submitting pull requests
-All code changes to the dev branch must be done via [pull requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests).
-1. Create a new ticket or take a known ticket from [the issue list][monai issue list].
-1. Check if there's already a branch dedicated to the task.
-1. If the task has not been taken, [create a new branch in your fork](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork)
-of the codebase named `[ticket_id]-[task_name]`.
-For example, branch name `19-ci-pipeline-setup` corresponds to [issue #19](https://github.com/Project-MONAI/MONAI/issues/19).
-Ideally, the new branch should be based on the latest `dev` branch.
-1. Make changes to the branch ([use detailed commit messages if possible](https://chris.beams.io/posts/git-commit/)).
-1. Make sure that new tests cover the changes and the changed codebase [passes all tests locally](#unit-testing).
-1. [Create a new pull request](https://help.github.com/en/desktop/contributing-to-projects/creating-a-pull-request) from the task branch to the dev branch, with detailed descriptions of the purpose of this pull request.
-1. Check [the CI/CD status of the pull request][github ci], make sure all CI/CD tests passed.
-1. Wait for reviews; if there are reviews, make point-to-point responses, make further code changes if needed.
-1. If there are conflicts between the pull request branch and the dev branch, pull the changes from the dev and resolve the conflicts locally.
-1. Reviewer and contributor may have discussions back and forth until all comments addressed.
-1. Wait for the pull request to be merged.
 
 ## The code reviewing process
 
-
 ### Reviewing pull requests
-All code review comments should be specific, constructive, and actionable.
-1. Check [the CI/CD status of the pull request][github ci], make sure all CI/CD tests passed before reviewing (contact the branch owner if needed).
-1. Read carefully the descriptions of the pull request and the files changed, write comments if needed.
-1. Make in-line comments to specific code segments, [request for changes](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-request-reviews) if needed.
-1. Review any further code changes until all comments addressed by the contributors.
-1. Comment to trigger `/black` and/or `/integration-test` for optional auto code formatting and [integration tests](.github/workflows/integration.yml).
-1. Merge the pull request to the dev branch.
-1. Close the corresponding task ticket on [the issue list][monai issue list].
-
-[github ci]: https://github.com/Project-MONAI/MONAI/actions
-[monai issue list]: https://github.com/Project-MONAI/MONAI/issues
-
 
 ## Admin tasks
 
 ### Release a new version
-The `dev` branch's `HEAD` always corresponds to MONAI docker image's latest tag: `projectmonai/monai:latest`.
-The `main` branch's `HEAD` always corresponds to the latest MONAI milestone release.
-
-When major features are ready for a milestone, to prepare for a new release:
-- Prepare [a release note](https://github.com/Project-MONAI/MONAI/releases) and release checklist.
-- Check out or cherry-pick a new branch `releasing/[version number]` locally from the `dev` branch and push to the codebase.
-- Create a release candidate tag, for example, `git tag -a 0.1.0rc1 -m "release candidate 1 of version 0.1.0"`.
-- Push the tag to the codebase, for example, `git push origin 0.1.0rc1`.
-  This step will trigger package building and testing.
-  The resultant packages are automatically uploaded to
-  [TestPyPI](https://test.pypi.org/project/monai/).  The packages are also available for downloading as
-  repository's artifacts (e.g. the file at https://github.com/Project-MONAI/MONAI/actions/runs/66570977).
-- Check the release test at [TestPyPI](https://test.pypi.org/project/monai/), download the artifacts when the CI finishes.
-- Optionally run [the cron testing jobs](https://github.com/Project-MONAI/MONAI/blob/dev/.github/workflows/cron.yml) on `releasing/[version number]`.
-- Once the release candidate is verified, tag and push a milestone, for example, `git push origin 0.1.0`.
-  The tag must be with the latest commit of `releasing/[version number]`.
-- Rebase `releasing/[version number]` to `main`, make sure all the test pipelines succeed.
-- Upload the packages to [PyPI](https://pypi.org/project/monai/).
-  This could be done manually by ``twine upload dist/*``, given the artifacts are unzipped to the folder ``dist/``.
-- Merge `releasing/[version number]` to `dev`, this step must make sure that the tagging commit unchanged on `dev`.
-- Publish the release note.
-
-Note that the release should be tagged with a [PEP440](https://www.python.org/dev/peps/pep-0440/) compliant
-[semantic versioning](https://semver.org/spec/v2.0.0.html) number.
-
-If any error occurs during the release process, first check out a new hotfix branch from the `releasing/[version number]`,
-then make PRs to the `releasing/[version number]` to fix the bugs via the regular contribution procedure.
-
-If any error occurs after the release process, first check out a new hotfix branch from the `main` branch,
-make a minor version release following the semantic versioning, for example, `releasing/0.1.1`.
-Make sure the `releasing/0.1.1` is merged back into both `dev` and `main` and all the test pipelines succeed.
+
+[github ci]: https://github.com/Project-MONAI/monai-deploy-app-sdk/actions
+[monai-app-sdk issue list]: https://github.com/Project-MONAI/monai-deploy-app-sdk/issues
diff --git a/README.md b/README.md
index 5e817304..d7974509 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,10 @@
+<p align="center">
+<img src="https://raw.githubusercontent.com/Project-MONAI/MONAI/dev/docs/images/MONAI-logo-color.png" width="50%" alt='project-monai'>
+</p>
+
 # MONAI Deploy Application SDK
 
-MONAI Deploy Application SDK offers a framework and associated tools to design, verify and analyze performance of AI-driven applications in healthcare domain.
+MONAI Deploy Application SDK offers a framework and associated tools to design, verify and analyze the performance of AI-driven applications in the healthcare domain.
 
 ## Features
 
@@ -19,11 +23,43 @@ MONAI Deploy Application SDK offers a framework and associated tools to design,
 To install [the current release](https://pypi.org/project/monai-app-sdk/), you can simply run:
 
 ```bash
-pip install monai-app-sdk
+pip install monai-app-sdk  # NOTE: monai-app-sdk package is not available in PyPI for now.
 ```
 
 ## Getting Started
 
+```bash
+pip install monai-app-sdk  # NOTE: monai-app-sdk package is not available in PyPI for now.
+
+# Clone monai-app-sdk repository for accessing examples.
+git clone https://github.com/Project-MONAI/monai-deploy-app-sdk.git
+cd monai-deploy-app-sdk
+
+# Install necessary dependencies for simple_imaging_app
+pip install scikit-image
+
+# Execute the app locally
+python examples/apps/simple_imaging_app/app.py -i examples/apps/simple_imaging_app/brain_mr_input.jpg -o output
+
+# Package app (creating MAP docker image), using `-l DEBUG` option to see progress.
+monai-deploy package examples/apps/simple_imaging_app -t simple_app:latest -l DEBUG
+
+# Run the app with docker image and input file locally
+
+# NOTES:
+# For now, we need to make sure that the output folder is available, otherwise, it would cause a permission issue.
+# - https://github.com/Project-MONAI/monai-deploy-app-sdk/issues/67
+mkdir -p output
+
+monai-deploy run simple_app:latest examples/apps/simple_imaging_app/brain_mr_input.jpg output
+```
+
+[MedNIST demo](TBD) is available on Colab.
+
+[Examples](https://github.com/Project-MONAI/monai-deploy-app-sdk/tree/main/examples) and [notebook tutorials](https://github.com/Project-MONAI/monai-deploy-app-sdk/tree/main/notebooks) are located at [Project-MONAI/monai-deploy-app-sdk](https://github.com/Project-MONAI/monai-deploy-app-sdk).
+
+Technical documentation is available at [docs.monai.io](https://docs.monai.io).
+
 ## Contributing
 
 For local development, please execute the following command:
@@ -34,8 +70,20 @@ For local development, please execute the following command:
 
 This will set up the development environment, installing necessary packages.
 
-For guidance on making a contribution to MONAI, see the [contributing guidelines](CONTRIBUTING.md).
+For guidance on making a contribution to MONAI Deploy Application SDK, see the [contributing guidelines](CONTRIBUTING.md).
 
 ## Community
 
+Join the conversation on Twitter [@ProjectMONAI](https://twitter.com/ProjectMONAI) or join our [Slack channel](https://forms.gle/QTxJq3hFictp31UM9).
+
 ## Links
+
+- Website: <https://monai.io>
+- API documentation: <https://docs.monai.io/projects/deploy>
+- Code: <https://github.com/Project-MONAI/monai-deploy-app-sdk>
+- Project tracker: <https://github.com/Project-MONAI/monai-deploy-app-sdk/projects>
+- Issue tracker: <https://github.com/Project-MONAI/monai-deploy-app-sdk/issues>
+- Wiki: <https://github.com/Project-MONAI/monai-deploy-app-sdk/wiki>
+- Test status: <https://github.com/Project-MONAI/monai-deploy-app-sdk/actions>
+- PyPI package: <https://pypi.org/project/monai-app-sdk>
+<!-- - Docker Hub: <https://hub.docker.com/r/projectmonai/monai-app-sdk> -->
diff --git a/examples/apps/ai_spleen_seg_app/__init__.py b/examples/apps/ai_spleen_seg_app/__init__.py
index fa75fd05..521cb31b 100644
--- a/examples/apps/ai_spleen_seg_app/__init__.py
+++ b/examples/apps/ai_spleen_seg_app/__init__.py
@@ -1,5 +1,6 @@
 import os
 import sys
+
 _current_dir = os.path.abspath(os.path.dirname(__file__))
 if sys.path and os.path.abspath(sys.path[0]) != _current_dir:
     sys.path.insert(0, _current_dir)
diff --git a/examples/apps/ai_spleen_seg_app/__main__.py b/examples/apps/ai_spleen_seg_app/__main__.py
index 8488b664..273444f9 100644
--- a/examples/apps/ai_spleen_seg_app/__main__.py
+++ b/examples/apps/ai_spleen_seg_app/__main__.py
@@ -1,4 +1,4 @@
 from app import AISpleenSegApp
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     AISpleenSegApp(do_run=True)
diff --git a/examples/apps/ai_spleen_seg_app/app.py b/examples/apps/ai_spleen_seg_app/app.py
index d7620d2d..fe84925a 100644
--- a/examples/apps/ai_spleen_seg_app/app.py
+++ b/examples/apps/ai_spleen_seg_app/app.py
@@ -10,12 +10,15 @@
 # limitations under the License.
 
 import logging
+
+from spleen_seg_operator import SpleenSegOperator
+
 from monai.deploy.core import Application, resource
 from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator
+from monai.deploy.operators.dicom_seg_writer_operator import DICOMSegmentationWriterOperator
 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.dicom_seg_writer_operator import DICOMSegmentationWriterOperator
-from spleen_seg_operator import SpleenSegOperator
+
 
 @resource(cpu=1, gpu=1, memory="7Gi")
 # pip_packages can be a string that is a path(str) to requirements.txt file or a list of packages.
@@ -27,22 +30,23 @@ def __init__(self, *args, **kwargs):
 
         super().__init__(*args, **kwargs)
 
-        self.logger.debug(f'App Path: {self.path}, \
+        self.logger.debug(
+            f"App Path: {self.path}, \
             Input: {self.context.input_path}, \
             Output: {self.context.output_path},\
-            Models: {self.context.model_path}'
+            Models: {self.context.model_path}"
         )
 
     def run(self):
         # This method calls the base class to run. Can be omitted if simply calling through.
-        self.logger.debug(f'Begin {self.run.__name__}')
+        self.logger.debug(f"Begin {self.run.__name__}")
         super().run()
-        self.logger.debug(f'End {self.run.__name__}')
+        self.logger.debug(f"End {self.run.__name__}")
 
     def compose(self):
         """Creates the app specific operators and chain them up in the processing DAG."""
 
-        self.logger.debug(f'Begin {self.compose.__name__}')
+        self.logger.debug(f"Begin {self.compose.__name__}")
         # Creates the custom operator(s) as well as SDK built-in operator(s).
         study_loader_op = DICOMDataLoaderOperator()
         series_selector_op = DICOMSeriesSelectorOperator()
@@ -61,7 +65,8 @@ def compose(self):
         self.add_flow(series_selector_op, dicom_seg_writer, {"dicom_series": "dicom_series"})
         self.add_flow(spleen_seg_op, dicom_seg_writer, {"seg_image": "seg_image"})
 
-        self.logger.debug(f'End {self.compose.__name__}')
+        self.logger.debug(f"End {self.compose.__name__}")
+
 
 if __name__ == "__main__":
     # Creates the app and test it standalone.
diff --git a/examples/apps/ai_spleen_seg_app/spleen_seg_operator.py b/examples/apps/ai_spleen_seg_app/spleen_seg_operator.py
index d9b5ce8a..2665769d 100644
--- a/examples/apps/ai_spleen_seg_app/spleen_seg_operator.py
+++ b/examples/apps/ai_spleen_seg_app/spleen_seg_operator.py
@@ -11,33 +11,22 @@
 
 import logging
 
+from monai.deploy.core import ExecutionContext, Image, InputContext, IOType, Operator, OutputContext, env, input, output
+from monai.deploy.operators.monai_seg_inference_operator import InMemImageReader, MonaiSegInferenceOperator
 from monai.transforms import (
     Activationsd,
     AsDiscreted,
     Compose,
+    CropForegroundd,
     EnsureChannelFirstd,
     Invertd,
     LoadImaged,
-    Spacingd,
     SaveImaged,
     ScaleIntensityRanged,
-    CropForegroundd,
-    ToTensord
-)
-
-from monai.deploy.core import (
-    ExecutionContext,
-    Image,
-    InputContext,
-    IOType,
-    Operator,
-    OutputContext,
-    input,
-    output,
-    env
+    Spacingd,
+    ToTensord,
 )
 
-from monai.deploy.operators.monai_seg_inference_operator import MonaiSegInferenceOperator, InMemImageReader
 
 @input("image", Image, IOType.IN_MEMORY)
 @output("seg_image", Image, IOType.IN_MEMORY)
@@ -51,7 +40,8 @@ class SpleenSegOperator(Operator):
     This derived reader is needed to parse the in memory image object, and return the expected data structure.
     Loading of the model, and predicting using in-proc PyTorch inference is done by MonaiSegInferenceOperator.
     """
-    def __init__(self, testing:bool =False):
+
+    def __init__(self, testing: bool = False):
         self.logger = logging.getLogger("{}.{}".format(__name__, type(self).__name__))
         super().__init__()
         self.testing = testing
@@ -62,7 +52,7 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
 
         input_image = input.get("image")
         if not input_image:
-            raise ValueError('Input image is not found.')
+            raise ValueError("Input image is not found.")
 
         if self.testing:
             seg_image = self.infer_and_save(input_image)
@@ -75,9 +65,14 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
 
             # Delegates inference and saving output to the built-in operator.
             infer_operator = MonaiSegInferenceOperator(
-                (160, 160, 160,),
+                (
+                    160,
+                    160,
+                    160,
+                ),
                 pre_transforms,
-                post_transforms)
+                post_transforms,
+            )
 
             # Setting the keys used in the dictironary based transforms may change.
             infer_operator.input_dataset_key = self._input_dataset_key
@@ -87,41 +82,37 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
             infer_operator.compute(input, output, context)
 
     def pre_process(self, img_reader) -> Compose:
-        """Composes transforms for preprocessing input before predicting on a model.
-        """
+        """Composes transforms for preprocessing input before predicting on a model."""
 
         my_key = self._input_dataset_key
-        return Compose([
-            LoadImaged(keys=my_key, reader=img_reader),
-            EnsureChannelFirstd(keys=my_key),
-            Spacingd(keys=my_key, pixdim=[1.0, 1.0, 1.0], mode=["blinear"], align_corners=True),
-            ScaleIntensityRanged(keys=my_key, a_min=-57, a_max=164, b_min=0.0, b_max=1.0, clip=True),
-            CropForegroundd(keys=my_key, source_key=my_key),
-            ToTensord(keys=my_key)
-        ])
-
-    def post_process(self, pre_transforms: Compose, out_dir:str="./infer_output") -> Compose:
+        return Compose(
+            [
+                LoadImaged(keys=my_key, reader=img_reader),
+                EnsureChannelFirstd(keys=my_key),
+                Spacingd(keys=my_key, pixdim=[1.0, 1.0, 1.0], mode=["blinear"], align_corners=True),
+                ScaleIntensityRanged(keys=my_key, a_min=-57, a_max=164, b_min=0.0, b_max=1.0, clip=True),
+                CropForegroundd(keys=my_key, source_key=my_key),
+                ToTensord(keys=my_key),
+            ]
+        )
+
+    def post_process(self, pre_transforms: Compose, out_dir: str = "./infer_output") -> Compose:
         """Composes transforms for postprocessing the prediction results."""
 
         pred_key = self._pred_dataset_key
-        return Compose([
-            Activationsd(keys=pred_key, softmax=True),
-            AsDiscreted(keys=pred_key, argmax=True),
-            Invertd(
-                keys=pred_key,
-                transform = pre_transforms,
-                orig_keys=self._input_dataset_key,
-                nearest_interp=True
-            ),
-            SaveImaged(keys=pred_key,
-                output_dir=out_dir,
-                output_postfix="seg",
-                resample=False)
-        ])
+        return Compose(
+            [
+                Activationsd(keys=pred_key, softmax=True),
+                AsDiscreted(keys=pred_key, argmax=True),
+                Invertd(
+                    keys=pred_key, transform=pre_transforms, orig_keys=self._input_dataset_key, nearest_interp=True
+                ),
+                SaveImaged(keys=pred_key, output_dir=out_dir, output_postfix="seg", resample=False),
+            ]
+        )
 
     def infer_and_save(self, image):
-        """Prints out the image obj, and bounce it back, for testing only.
-        """
+        """Prints out the image obj, and bounce it back, for testing only."""
 
         image_data = image.asnumpy()
         image_shape = image_data.shape
diff --git a/examples/apps/dicom_series_to_image_app/__init__.py b/examples/apps/dicom_series_to_image_app/__init__.py
index fa75fd05..521cb31b 100644
--- a/examples/apps/dicom_series_to_image_app/__init__.py
+++ b/examples/apps/dicom_series_to_image_app/__init__.py
@@ -1,5 +1,6 @@
 import os
 import sys
+
 _current_dir = os.path.abspath(os.path.dirname(__file__))
 if sys.path and os.path.abspath(sys.path[0]) != _current_dir:
     sys.path.insert(0, _current_dir)
diff --git a/examples/apps/dicom_series_to_image_app/__main__.py b/examples/apps/dicom_series_to_image_app/__main__.py
index bea0e18d..412a8ca1 100644
--- a/examples/apps/dicom_series_to_image_app/__main__.py
+++ b/examples/apps/dicom_series_to_image_app/__main__.py
@@ -1,4 +1,4 @@
 from app import App
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     App(do_run=True)
diff --git a/examples/apps/dicom_series_to_image_app/app.py b/examples/apps/dicom_series_to_image_app/app.py
index 34b7aae9..1fc0ddc2 100644
--- a/examples/apps/dicom_series_to_image_app/app.py
+++ b/examples/apps/dicom_series_to_image_app/app.py
@@ -18,7 +18,6 @@
 
 
 class App(Application):
-
     def compose(self):
         study_loader_op = DICOMDataLoaderOperator()
         series_selector_op = DICOMSeriesSelectorOperator()
diff --git a/examples/apps/simple_imaging_app/__init__.py b/examples/apps/simple_imaging_app/__init__.py
index fa75fd05..521cb31b 100644
--- a/examples/apps/simple_imaging_app/__init__.py
+++ b/examples/apps/simple_imaging_app/__init__.py
@@ -1,5 +1,6 @@
 import os
 import sys
+
 _current_dir = os.path.abspath(os.path.dirname(__file__))
 if sys.path and os.path.abspath(sys.path[0]) != _current_dir:
     sys.path.insert(0, _current_dir)
diff --git a/examples/apps/simple_imaging_app/__main__.py b/examples/apps/simple_imaging_app/__main__.py
index bea0e18d..412a8ca1 100644
--- a/examples/apps/simple_imaging_app/__main__.py
+++ b/examples/apps/simple_imaging_app/__main__.py
@@ -1,4 +1,4 @@
 from app import App
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     App(do_run=True)
diff --git a/examples/apps/simple_imaging_app/median_operator.py b/examples/apps/simple_imaging_app/median_operator.py
index 650aa941..d5cbcc7e 100644
--- a/examples/apps/simple_imaging_app/median_operator.py
+++ b/examples/apps/simple_imaging_app/median_operator.py
@@ -49,7 +49,6 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
 
         # `context.input.get().path` (Path) is the file/folder path of the input data from the application's context.
         # `context.output.get().path` (Path) is the file/folder path of the output data from the application's context.
-
         # `context.models.get(model_name)` returns a model instance
         #  (a null model would be returned if model is not available)
         # If model_name is not specified and only one model exists, it returns that model.
diff --git a/monai/deploy/__init__.py b/monai/deploy/__init__.py
index ecd3379a..28a88b97 100644
--- a/monai/deploy/__init__.py
+++ b/monai/deploy/__init__.py
@@ -1,3 +1,14 @@
+# Copyright 2021 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.
 
 from . import _version
-__version__ = _version.get_versions()['version']
+
+__version__ = _version.get_versions()["version"]
diff --git a/monai/deploy/cli/__init__.py b/monai/deploy/cli/__init__.py
index c28a133f..26c54045 100644
--- a/monai/deploy/cli/__init__.py
+++ b/monai/deploy/cli/__init__.py
@@ -1,1 +1,18 @@
-from .main import main
+# Copyright 2021 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 os
+import sys
+
+_current_dir = os.path.abspath(os.path.dirname(__file__))
+if sys.path and os.path.abspath(sys.path[0]) != _current_dir:
+    sys.path.insert(0, _current_dir)
+del _current_dir
diff --git a/monai/deploy/cli/__main__.py b/monai/deploy/cli/__main__.py
index 14928d69..1fcbe7c6 100644
--- a/monai/deploy/cli/__main__.py
+++ b/monai/deploy/cli/__main__.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -10,7 +10,7 @@
 # limitations under the License.
 
 
-from . import main
+from main import main
 
 if __name__ == "__main__":
-    main.main()
+    main()
diff --git a/monai/deploy/core/application.py b/monai/deploy/core/application.py
index afc2a1b9..19c1962d 100644
--- a/monai/deploy/core/application.py
+++ b/monai/deploy/core/application.py
@@ -53,7 +53,7 @@ class Application(ABC):
     # This is needed to identify Application class across different environments (e.g. by `runpy.run_path()`).
     _class_id: str = "monai.application"
 
-    _env: "ApplicationEnv" = None
+    _env: Optional["ApplicationEnv"] = None
 
     def __init__(
         self,
@@ -179,7 +179,7 @@ def add_operator(self, operator: Operator):
         self._graph.add_operator(operator)
 
     def add_flow(
-        self, upstream_op: Operator, downstream_op: Operator, io_map: Optional[Dict[str, Union[str, Set]]] = None
+        self, upstream_op: Operator, downstream_op: Operator, io_map: Optional[Dict[str, Union[str, Set[str]]]] = None
     ):
         """Adds a flow from upstream to downstream.
 
@@ -189,8 +189,8 @@ def add_flow(
         Args:
             upstream_op (Operator): An instance of the upstream operator of type Operator.
             downstream_op (Operator): An instance of the downstream operator of type Operator.
-            io_map (Optional[Dict[str, str]]): A dictionary of mapping from the source operator's label to the
-                                               destination operator's label.
+            io_map (Optional[Dict[str, Union[str, Set[str]]]]): A dictionary of mapping from the source operator's label
+                                                                 to the destination operator's label(s).
         """
 
         # Ensure that the upstream and downstream operators are valid
@@ -213,12 +213,13 @@ def add_flow(
             io_map = {"": {""}}
 
         # Convert io_map's values to the set of strings.
+        io_maps: Dict[str, Set[str]] = io_map  # type: ignore
         for k, v in io_map.items():
             if isinstance(v, str):
-                io_map[k] = {v}
+                io_maps[k] = {v}
 
         # Verify that the upstream & downstream operator have the input and output ports specified by the io_map
-        output_labels = list(io_map.keys())
+        output_labels = list(io_maps.keys())
 
         if len(op_output_labels) == 1 and len(output_labels) != 1:
             raise IOMappingError(
@@ -231,17 +232,17 @@ def add_flow(
             if output_label not in op_output_labels:
                 if len(op_output_labels) == 1 and len(output_labels) == 1 and output_label == "":
                     # Set the default output port label.
-                    io_map[next(iter(op_output_labels))] = io_map[output_label]
-                    del io_map[output_label]
+                    io_maps[next(iter(op_output_labels))] = io_maps[output_label]
+                    del io_maps[output_label]
                     break
                 raise IOMappingError(
                     f"The upstream operator({upstream_op.name}) has no output port with label '{output_label}'. "
                     f"It should be one of ({', '.join(op_output_labels)})."
                 )
 
-        output_labels = list(io_map.keys())  # re-evaluate output_labels
+        output_labels = list(io_maps.keys())  # re-evaluate output_labels
         for output_label in output_labels:
-            input_labels = io_map[output_label]
+            input_labels = io_maps[output_label]
 
             if len(op_input_labels) == 1 and len(input_labels) != 1:
                 raise IOMappingError(
@@ -262,7 +263,7 @@ def add_flow(
                         f"It should be one of ({', '.join(op_input_labels)})."
                     )
 
-        self._graph.add_flow(upstream_op, downstream_op, io_map)
+        self._graph.add_flow(upstream_op, downstream_op, io_maps)
 
     def get_package_info(self, model_path: Union[str, Path] = "") -> Dict:
         """Returns the package information of this application.
diff --git a/monai/deploy/core/datastores/memory.py b/monai/deploy/core/datastores/memory.py
index a282badb..fd7c78df 100644
--- a/monai/deploy/core/datastores/memory.py
+++ b/monai/deploy/core/datastores/memory.py
@@ -1,10 +1,21 @@
+# Copyright 2021 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.
+
 from typing import Any, Dict, Hashable, KeysView, Optional
 
 from .datastore import Datastore
 
 
 class MemoryDatastore(Datastore):
-    def __init__(self):
+    def __init__(self, **kwargs: Dict):
         self._storage: Dict = {}
 
     def get(self, key: Hashable, def_val: Optional[Any] = None) -> Any:
diff --git a/monai/deploy/core/domain/dicom_series.py b/monai/deploy/core/domain/dicom_series.py
index 20e39eba..e303782b 100644
--- a/monai/deploy/core/domain/dicom_series.py
+++ b/monai/deploy/core/domain/dicom_series.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -9,8 +9,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
-import math
 from .dicom_sop_instance import DICOMSOPInstance
 from .domain import Domain
 
diff --git a/monai/deploy/core/domain/dicom_study.py b/monai/deploy/core/domain/dicom_study.py
index 5729be22..eda07e54 100644
--- a/monai/deploy/core/domain/dicom_study.py
+++ b/monai/deploy/core/domain/dicom_study.py
@@ -10,7 +10,6 @@
 # limitations under the License.
 
 
-from .dicom_series import DICOMSeries
 from .domain import Domain
 
 
diff --git a/monai/deploy/core/domain/image.py b/monai/deploy/core/domain/image.py
index 1de9f77e..4688d211 100644
--- a/monai/deploy/core/domain/image.py
+++ b/monai/deploy/core/domain/image.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -12,7 +12,7 @@
 from typing import Any, Dict, Optional, Union
 
 try:
-    from numpy.typing import ArrayLike
+    from numpy.typing import ArrayLike  # type: ignore
 except ImportError:
     ArrayLike = Any
 
diff --git a/monai/deploy/core/execution_context.py b/monai/deploy/core/execution_context.py
index 0cf4b8c1..66b6df71 100644
--- a/monai/deploy/core/execution_context.py
+++ b/monai/deploy/core/execution_context.py
@@ -17,7 +17,6 @@
     from .operator import Operator
 
 from .datastores import Datastore, MemoryDatastore
-from .domain import NamedDataPath
 from .io_context import InputContext, OutputContext
 from .models import Model
 
@@ -42,7 +41,7 @@ def __init__(
         models: Optional[Model] = None,
     ):
         if datastore is None:
-            self._storage = MemoryDatastore()
+            self._storage: Datastore = MemoryDatastore()
         else:
             self._storage = datastore
 
diff --git a/monai/deploy/core/executors/executor.py b/monai/deploy/core/executors/executor.py
index 6e4c33de..04d93725 100644
--- a/monai/deploy/core/executors/executor.py
+++ b/monai/deploy/core/executors/executor.py
@@ -10,7 +10,7 @@
 # limitations under the License.
 
 from abc import ABC, abstractmethod
-from typing import TYPE_CHECKING, Optional
+from typing import TYPE_CHECKING, Dict, Optional
 
 if TYPE_CHECKING:
     from monai.deploy.core import Application
@@ -21,7 +21,7 @@
 class Executor(ABC):
     """This is the base class that enables execution of an application."""
 
-    def __init__(self, app: "Application", datastore: Optional[Datastore] = None):
+    def __init__(self, app: "Application", datastore: Optional[Datastore] = None, **kwargs: Dict):
         """Constructor of the class.
 
         Given an application it invokes the compose method on the app, which
diff --git a/monai/deploy/core/graphs/graph.py b/monai/deploy/core/graphs/graph.py
index 0ce8d660..c8ab012b 100644
--- a/monai/deploy/core/graphs/graph.py
+++ b/monai/deploy/core/graphs/graph.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -10,7 +10,7 @@
 # limitations under the License.
 
 from abc import ABC, abstractmethod
-from typing import Dict, Generator, Optional
+from typing import Dict, Generator, Optional, Set
 
 from monai.deploy.core.operator import Operator
 
@@ -24,24 +24,26 @@ def add_operator(self, op: Operator):
         pass
 
     @abstractmethod
-    def add_flow(self, op_u: Operator, op_v: Operator, io_map: Dict[str, str]):
+    def add_flow(self, op_u: Operator, op_v: Operator, io_map: Dict[str, Set[str]]):
         """Add an edge to the graph.
 
         Args:
             op_u (Operator): A source operator.
             op_v (Operator): A destination operator.
-            io_map (Dict[str, str]): A dictionary of mapping from the source operator's label to the destination operator's label.
+            io_map (Dict[str, Set[str]]): A dictionary of mapping from the source operator's label to the destination
+                                          operator's label(s).
         """
         pass
 
     @abstractmethod
-    def get_io_map(self, op_u: Operator, op_v) -> Dict[str, str]:
+    def get_io_map(self, op_u: Operator, op_v) -> Dict[str, Set[str]]:
         """Get a mapping from the source operator's output label to the destination operator's input label.
         Args:
             op_u (Operator): A source operator.
             op_v (Operator): A destination operator.
         Returns:
-            A dictionary of mapping from the source operator's output label to the destination operator's input label.
+            A dictionary of mapping from the source operator's output label to the destination operator's
+            input label(s).
         """
         pass
 
diff --git a/monai/deploy/core/graphs/nx_digraph.py b/monai/deploy/core/graphs/nx_digraph.py
index 4bbb8cd7..34397b12 100644
--- a/monai/deploy/core/graphs/nx_digraph.py
+++ b/monai/deploy/core/graphs/nx_digraph.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -9,7 +9,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from typing import Dict, Generator, Optional
+from typing import Dict, Generator, Optional, Set
 
 import networkx as nx
 from networkx.algorithms.dag import topological_sort
@@ -22,24 +22,24 @@
 class NetworkXGraph(Graph):
     """NetworkX graph implementation."""
 
-    def __init__(self):
+    def __init__(self, **kwargs: Dict):
         self._graph = nx.DiGraph()
 
     def add_operator(self, op: Operator):
         self._graph.add_node(op)
 
-    def add_flow(self, op_u: Operator, op_v: Operator, io_map: Dict[str, str]):
+    def add_flow(self, op_u: Operator, op_v: Operator, io_map: Dict[str, Set[str]]):
         self._graph.add_edge(op_u, op_v, io_map=io_map)
 
-    def get_io_map(self, op_u: Operator, op_v) -> Dict[str, str]:
-        io_map = self._graph.get_edge_data(op_u, op_v).get("io_map")
+    def get_io_map(self, op_u: Operator, op_v) -> Dict[str, Set[str]]:
+        io_map: Dict[str, Set[str]] = self._graph.get_edge_data(op_u, op_v).get("io_map")
         return io_map
 
     def is_root(self, op: Operator) -> bool:
-        return self._graph.in_degree(op) == 0
+        return bool(self._graph.in_degree(op) == 0)
 
     def is_leaf(self, op: Operator) -> bool:
-        return self._graph.out_degree(op) == 0
+        return bool(self._graph.out_degree(op) == 0)
 
     def get_root_operators(self) -> Generator[Operator, None, None]:
         return (op for (op, degree) in self._graph.in_degree() if degree == 0)
@@ -48,7 +48,8 @@ def get_operators(self) -> Generator[Operator, None, None]:
         return (op for op in self._graph.nodes())
 
     def gen_worklist(self) -> Generator[Optional[Operator], None, None]:
-        return topological_sort(self._graph)
+        worklist: Generator[Optional[Operator], None, None] = topological_sort(self._graph)
+        return worklist
 
     def gen_next_operators(self, op: Operator) -> Generator[Optional[Operator], None, None]:
         for (_, v) in self._graph.out_edges(op):
diff --git a/monai/deploy/core/io_context.py b/monai/deploy/core/io_context.py
index 05b66038..06b09dca 100644
--- a/monai/deploy/core/io_context.py
+++ b/monai/deploy/core/io_context.py
@@ -10,7 +10,7 @@
 # limitations under the License.
 
 from abc import ABC
-from typing import TYPE_CHECKING, Any
+from typing import TYPE_CHECKING, Any, Set
 
 if TYPE_CHECKING:
     from .execution_context import ExecutionContext
@@ -33,7 +33,7 @@ def __init__(self, execution_context: "ExecutionContext"):
         self._execution_context: "ExecutionContext" = execution_context
         self._op: Operator = execution_context.op
         self._op_info: OperatorInfo = self._op.op_info
-        self._labels: str = self._op_info.get_labels(self._io_kind)
+        self._labels: Set[str] = self._op_info.get_labels(self._io_kind)
         self._storage: Datastore = execution_context.storage
 
     def get_default_label(self, label: str = "") -> str:
diff --git a/monai/deploy/core/models/__init__.py b/monai/deploy/core/models/__init__.py
index a3b2603e..aff38e70 100644
--- a/monai/deploy/core/models/__init__.py
+++ b/monai/deploy/core/models/__init__.py
@@ -1,7 +1,18 @@
+# Copyright 2021 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.
+
 from .factory import ModelFactory
 from .model import Model
-from .torch_model import TorchScriptModel
 from .named_model import NamedModel
+from .torch_model import TorchScriptModel
 from .triton_model import TritonModel
 
 Model.register([TritonModel, NamedModel, TorchScriptModel, Model])
diff --git a/monai/deploy/core/models/factory.py b/monai/deploy/core/models/factory.py
index 04b67031..e6596e31 100644
--- a/monai/deploy/core/models/factory.py
+++ b/monai/deploy/core/models/factory.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -19,32 +19,32 @@ class ModelFactory:
     """ModelFactory is a class that provides a way to create a model object."""
 
     @staticmethod
-    def create(path: Union[str, Path], name: str = "", model_type: Optional[str] = None) -> Model:
+    def create(path: Union[str, Path], name: str = "", model_type: str = "") -> Optional[Model]:
         """Creates a model object.
 
         Args:
             path (Union[str, Path]): A path to the model.
             name (str): A name of the model.
-            model_type (Optional[str]): A type of the model.
+            model_type (str): A type of the model.
 
         Returns:
             A model object. Returns None if the model file/folder does not exist.
         """
         model_type, model_cls = ModelFactory.detect_model_type(path, model_type)
 
-        if model_type:
+        if model_type and model_cls:
             model = model_cls(str(path), name)
             return model
         else:
             return None
 
     @staticmethod
-    def detect_model_type(path: Union[str, Path], model_type: Optional[str] = None) -> Tuple[str, Type[Model]]:
+    def detect_model_type(path: Union[str, Path], model_type: str = "") -> Tuple[str, Optional[Type[Model]]]:
         """Detects the model type based on a model path.
 
         Args:
             path (Union[str, Path]): A path to the model file/folder.
-            model_type (Optional[str]): A model type.
+            model_type (str): A model type.
 
         Returns:
             A tuple of the model type string and the model class.
diff --git a/monai/deploy/core/models/model.py b/monai/deploy/core/models/model.py
index 63ea7a20..e6501f67 100644
--- a/monai/deploy/core/models/model.py
+++ b/monai/deploy/core/models/model.py
@@ -138,10 +138,10 @@ def accept(cls, path: str) -> Tuple[bool, str]:
             path (str): A path to a model.
 
         Returns:
-            (True, <model_type>) if the path is a type of this model class, (False, None) otherwise.
+            (True, <model_type>) if the path is a type of this model class, (False, "") otherwise.
         """
         if not os.path.exists(path):
-            return False, None
+            return False, ""
         return True, cls.model_type
 
     def get(self, name: str = "") -> "Model":
@@ -176,7 +176,7 @@ def get(self, name: str = "") -> "Model":
             else:
                 return self
 
-    def get_model_list(self) -> List[str]:
+    def get_model_list(self) -> List[Dict[str, str]]:
         """Return a list of models in the repository.
 
         If this model represents a model repository, then a list of model objects (name and path) is returned.
diff --git a/monai/deploy/core/models/named_model.py b/monai/deploy/core/models/named_model.py
index 2f34fd3c..948522cb 100644
--- a/monai/deploy/core/models/named_model.py
+++ b/monai/deploy/core/models/named_model.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -9,17 +9,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import logging
 from pathlib import Path
 
 from monai.deploy.core.models import ModelFactory
 
 from .model import Model
 
-import logging
-
-
 logger = logging.getLogger(__name__)
 
+
 class NamedModel(Model):
     """Represents named models in the model repository.
 
@@ -55,9 +54,9 @@ def __init__(self, path: str, name: str = ""):
 
         # Clear existing model item and fill model items
         self._items.clear()
-        path: Path = Path(path)
+        model_path: Path = Path(path)
 
-        for model_folder in path.iterdir():
+        for model_folder in model_path.iterdir():
             if model_folder.is_dir():
                 # Pick one file (assume that only one file exists in the folder)
                 model_file = next(model_folder.iterdir())
@@ -65,25 +64,28 @@ def __init__(self, path: str, name: str = ""):
                     # Recursive call to identify the model type
                     model = ModelFactory.create(str(model_file), model_folder.name)
                     # Add model to items only if the model's class is not 'Model'
-                    if model.__class__ != Model:
+                    if model and model.__class__ != Model:
                         self._items[model_folder.name] = model
 
     @classmethod
     def accept(cls, path: str):
-        path: Path = Path(path)
+        model_path: Path = Path(path)
 
         # 1) The path should be a folder path.
-        if not path.is_dir():
+        if not model_path.is_dir():
             return False, None
 
         # 2) The folder should contain only sub folders (model folders).
-        if not all((p.is_dir() for p in path.iterdir())):
+        if not all((p.is_dir() for p in model_path.iterdir())):
             return False, None
 
-        for model_folder in path.iterdir():
+        for model_folder in model_path.iterdir():
             # 3) Each model folder must contain only one model definition file or folder.
             if sum(1 for _ in model_folder.iterdir()) != 1:
-                logger.warning(f"Model repository '{model_folder}' contains more than one model definition file or folder so not treated as NamedModel.")
+                logger.warning(
+                    f"Model repository '{model_folder}' contains more than one model definition file or folder "
+                    "so not treated as NamedModel."
+                )
                 return False, None
 
         return True, cls.model_type
diff --git a/monai/deploy/core/models/torch_model.py b/monai/deploy/core/models/torch_model.py
index 12709da8..bc390938 100644
--- a/monai/deploy/core/models/torch_model.py
+++ b/monai/deploy/core/models/torch_model.py
@@ -37,7 +37,7 @@ class TorchScriptModel(Model):
     model_type: str = "torch_script"
 
     @property
-    def predictor(self) -> "torch.nn.Module":
+    def predictor(self) -> "torch.nn.Module":  # type: ignore
         """Get the model's predictor (torch.nn.Module)
 
         If the predictor is not loaded, load it from the model file in evaluation mode.
diff --git a/monai/deploy/core/models/triton_model.py b/monai/deploy/core/models/triton_model.py
index 17d791ec..a82d476d 100644
--- a/monai/deploy/core/models/triton_model.py
+++ b/monai/deploy/core/models/triton_model.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -68,26 +68,26 @@ def __init__(self, path: str, name: str = ""):
 
         # Clear existing model item and fill model items
         self._items.clear()
-        path: Path = Path(path)
+        model_path: Path = Path(path)
 
-        for model_folder in path.iterdir():
+        for model_folder in model_path.iterdir():
             if model_folder.is_dir():
                 self._items[model_folder.name] = Model(str(model_folder), model_folder.name)
 
     @classmethod
     def accept(cls, path: str):
-        path: Path = Path(path)
+        model_path: Path = Path(path)
 
         # 1) The path should be a folder path.
-        if not path.is_dir():
+        if not model_path.is_dir():
             return False, None
 
         # 2) The directory should contain only sub folders (model folders).
-        if not all((p.is_dir() for p in path.iterdir())):
+        if not all((p.is_dir() for p in model_path.iterdir())):
             return False, None
 
         is_triton_model_repository = True
-        for model_folder in path.iterdir():
+        for model_folder in model_path.iterdir():
             # 3) Each model folder must contain a config.pbtxt file.
             if not (model_folder / "config.pbtxt").exists():
                 return False, None
diff --git a/monai/deploy/core/operator.py b/monai/deploy/core/operator.py
index 2072846e..8a9faa7f 100644
--- a/monai/deploy/core/operator.py
+++ b/monai/deploy/core/operator.py
@@ -11,7 +11,7 @@
 
 import uuid
 from abc import ABC, abstractmethod
-from typing import Any, Type, Union
+from typing import Optional, Type, Union
 
 from monai.deploy.exceptions import UnknownTypeError
 from monai.deploy.utils.importutil import is_subclass
@@ -38,7 +38,7 @@ class Operator(ABC):
     # This is needed to identify Operator class across different environments (e.g. by `runpy.run_path()`).
     _class_id: str = "monai.operator"
 
-    _env: "OperatorEnv" = None
+    _env: Optional["OperatorEnv"] = None
 
     def __init__(self, *args, **kwargs):
         """Constructor of the base operator.
@@ -47,8 +47,8 @@ def __init__(self, *args, **kwargs):
         to all inputs and outputs relavant for this operator.
         """
         super().__init__()
-        self._uid = uuid.uuid4()
-        self._op_info = OperatorInfo()
+        self._uid: uuid.UUID = uuid.uuid4()
+        self._op_info: OperatorInfo = OperatorInfo()
 
         # Execute the builder to set up the operator
         self._builder()
@@ -216,7 +216,7 @@ def post_compute(self):
         pass
 
 
-def input(label: str = "", data_type: Type = Any, storage_type: Union[int, IOType] = IOType.UNKNOWN):
+def input(label: str = "", data_type: Type = object, storage_type: Union[int, IOType] = IOType.UNKNOWN):
     """A decorator that adds input specification to the operator.
 
     Args:
@@ -247,7 +247,7 @@ def new_builder(self: Operator):
     return decorator
 
 
-def output(label: str = "", data_type: Type = Any, storage_type: Union[int, IOType] = IOType.UNKNOWN):
+def output(label: str = "", data_type: Type = object, storage_type: Union[int, IOType] = IOType.UNKNOWN):
     """A decorator that adds output specification to the operator.
 
     Args:
diff --git a/monai/deploy/core/operator_info.py b/monai/deploy/core/operator_info.py
index 809e6623..9f0a001e 100644
--- a/monai/deploy/core/operator_info.py
+++ b/monai/deploy/core/operator_info.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -17,6 +17,7 @@
 
 
 class IO(Enum):
+    UNDEFINED = "undefined"
     INPUT = "input"
     OUTPUT = "output"
 
@@ -29,7 +30,7 @@ class OperatorInfo:
 
     def __init__(self):
         # Initializing the attributes
-        self.labels: Dict[IO, Set] = {IO.INPUT: set(), IO.OUTPUT: set()}
+        self.labels: Dict[IO, Set[str]] = {IO.INPUT: set(), IO.OUTPUT: set()}
         self.data_type: Dict[IO, Dict[str, Type]] = {IO.INPUT: {}, IO.OUTPUT: {}}
         self.storage_type: Dict[IO, Dict[str, IOType]] = {IO.INPUT: {}, IO.OUTPUT: {}}
 
@@ -44,26 +45,26 @@ def ensure_valid(self):
                 self.data_type[kind][""] = DataPath
                 self.storage_type[kind][""] = IOType.DISK
 
-    def add_label(self, io_kind: IO, label: str):
+    def add_label(self, io_kind: Union[IO, str], label: str):
         io_kind = IO(io_kind)
         self.labels[io_kind].add(label)
 
-    def get_labels(self, io_kind: IO) -> str:
+    def get_labels(self, io_kind: Union[IO, str]) -> Set[str]:
         io_kind = IO(io_kind)
         return self.labels[io_kind]
 
-    def set_data_type(self, io_kind: IO, label: str, data_type: Type):
+    def set_data_type(self, io_kind: Union[IO, str], label: str, data_type: Type):
         io_kind = IO(io_kind)
         self.data_type[io_kind][label] = data_type
 
-    def get_data_type(self, io_kind: IO, label: str) -> Type:
+    def get_data_type(self, io_kind: Union[IO, str], label: str) -> Type:
         io_kind = IO(io_kind)
         return self.data_type[io_kind][label]
 
-    def set_storage_type(self, io_kind: IO, label: str, storage_type: Union[int, IOType]):
+    def set_storage_type(self, io_kind: Union[IO, str], label: str, storage_type: Union[int, IOType]):
         io_kind = IO(io_kind)
         self.storage_type[io_kind][label] = IOType(storage_type)
 
-    def get_storage_type(self, io_kind: IO, label: str) -> IOType:
+    def get_storage_type(self, io_kind: Union[IO, str], label: str) -> IOType:
         io_kind = IO(io_kind)
         return self.storage_type[io_kind][label]
diff --git a/monai/deploy/core/resource.py b/monai/deploy/core/resource.py
index 9705e722..d14d9f6f 100644
--- a/monai/deploy/core/resource.py
+++ b/monai/deploy/core/resource.py
@@ -79,16 +79,17 @@ def set_resource_limits(
             try:
                 self._memory = get_bytes(memory_limit)
             except Exception as e:
-                raise WrongValueError(f"Memory size specified in the application (via @resource) is not valid: {e.args[0]}")
-        else:
-            if memory_limit is not None:
-                if self._memory is None:
-                    self._memory = memory_limit
-                else:
-                    raise ItemAlreadyExistsError(
-                        f"'memory' wouldn't be set to {memory_limit} because it is already set to {self._memory}"
-                        " by the runtime environment."
-                    )
+                raise WrongValueError(
+                    f"Memory size specified in the application (via @resource) is not valid: {e.args[0]}"
+                )
+        elif type(memory_limit) == int:
+            if self._memory is None:
+                self._memory = memory_limit
+            else:
+                raise ItemAlreadyExistsError(
+                    f"'memory' wouldn't be set to {memory_limit} because it is already set to {self._memory}"
+                    " by the runtime environment."
+                )
 
     def __str__(self):
         return "Resource(cpu={}, memory={}, gpu={})".format(self.cpu, self.memory, self.gpu)
@@ -130,6 +131,7 @@ def new_builder(self: Application):
                 builder(self)  # execute the original builder
 
             return self
+
         cls._builder = new_builder
         return cls
 
diff --git a/monai/deploy/core/runtime_env.py b/monai/deploy/core/runtime_env.py
index e8f2ecec..63ef1670 100644
--- a/monai/deploy/core/runtime_env.py
+++ b/monai/deploy/core/runtime_env.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -11,7 +11,7 @@
 
 import os
 from abc import ABC
-from typing import Dict, Tuple
+from typing import Dict, Optional, Tuple
 
 from monai.deploy.core.datastores.factory import DatastoreFactory
 from monai.deploy.core.executors.factory import ExecutorFactory
@@ -25,7 +25,7 @@ class RuntimeEnv(ABC):
     and they can be set to override the defaults.
     """
 
-    ENV_DEFAULT = {
+    ENV_DEFAULT: Dict[str, Tuple[str, ...]] = {
         "input": ("MONAI_INPUTPATH", "input"),
         "output": ("MONAI_OUTPUTPATH", "output"),
         "model": ("MONAI_MODELPATH", "models"),
@@ -39,8 +39,11 @@ class RuntimeEnv(ABC):
     output: str = ""
     model: str = ""
     workdir: str = ""
+    graph: str = ""
+    datastore: str = ""
+    executor: str = ""
 
-    def __init__(self, defaults: Dict[str, Tuple[str]] = None):
+    def __init__(self, defaults: Optional[Dict[str, Tuple[str, ...]]] = None):
         if defaults is None:
             defaults = self.ENV_DEFAULT
         for key, (env, default) in defaults.items():
diff --git a/monai/deploy/exceptions.py b/monai/deploy/exceptions.py
index 8b6694f3..26c9c1b3 100644
--- a/monai/deploy/exceptions.py
+++ b/monai/deploy/exceptions.py
@@ -39,11 +39,13 @@ class UnknownTypeError(MONAIAppSdkError):
 
     pass
 
+
 class WrongValueError(MONAIAppSdkError):
     """Raises when wrong value is specified."""
 
     pass
 
+
 class UnsupportedOperationError(MONAIAppSdkError):
     """Raises when unsupported operation is requested."""
 
diff --git a/monai/deploy/operators/dicom_data_loader_operator.py b/monai/deploy/operators/dicom_data_loader_operator.py
index 27419951..5b24dc52 100644
--- a/monai/deploy/operators/dicom_data_loader_operator.py
+++ b/monai/deploy/operators/dicom_data_loader_operator.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -18,9 +18,9 @@
     IOType,
     Operator,
     OutputContext,
+    env,
     input,
     output,
-    env
 )
 from monai.deploy.core.domain.dicom_series import DICOMSeries
 from monai.deploy.core.domain.dicom_study import DICOMStudy
diff --git a/monai/deploy/operators/dicom_seg_writer_operator.py b/monai/deploy/operators/dicom_seg_writer_operator.py
index fab958bb..e710a126 100644
--- a/monai/deploy/operators/dicom_seg_writer_operator.py
+++ b/monai/deploy/operators/dicom_seg_writer_operator.py
@@ -9,15 +9,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os
-import logging
-import json
 import copy
-import numpy as np
 import datetime
+import json
+import logging
+import os
 from random import randint
 from typing import List, Union
 
+import numpy as np
+
 from monai.deploy.utils.importutil import optional_import
 from monai.deploy.utils.version import get_sdk_semver
 
@@ -37,15 +38,15 @@
     IOType,
     Operator,
     OutputContext,
+    env,
     input,
     output,
-    env
 )
-
 from monai.deploy.core.domain.dicom_series import DICOMSeries
 from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator
 from monai.deploy.operators.dicom_series_to_volume_operator import DICOMSeriesToVolumeOperator
 
+
 @input("seg_image", Image, IOType.IN_MEMORY)
 @input("dicom_series", DICOMSeries, IOType.IN_MEMORY)
 @output("dicom_seg_instance", DataPath, IOType.DISK)
@@ -56,11 +57,11 @@ class DICOMSegmentationWriterOperator(Operator):
     """
 
     # Supported input image format, based on extension.
-    SUPPORTED_EXTENSIONS = ['.nii', '.nii.gz', '.mhd']
+    SUPPORTED_EXTENSIONS = [".nii", ".nii.gz", ".mhd"]
     # DICOM instance file extension. Case insentiive in string comaprision.
-    DCM_EXTENSION = '.dcm'
+    DCM_EXTENSION = ".dcm"
     # Suffix to add to file name to indicate DICOM Seg dcm file.
-    DICOMSEG_SUFFIX = '-DICOMSEG'
+    DICOMSEG_SUFFIX = "-DICOMSEG"
 
     def __init__(self, seg_labels: Union[List[str], str] = None, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -100,7 +101,7 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
 
         # Get the seg image in numpy
         seg_image_numpy = None
-        input_path = 'dicom_seg'
+        input_path = "dicom_seg"
         seg_image = input.get("seg_image")
         if isinstance(seg_image, Image):
             seg_image_numpy = seg_image.asnumpy()
@@ -115,36 +116,32 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
         # Create the output path for created DICOM Seg instance
         output_dir = output.get().path
         output_dir.mkdir(parents=True, exist_ok=True)
-        output_filename = '{0}{1}{2}'.format(
+        output_filename = "{0}{1}{2}".format(
             os.path.splitext(os.path.basename(input_path))[0],
             DICOMSegmentationWriterOperator.DICOMSEG_SUFFIX,
-            DICOMSegmentationWriterOperator.DCM_EXTENSION)
+            DICOMSegmentationWriterOperator.DCM_EXTENSION,
+        )
         output_path = os.path.join(output_dir, output_filename)
 
         self.create_dicom_seg(seg_image_numpy, dicom_series, output_path)
 
-    def create_dicom_seg(self, image, dicom_series: DICOMSeries, file_path:str):
-        dicom_dataset_list = \
-            [i.get_native_sop_instance() for i in dicom_series.get_sop_instances()]
+    def create_dicom_seg(self, image, dicom_series: DICOMSeries, file_path: str):
+        dicom_dataset_list = [i.get_native_sop_instance() for i in dicom_series.get_sop_instances()]
 
         # DICOM Seg creation
         self._seg_writer = DICOMSegWriter()
         try:
-            self._seg_writer.write(
-                image,
-                dicom_dataset_list,
-                file_path,
-                self._seg_labels)
+            self._seg_writer.write(image, dicom_dataset_list, file_path, self._seg_labels)
             # TODO: get a class to encapsulate the seg label information.
 
             # Test reading back
             _ = self._read_from_dcm(file_path)
         except Exception as ex:
-            print('DICOMSeg creation failed. Error:\n{}'.format(ex))
+            print("DICOMSeg creation failed. Error:\n{}".format(ex))
             raise
 
     def _read_from_dcm(self, file_path):
-        """ Read dcm file into pydicom Dataset
+        """Read dcm file into pydicom Dataset
 
         Args:
             file_path (str): The path to dcm file
@@ -152,7 +149,7 @@ def _read_from_dcm(self, file_path):
         return dcmread(file_path)
 
     def select_input_file(self, input_folder, extensions=SUPPORTED_EXTENSIONS):
-        """ Select the inut files based on supported extensions.
+        """Select the inut files based on supported extensions.
 
         Args:
             input_folder (string): the path of the folder containing the input file(s)
@@ -176,25 +173,24 @@ def which_supported_ext(file_path, extensions):
                     ext = which_supported_ext(file_path, extensions)
                     if ext:
                         return file_path, ext
-            raise IOError('No supported input file found ({})'.format(extensions))
+            raise IOError("No supported input file found ({})".format(extensions))
         elif os.path.isfile(input_folder):
             ext = which_supported_ext(input_folder, extensions)
             if ext:
                 return input_folder, ext
         else:
-            raise FileNotFoundError('{} is not found.'.format(input_folder))
+            raise FileNotFoundError("{} is not found.".format(input_folder))
 
-    def _image_file_to_numpy(self, input_path:str):
-        """Converts image file to numpy
-        """
+    def _image_file_to_numpy(self, input_path: str):
+        """Converts image file to numpy"""
 
         img = sitk.ReadImage(input_path)
         data_np = sitk.GetArrayFromImage(img)
         if data_np is None:
-            raise RuntimeError('Failed to convert image file to numpy: {}'.format(input_path))
+            raise RuntimeError("Failed to convert image file to numpy: {}".format(input_path))
         return data_np.astype(np.uint8)
 
-    def _get_label_list(self, stringfied_list_of_labels: str = ''):
+    def _get_label_list(self, stringfied_list_of_labels: str = ""):
         """Parse the string to get the label list.
 
         If empty string is provided, a list of a single element is retured.
@@ -209,17 +205,16 @@ def _get_label_list(self, stringfied_list_of_labels: str = ''):
         # Use json.loads as a convenience method to convert string to list of strings
         assert isinstance(stringfied_list_of_labels, str), "Expected stringfiled list pf labels."
 
-        label_list = ["default-label"]    # Use this as default if empty string
+        label_list = ["default-label"]  # Use this as default if empty string
         if stringfied_list_of_labels:
             label_list = json.loads(stringfied_list_of_labels)
 
         return label_list
 
-class DICOMSegWriter(object):
 
+class DICOMSegWriter(object):
     def __init__(self):
-        """Class to write DICOM SEG with the segmentation image and DICOM dataset.
-        """
+        """Class to write DICOM SEG with the segmentation image and DICOM dataset."""
 
         self._logger = logging.getLogger("{}.{}".format(__name__, type(self).__name__))
 
@@ -234,7 +229,7 @@ def write(self, seg_img, input_ds, outfile, seg_labels):
         """
 
         if seg_img is None:
-            raise ValueError('Argument seg_img cannot be None.')
+            raise ValueError("Argument seg_img cannot be None.")
         if not isinstance(input_ds, list) or len(input_ds) < 1:
             raise ValueError("Argument input_ds must not be empty.")
         if not outfile:
@@ -266,10 +261,12 @@ def write(self, seg_img, input_ds, outfile, seg_labels):
         dcm_out.save_as(outfile, False)
         self._logger.info("File saved.")
 
+
 # The following functions are mostly based on the implementation demo'ed at RSNA 2019.
 # They can be further refactored and made into class methods, but work for now.
 
-def safe_get(ds,key):
+
+def safe_get(ds, key):
     """Safely gets the tag value if present from the Dataset and logs failure.
 
     The safe get method of dict works for str, but not the hex key. The added
@@ -284,15 +281,17 @@ def safe_get(ds,key):
         return ds[key].value
     except KeyError as e:
         logging.error("Failed to get value for key: {}".format(e))
-    return ''
+    return ""
+
 
 def random_with_n_digits(n):
     assert isinstance(n, int), "Argument n must be a int."
     n = n if n >= 1 else 1
-    range_start = 10**(n-1)
-    range_end = (10**n)-1
+    range_start = 10 ** (n - 1)
+    range_end = (10 ** n) - 1
     return randint(range_start, range_end)
 
+
 def create_multiframe_metadata(dicom_file, input_ds):
     """Creates the DICOM metadata for the multiframe object, e.g. SEG
 
@@ -305,17 +304,17 @@ def create_multiframe_metadata(dicom_file, input_ds):
     """
 
     currentDateRaw = datetime.datetime.now()
-    currentDate = currentDateRaw.strftime('%Y%m%d')
-    currentTime = currentDateRaw.strftime('%H%M%S.%f')  # long format with micro seconds
+    currentDate = currentDateRaw.strftime("%Y%m%d")
+    currentTime = currentDateRaw.strftime("%H%M%S.%f")  # long format with micro seconds
     segmentationSeriesInstanceUID = generate_uid(prefix=None)
     segmentationSOPInstanceUID = generate_uid(prefix=None)
 
     # Populate required values for file meta information
 
     file_meta = Dataset()
-    file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.66.4'
+    file_meta.MediaStorageSOPClassUID = "1.2.840.10008.5.1.4.1.1.66.4"
     file_meta.MediaStorageSOPInstanceUID = segmentationSOPInstanceUID
-    file_meta.ImplementationClassUID = '1.2.840.10008.5.1.4.1.1.66.4'
+    file_meta.ImplementationClassUID = "1.2.840.10008.5.1.4.1.1.66.4"
     file_meta.TransferSyntaxUID = ImplicitVRLittleEndian
     # create dicom global metadata
     dicomOutput = FileDataset(dicom_file, {}, file_meta=file_meta, preamble=b"\0" * 128)
@@ -327,110 +326,109 @@ def create_multiframe_metadata(dicom_file, input_ds):
 
     # None of Patient module attributes are mandatory.
     # The following are Type 2, present though could be blank
-    dicomOutput.PatientName = input_ds.get('PatientName', '')  # name is actual suppoted
-    dicomOutput.add_new(0x00100020, 'LO', safe_get(input_ds,0x00100020))  # PatientID
-    dicomOutput.add_new(0x00100030, 'DA', safe_get(input_ds,0x00100030))  # PatientBirthDate
-    dicomOutput.add_new(0x00100040, 'CS', safe_get(input_ds,0x00100040))  # PatientSex
-    dicomOutput.add_new(0x00104000, 'LT', safe_get(input_ds, '0x00104000'))  # PatientComments
+    dicomOutput.PatientName = input_ds.get("PatientName", "")  # name is actual suppoted
+    dicomOutput.add_new(0x00100020, "LO", safe_get(input_ds, 0x00100020))  # PatientID
+    dicomOutput.add_new(0x00100030, "DA", safe_get(input_ds, 0x00100030))  # PatientBirthDate
+    dicomOutput.add_new(0x00100040, "CS", safe_get(input_ds, 0x00100040))  # PatientSex
+    dicomOutput.add_new(0x00104000, "LT", safe_get(input_ds, "0x00104000"))  # PatientComments
 
     # For Study module, copy original StudyInstanceUID and other Type 2 study attributes
     # Only Study Instance UID is Type 1, though still may be absent, so try to get
-    dicomOutput.add_new(0x0020000D, 'UI', safe_get(input_ds,0x0020000D))  # StudyInstanceUID
-    dicomOutput.add_new(0x00080020, 'DA', input_ds.get('StudyDate', currentDate))  # StudyDate
-    dicomOutput.add_new(0x00080030, 'TM', input_ds.get('StudyTime', currentTime))  # StudyTime
-    dicomOutput.add_new(0x00080090, 'PN', safe_get(input_ds,0x00080090))  # ReferringPhysicianName
-    dicomOutput.add_new(0x00200010, 'SH', safe_get(input_ds,0x00200010))  # StudyID
-    dicomOutput.add_new(0x00080050, 'SH', safe_get(input_ds,0x00080050))  # AccessionNumber
+    dicomOutput.add_new(0x0020000D, "UI", safe_get(input_ds, 0x0020000D))  # StudyInstanceUID
+    dicomOutput.add_new(0x00080020, "DA", input_ds.get("StudyDate", currentDate))  # StudyDate
+    dicomOutput.add_new(0x00080030, "TM", input_ds.get("StudyTime", currentTime))  # StudyTime
+    dicomOutput.add_new(0x00080090, "PN", safe_get(input_ds, 0x00080090))  # ReferringPhysicianName
+    dicomOutput.add_new(0x00200010, "SH", safe_get(input_ds, 0x00200010))  # StudyID
+    dicomOutput.add_new(0x00080050, "SH", safe_get(input_ds, 0x00080050))  # AccessionNumber
 
     # Series module with new attribute values, only Modality and SeriesInstanceUID are Type 1
-    dicomOutput.add_new(0x00080060, 'CS', 'SEG')  # Modality
-    dicomOutput.add_new(0x0020000E, 'UI', segmentationSeriesInstanceUID)  # SeriesInstanceUID
-    dicomOutput.add_new(0x00200011, 'IS', random_with_n_digits(4))  # SeriesNumber (randomized)
+    dicomOutput.add_new(0x00080060, "CS", "SEG")  # Modality
+    dicomOutput.add_new(0x0020000E, "UI", segmentationSeriesInstanceUID)  # SeriesInstanceUID
+    dicomOutput.add_new(0x00200011, "IS", random_with_n_digits(4))  # SeriesNumber (randomized)
     descr = "CAUTION: Research Use Only. MONAI Deploy App SDK generated DICOM SEG"
-    if safe_get(input_ds, 0x0008103e):
-        descr += " for " + safe_get(input_ds,0x0008103e)
-    dicomOutput.add_new(0x0008103e, 'LO', descr )  # SeriesDescription
-    dicomOutput.add_new(0x00080021, 'DA', currentDate)  # SeriesDate
-    dicomOutput.add_new(0x00080031, 'TM', currentTime)  # SeriesTime
+    if safe_get(input_ds, 0x0008103E):
+        descr += " for " + safe_get(input_ds, 0x0008103E)
+    dicomOutput.add_new(0x0008103E, "LO", descr)  # SeriesDescription
+    dicomOutput.add_new(0x00080021, "DA", currentDate)  # SeriesDate
+    dicomOutput.add_new(0x00080031, "TM", currentTime)  # SeriesTime
 
     # General Equipment module, only Manufacturer is Type 2, the rest Type 3
-    dicomOutput.add_new(0x00181000, 'LO', '0000')  # DeviceSerialNumber
-    dicomOutput.add_new(0x00080070, 'LO', 'MONAI Deploy')  # Manufacturer
-    dicomOutput.add_new(0x00081090, 'LO', 'App SDK')  # ManufacturerModelName
+    dicomOutput.add_new(0x00181000, "LO", "0000")  # DeviceSerialNumber
+    dicomOutput.add_new(0x00080070, "LO", "MONAI Deploy")  # Manufacturer
+    dicomOutput.add_new(0x00081090, "LO", "App SDK")  # ManufacturerModelName
     try:
-        version_str = get_sdk_semver()    # SDK Version
+        version_str = get_sdk_semver()  # SDK Version
     except Exception:
-        version_str = "0.1"    # Fall back to the initial version
-    dicomOutput.add_new(0x00181020, 'LO',  version_str) # SoftwareVersions
+        version_str = "0.1"  # Fall back to the initial version
+    dicomOutput.add_new(0x00181020, "LO", version_str)  # SoftwareVersions
 
     # SOP common, only SOPClassUID and SOPInstanceUID are Type 1
-    dicomOutput.add_new(0x00200013, 'IS', 1)  # InstanceNumber
-    dicomOutput.add_new(0x00080016, 'UI', '1.2.840.10008.5.1.4.1.1.66.4')  # SOPClassUID, per DICOM.
-    dicomOutput.add_new(0x00080018, 'UI', segmentationSOPInstanceUID)  # SOPInstanceUID
-    dicomOutput.add_new(0x00080012, 'DA', currentDate)  # InstanceCreationDate
-    dicomOutput.add_new(0x00080013, 'TM', currentTime)  # InstanceCreationTime
+    dicomOutput.add_new(0x00200013, "IS", 1)  # InstanceNumber
+    dicomOutput.add_new(0x00080016, "UI", "1.2.840.10008.5.1.4.1.1.66.4")  # SOPClassUID, per DICOM.
+    dicomOutput.add_new(0x00080018, "UI", segmentationSOPInstanceUID)  # SOPInstanceUID
+    dicomOutput.add_new(0x00080012, "DA", currentDate)  # InstanceCreationDate
+    dicomOutput.add_new(0x00080013, "TM", currentTime)  # InstanceCreationTime
 
     # General Image module.
-    dicomOutput.add_new(0x00080008, 'CS', ['DERIVED', 'PRIMARY'])  #  ImageType
-    dicomOutput.add_new(0x00200020, 'CS', '')  # PatientOrientation, forced empty
+    dicomOutput.add_new(0x00080008, "CS", ["DERIVED", "PRIMARY"])  #  ImageType
+    dicomOutput.add_new(0x00200020, "CS", "")  # PatientOrientation, forced empty
     # Set content date/time
     dicomOutput.ContentDate = currentDate
     dicomOutput.ContentTime = currentTime
 
     # Image Pixel
-    dicomOutput.add_new(0x00280002, 'US', 1)  # SamplesPerPixel
-    dicomOutput.add_new(0x00280004, 'CS', 'MONOCHROME2')  # PhotometricInterpretation
+    dicomOutput.add_new(0x00280002, "US", 1)  # SamplesPerPixel
+    dicomOutput.add_new(0x00280004, "CS", "MONOCHROME2")  # PhotometricInterpretation
 
     # Common Instance Reference module
-    dicomOutput.add_new(0x00081115, 'SQ', [Dataset()]) # ReferencedSeriesSequence
+    dicomOutput.add_new(0x00081115, "SQ", [Dataset()])  # ReferencedSeriesSequence
     # Set the referenced SeriesInstanceUID
-    dicomOutput.get(0x00081115)[0].add_new(0x0020000E, 'UI', safe_get(input_ds, 0x0020000E))
+    dicomOutput.get(0x00081115)[0].add_new(0x0020000E, "UI", safe_get(input_ds, 0x0020000E))
 
     # Multi-frame Dimension Module
     dimensionID = generate_uid(prefix=None)
     dimensionOragnizationSequence = Sequence()
     dimensionOragnizationSequenceDS = Dataset()
-    dimensionOragnizationSequenceDS.add_new(0x00209164, 'UI', dimensionID)  # DimensionOrganizationUID
+    dimensionOragnizationSequenceDS.add_new(0x00209164, "UI", dimensionID)  # DimensionOrganizationUID
     dimensionOragnizationSequence.append(dimensionOragnizationSequenceDS)
-    dicomOutput.add_new(0x00209221, 'SQ', dimensionOragnizationSequence)  # DimensionOrganizationSequence
+    dicomOutput.add_new(0x00209221, "SQ", dimensionOragnizationSequence)  # DimensionOrganizationSequence
 
     dimensionIndexSequence = Sequence()
     dimensionIndexSequenceDS = Dataset()
-    dimensionIndexSequenceDS.add_new(0x00209164, 'UI', dimensionID)  # DimensionOrganizationUID
-    dimensionIndexSequenceDS.add_new(0x00209165, 'AT', 0x00209153)  # DimensionIndexPointer
-    dimensionIndexSequenceDS.add_new(0x00209167, 'AT', 0x00209153)  # FunctionalGroupPointer
+    dimensionIndexSequenceDS.add_new(0x00209164, "UI", dimensionID)  # DimensionOrganizationUID
+    dimensionIndexSequenceDS.add_new(0x00209165, "AT", 0x00209153)  # DimensionIndexPointer
+    dimensionIndexSequenceDS.add_new(0x00209167, "AT", 0x00209153)  # FunctionalGroupPointer
     dimensionIndexSequence.append(dimensionIndexSequenceDS)
-    dicomOutput.add_new(0x00209222, 'SQ', dimensionIndexSequence)  # DimensionIndexSequence
+    dicomOutput.add_new(0x00209222, "SQ", dimensionIndexSequence)  # DimensionIndexSequence
 
     return dicomOutput
 
+
 def create_label_segments(dcm_output, seg_labels):
-    """"Creates the segments with the given labels
-    """
+    """ "Creates the segments with the given labels"""
 
     def create_label_segment(label, name):
-        """Creates segment labels
-        """
+        """Creates segment labels"""
         segment = Dataset()
-        segment.add_new(0x00620004, 'US', int(label))  # SegmentNumber
-        segment.add_new(0x00620005, 'LO', name)  # SegmentLabel
-        segment.add_new(0x00620009, 'LO', 'AI Organ Segmentation')  # SegmentAlgorithmName
-        segment.SegmentAlgorithmType = 'AUTOMATIC'  # SegmentAlgorithmType
-        segment.add_new(0x0062000d, 'US', [128, 174, 128]) # RecommendedDisplayCIELabValue
+        segment.add_new(0x00620004, "US", int(label))  # SegmentNumber
+        segment.add_new(0x00620005, "LO", name)  # SegmentLabel
+        segment.add_new(0x00620009, "LO", "AI Organ Segmentation")  # SegmentAlgorithmName
+        segment.SegmentAlgorithmType = "AUTOMATIC"  # SegmentAlgorithmType
+        segment.add_new(0x0062000D, "US", [128, 174, 128])  # RecommendedDisplayCIELabValue
         ## create SegmentedPropertyCategoryCodeSequence
         segmentedPropertyCategoryCodeSequence = Sequence()
         segmentedPropertyCategoryCodeSequenceDS = Dataset()
-        segmentedPropertyCategoryCodeSequenceDS.add_new(0x00080100, 'SH', 'T-D0050')  # CodeValue
-        segmentedPropertyCategoryCodeSequenceDS.add_new(0x00080102, 'SH', 'SRT')  # CodingSchemeDesignator
-        segmentedPropertyCategoryCodeSequenceDS.add_new(0x00080104, 'LO', 'Anatomical Structure')  # CodeMeaning
+        segmentedPropertyCategoryCodeSequenceDS.add_new(0x00080100, "SH", "T-D0050")  # CodeValue
+        segmentedPropertyCategoryCodeSequenceDS.add_new(0x00080102, "SH", "SRT")  # CodingSchemeDesignator
+        segmentedPropertyCategoryCodeSequenceDS.add_new(0x00080104, "LO", "Anatomical Structure")  # CodeMeaning
         segmentedPropertyCategoryCodeSequence.append(segmentedPropertyCategoryCodeSequenceDS)
         segment.SegmentedPropertyCategoryCodeSequence = segmentedPropertyCategoryCodeSequence
         ## create SegmentedPropertyTypeCodeSequence
         segmentedPropertyTypeCodeSequence = Sequence()
         segmentedPropertyTypeCodeSequenceDS = Dataset()
-        segmentedPropertyTypeCodeSequenceDS.add_new(0x00080100, 'SH', 'T-D0050')  # CodeValue
-        segmentedPropertyTypeCodeSequenceDS.add_new(0x00080102, 'SH', 'SRT')  # CodingSchemeDesignator
-        segmentedPropertyTypeCodeSequenceDS.add_new(0x00080104, 'LO', 'Organ')  # CodeMeaning
+        segmentedPropertyTypeCodeSequenceDS.add_new(0x00080100, "SH", "T-D0050")  # CodeValue
+        segmentedPropertyTypeCodeSequenceDS.add_new(0x00080102, "SH", "SRT")  # CodingSchemeDesignator
+        segmentedPropertyTypeCodeSequenceDS.add_new(0x00080104, "LO", "Organ")  # CodeMeaning
         segmentedPropertyTypeCodeSequence.append(segmentedPropertyTypeCodeSequenceDS)
         segment.SegmentedPropertyTypeCodeSequence = segmentedPropertyTypeCodeSequence
         return segment
@@ -441,11 +439,11 @@ def create_label_segment(label, name):
     for lb, name in enumerate(seg_labels, 1):
         segment = create_label_segment(lb, name)
         segments.append(segment)
-    dcm_output.add_new(0x00620002, 'SQ', segments)  # SegmentSequence
+    dcm_output.add_new(0x00620002, "SQ", segments)  # SegmentSequence
+
 
 def create_frame_meta(input_ds, label, ref_instances, dimIdxVal, instance_num):
-    """Creates the metadata for the each frame
-    """
+    """Creates the metadata for the each frame"""
 
     sop_inst_uid = safe_get(input_ds, 0x00080018)  # SOPInstanceUID
     sourceInstanceSOPClass = safe_get(input_ds, 0x00080016)  # SOPClassUID
@@ -453,8 +451,8 @@ def create_frame_meta(input_ds, label, ref_instances, dimIdxVal, instance_num):
     # add frame to Referenced Image Sequence
     frame_ds = Dataset()
     referenceInstance = Dataset()
-    referenceInstance.add_new(0x00081150, 'UI', sourceInstanceSOPClass)  # ReferencedSOPClassUID
-    referenceInstance.add_new(0x00081155, 'UI', sop_inst_uid)  # ReferencedSOPInstanceUID
+    referenceInstance.add_new(0x00081150, "UI", sourceInstanceSOPClass)  # ReferencedSOPClassUID
+    referenceInstance.add_new(0x00081155, "UI", sop_inst_uid)  # ReferencedSOPInstanceUID
 
     ref_instances.append(referenceInstance)
     ############################
@@ -468,58 +466,58 @@ def create_frame_meta(input_ds, label, ref_instances, dimIdxVal, instance_num):
     sourceImage = Dataset()
     # TODO if CT multi-frame
     # sourceImage.add_new(0x00081160, 'IS', inputFrameCounter + 1) # Referenced Frame Number
-    sourceImage.add_new(0x00081150, 'UI', sourceInstanceSOPClass)  # ReferencedSOPClassUID
-    sourceImage.add_new(0x00081155, 'UI', sop_inst_uid)  # ReferencedSOPInstanceUID
+    sourceImage.add_new(0x00081150, "UI", sourceInstanceSOPClass)  # ReferencedSOPClassUID
+    sourceImage.add_new(0x00081155, "UI", sop_inst_uid)  # ReferencedSOPInstanceUID
     ## create PurposeOfReferenceCodeSequence within SourceImageSequence
     purposeOfReferenceCodeSequence = Sequence()
     purposeOfReferenceCode = Dataset()
-    purposeOfReferenceCode.add_new(0x00080100, 'SH', '121322')  # CodeValue
-    purposeOfReferenceCode.add_new(0x00080102, 'SH', 'DCM')  # CodingSchemeDesignator
-    purposeOfReferenceCode.add_new(0x00080104, 'LO', 'Anatomical Stucture')  # CodeMeaning
+    purposeOfReferenceCode.add_new(0x00080100, "SH", "121322")  # CodeValue
+    purposeOfReferenceCode.add_new(0x00080102, "SH", "DCM")  # CodingSchemeDesignator
+    purposeOfReferenceCode.add_new(0x00080104, "LO", "Anatomical Stucture")  # CodeMeaning
     purposeOfReferenceCodeSequence.append(purposeOfReferenceCode)
-    sourceImage.add_new(0x0040a170, 'SQ', purposeOfReferenceCodeSequence)  # PurposeOfReferenceCodeSequence
-    sourceImageSequence.append(sourceImage) # AEH Beck commentout
+    sourceImage.add_new(0x0040A170, "SQ", purposeOfReferenceCodeSequence)  # PurposeOfReferenceCodeSequence
+    sourceImageSequence.append(sourceImage)  # AEH Beck commentout
     ### create DerivationCodeSequence within DerivationImageSequence
     derivationCodeSequence = Sequence()
     derivationCode = Dataset()
-    derivationCode.add_new(0x00080100, 'SH', '113076')  # CodeValue
-    derivationCode.add_new(0x00080102, 'SH', 'DCM')  # CodingSchemeDesignator
-    derivationCode.add_new(0x00080104, 'LO', 'Segmentation')  # CodeMeaning
+    derivationCode.add_new(0x00080100, "SH", "113076")  # CodeValue
+    derivationCode.add_new(0x00080102, "SH", "DCM")  # CodingSchemeDesignator
+    derivationCode.add_new(0x00080104, "LO", "Segmentation")  # CodeMeaning
     derivationCodeSequence.append(derivationCode)
-    derivationImage.add_new(0x00089215, 'SQ', derivationCodeSequence)  # DerivationCodeSequence
-    derivationImage.add_new(0x00082112, 'SQ', sourceImageSequence)  # SourceImageSequence
+    derivationImage.add_new(0x00089215, "SQ", derivationCodeSequence)  # DerivationCodeSequence
+    derivationImage.add_new(0x00082112, "SQ", sourceImageSequence)  # SourceImageSequence
     derivationImageSequence.append(derivationImage)
-    frame_ds.add_new(0x00089124, 'SQ', derivationImageSequence)  # DerivationImageSequence
+    frame_ds.add_new(0x00089124, "SQ", derivationImageSequence)  # DerivationImageSequence
     ##### create FrameContentSequence within Per-frame Functional Groups sequence
     frameContent = Sequence()
     dimensionIndexValues = Dataset()
-    dimensionIndexValues.add_new(0x00209157, 'UL', [dimIdxVal, instance_num])  # DimensionIndexValues
+    dimensionIndexValues.add_new(0x00209157, "UL", [dimIdxVal, instance_num])  # DimensionIndexValues
     frameContent.append(dimensionIndexValues)
-    frame_ds.add_new(0x00209111, 'SQ', frameContent)  # FrameContentSequence
+    frame_ds.add_new(0x00209111, "SQ", frameContent)  # FrameContentSequence
     ##### create PlanePositionSequence within Per-frame Functional Groups sequence
     planePositionSequence = Sequence()
     imagePositionPatient = Dataset()
-    imagePositionPatient.add_new(0x00200032, 'DS', safe_get(input_ds,0x00200032))  # ImagePositionPatient
+    imagePositionPatient.add_new(0x00200032, "DS", safe_get(input_ds, 0x00200032))  # ImagePositionPatient
     planePositionSequence.append(imagePositionPatient)
-    frame_ds.add_new(0x00209113, 'SQ', planePositionSequence)  # PlanePositionSequence
+    frame_ds.add_new(0x00209113, "SQ", planePositionSequence)  # PlanePositionSequence
     ##### create PlaneOrientationSequence within Per-frame Functional Groups sequence
     planeOrientationSequence = Sequence()
     imageOrientationPatient = Dataset()
-    imageOrientationPatient.add_new(0x00200037, 'DS', safe_get(input_ds,0x00200037))  # ImageOrientationPatient
+    imageOrientationPatient.add_new(0x00200037, "DS", safe_get(input_ds, 0x00200037))  # ImageOrientationPatient
     planeOrientationSequence.append(imageOrientationPatient)
-    frame_ds.add_new(0x00209116, 'SQ', planeOrientationSequence)  # PlaneOrientationSequence
+    frame_ds.add_new(0x00209116, "SQ", planeOrientationSequence)  # PlaneOrientationSequence
     ##### create SegmentIdentificationSequence within Per-frame Functional Groups sequence
     segmentIdentificationSequence = Sequence()
     referencedSegmentNumber = Dataset()
     # TODO lop over label and only get pixel with that value
-    referencedSegmentNumber.add_new(0x0062000B, 'US', label)  # ReferencedSegmentNumber, which label is this frame
+    referencedSegmentNumber.add_new(0x0062000B, "US", label)  # ReferencedSegmentNumber, which label is this frame
     segmentIdentificationSequence.append(referencedSegmentNumber)
-    frame_ds.add_new(0x0062000A, 'SQ', segmentIdentificationSequence)  # SegmentIdentificationSequence
+    frame_ds.add_new(0x0062000A, "SQ", segmentIdentificationSequence)  # SegmentIdentificationSequence
     return frame_ds
 
+
 def set_pixel_meta(dicomOutput, input_ds):
-    """Sets the pixel metadata in the DICOM object
-    """
+    """Sets the pixel metadata in the DICOM object"""
 
     dicomOutput.Rows = input_ds.Rows
     dicomOutput.Columns = input_ds.Columns
@@ -529,28 +527,28 @@ def set_pixel_meta(dicomOutput, input_ds):
     dicomOutput.PixelRepresentation = 0
     # dicomOutput.PixelRepresentation = input_ds.PixelRepresentation
     dicomOutput.SamplesPerPixel = 1
-    dicomOutput.ImageType = 'DERIVED\PRIMARY'
-    dicomOutput.ContentLabel = 'SEGMENTATION'
-    dicomOutput.ContentDescription = ''
-    dicomOutput.ContentCreatorName = ''
-    dicomOutput.LossyImageCompression = '00'
-    dicomOutput.SegmentationType = 'BINARY'
+    dicomOutput.ImageType = "DERIVED\PRIMARY"
+    dicomOutput.ContentLabel = "SEGMENTATION"
+    dicomOutput.ContentDescription = ""
+    dicomOutput.ContentCreatorName = ""
+    dicomOutput.LossyImageCompression = "00"
+    dicomOutput.SegmentationType = "BINARY"
     dicomOutput.MaximumFractionalValue = 1
     dicomOutput.SharedFunctionalGroupsSequence = Sequence()
     dicomOutput.PixelPaddingValue = 0
     # Try to get the attributes from the original.
     # Even though they are Type 1 and 2, can still be absent
-    dicomOutput.PixelSpacing = copy.deepcopy(input_ds.get('PixelSpacing', None))
-    dicomOutput.SliceThickness = input_ds.get('SliceThickness', '')
+    dicomOutput.PixelSpacing = copy.deepcopy(input_ds.get("PixelSpacing", None))
+    dicomOutput.SliceThickness = input_ds.get("SliceThickness", "")
     dicomOutput.RescaleSlope = 1
     dicomOutput.RescaleIntercept = 0
     # Set the transfer syntax
-    dicomOutput.is_little_endian = False # True
-    dicomOutput.is_implicit_VR = False #True
+    dicomOutput.is_little_endian = False  # True
+    dicomOutput.is_implicit_VR = False  # True
+
 
 def segslice_from_mhd(dcm_output, seg_img, input_ds, num_labels):
-    """Sets the pixel data from the input numpy image
-    """
+    """Sets the pixel data from the input numpy image"""
 
     if np.amax(seg_img) == 0 and np.amin(seg_img) == 0:
         raise ValueError("Seg mask is not detected; all 0's.")
@@ -570,7 +568,7 @@ def segslice_from_mhd(dcm_output, seg_img, input_ds, num_labels):
         for label in range(1, num_labels + 1):
 
             # Determine if frame gets output
-            if np.count_nonzero(seg_img[img_slice, ...] == label)==0: # no label for this frame --> skip
+            if np.count_nonzero(seg_img[img_slice, ...] == label) == 0:  # no label for this frame --> skip
                 continue
 
             dimIdxVal += 1
@@ -578,10 +576,14 @@ def segslice_from_mhd(dcm_output, seg_img, input_ds, num_labels):
             frame_meta = create_frame_meta(input_ds[img_slice], label, referenceInstances, dimIdxVal, img_slice)
 
             out_frames.append(frame_meta)
-            logging.info("img slice {}, label {}, frame {}, img pos {}".format(img_slice, label, out_frame_counter, safe_get(input_ds[img_slice],0x00200032)))
+            logging.info(
+                "img slice {}, label {}, frame {}, img pos {}".format(
+                    img_slice, label, out_frame_counter, safe_get(input_ds[img_slice], 0x00200032)
+                )
+            )
             seg_slice = np.zeros((1, seg_img.shape[1], seg_img.shape[2]), dtype=np.bool)
 
-            seg_slice[np.expand_dims(seg_img[img_slice, ...] == label,0)] = 1
+            seg_slice[np.expand_dims(seg_img[img_slice, ...] == label, 0)] = 1
 
             if out_pixels is None:
                 out_pixels = seg_slice
@@ -590,12 +592,11 @@ def segslice_from_mhd(dcm_output, seg_img, input_ds, num_labels):
 
             out_frame_counter = out_frame_counter + 1
 
-    dcm_output.add_new(0x52009230, 'SQ', out_frames) # PerFrameFunctionalGroupsSequence
+    dcm_output.add_new(0x52009230, "SQ", out_frames)  # PerFrameFunctionalGroupsSequence
     dcm_output.NumberOfFrames = out_frame_counter
     dcm_output.PixelData = np.packbits(np.flip(np.reshape(out_pixels.astype(np.bool), (-1, 8)), 1)).tostring()
 
-
-    dcm_output.get(0x00081115)[0].add_new(0x0008114A, 'SQ', referenceInstances)  # ReferencedInstanceSequence
+    dcm_output.get(0x00081115)[0].add_new(0x0008114A, "SQ", referenceInstances)  # ReferencedInstanceSequence
 
     ##### create shared  Functional Groups sequence
     sharedFunctionalGroups = Sequence()
@@ -603,24 +604,27 @@ def segslice_from_mhd(dcm_output, seg_img, input_ds, num_labels):
 
     planeOrientationSeq = Sequence()
     planeOrientationDS = Dataset()
-    planeOrientationDS.add_new('0x00200037','DS', safe_get(input_ds[0], 0x00200037))  # ImageOrientationPatient
+    planeOrientationDS.add_new("0x00200037", "DS", safe_get(input_ds[0], 0x00200037))  # ImageOrientationPatient
     planeOrientationSeq.append(planeOrientationDS)
-    sharedFunctionalGroupsDS.add_new('0x00209116', 'SQ', planeOrientationSeq)  # PlaneOrientationSequence
+    sharedFunctionalGroupsDS.add_new("0x00209116", "SQ", planeOrientationSeq)  # PlaneOrientationSequence
 
     pixelMeasuresSequence = Sequence()
     pixelMeasuresDS = Dataset()
-    pixelMeasuresDS.add_new('0x00280030','DS', safe_get(input_ds[0],'0x00280030'))  # PixelSpacing
-    if input_ds[0].get('SpacingBetweenSlices', ''):
-        pixelMeasuresDS.add_new('0x00180088','DS', input_ds[0].get('SpacingBetweenSlices', ''))  # SpacingBetweenSlices
-    pixelMeasuresDS.add_new('0x00180050','DS', safe_get(input_ds[0], '0x00180050'))  # SliceThickness
+    pixelMeasuresDS.add_new("0x00280030", "DS", safe_get(input_ds[0], "0x00280030"))  # PixelSpacing
+    if input_ds[0].get("SpacingBetweenSlices", ""):
+        pixelMeasuresDS.add_new("0x00180088", "DS", input_ds[0].get("SpacingBetweenSlices", ""))  # SpacingBetweenSlices
+    pixelMeasuresDS.add_new("0x00180050", "DS", safe_get(input_ds[0], "0x00180050"))  # SliceThickness
     pixelMeasuresSequence.append(pixelMeasuresDS)
-    sharedFunctionalGroupsDS.add_new('0x00289110', 'SQ', pixelMeasuresSequence)  # PixelMeasuresSequence
+    sharedFunctionalGroupsDS.add_new("0x00289110", "SQ", pixelMeasuresSequence)  # PixelMeasuresSequence
 
     sharedFunctionalGroups.append(sharedFunctionalGroupsDS)
 
-    dcm_output.add_new(0x52009229, 'SQ', sharedFunctionalGroups)  # SharedFunctionalGroupsSequence
+    dcm_output.add_new(0x52009229, "SQ", sharedFunctionalGroups)  # SharedFunctionalGroupsSequence
+
+
 # End DICOM Seg Writer temp
 
+
 def test():
     data_path = "/home/mqin/src/monai-app-sdk/examples/apps/ai_spleen_seg_app/input"
     out_path = "/home/mqin/src/monai-app-sdk/examples/apps/ai_spleen_seg_app/output/dcm_seg_test.dcm"
@@ -641,5 +645,6 @@ def test():
     seg_writer = DICOMSegmentationWriterOperator()
     seg_writer.create_dicom_seg(image_numpy, series, out_path)
 
+
 if __name__ == "__main__":
     test()
diff --git a/monai/deploy/operators/dicom_series_selector_operator.py b/monai/deploy/operators/dicom_series_selector_operator.py
index b58abf59..0730d5ef 100644
--- a/monai/deploy/operators/dicom_series_selector_operator.py
+++ b/monai/deploy/operators/dicom_series_selector_operator.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -11,20 +11,13 @@
 
 from typing import Dict
 
-from monai.deploy.core import (
-    ExecutionContext,
-    InputContext,
-    IOType,
-    Operator,
-    OutputContext,
-    input,
-    output,
-)
+from monai.deploy.core import ExecutionContext, InputContext, IOType, Operator, OutputContext, input, output
 from monai.deploy.core.domain.dicom_series import DICOMSeries
 from monai.deploy.core.domain.dicom_study import DICOMStudy
 from monai.deploy.exceptions import ItemNotExistsError
 from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator
 
+
 @input("dicom_study_list", DICOMStudy, IOType.IN_MEMORY)
 @input("selection_rules", Dict, IOType.IN_MEMORY)
 @output("dicom_series", DICOMSeries, IOType.IN_MEMORY)
diff --git a/monai/deploy/operators/dicom_series_to_volume_operator.py b/monai/deploy/operators/dicom_series_to_volume_operator.py
index b3dbdd49..6241ca5e 100644
--- a/monai/deploy/operators/dicom_series_to_volume_operator.py
+++ b/monai/deploy/operators/dicom_series_to_volume_operator.py
@@ -1,4 +1,4 @@
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -18,6 +18,7 @@
 from monai.deploy.core.domain.dicom_series import DICOMSeries
 from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator
 
+
 @input("dicom_series", DICOMSeries, IOType.IN_MEMORY)
 @output("image", Image, IOType.IN_MEMORY)
 class DICOMSeriesToVolumeOperator(Operator):
@@ -226,13 +227,10 @@ def compute_affine_transform(self, s_1, s_n, n, series):
         y1 = ip1[1]
         z1 = ip1[2]
 
-
-
         xn = ipn[0]
         yn = ipn[1]
         zn = ipn[2]
 
-
         m1[0, 0] = rx * vr
         m1[0, 1] = cx * vc
         m1[0, 2] = (xn - x1) / (n - 1)
diff --git a/monai/deploy/operators/inference_operator.py b/monai/deploy/operators/inference_operator.py
index 56c64abb..64a81f45 100644
--- a/monai/deploy/operators/inference_operator.py
+++ b/monai/deploy/operators/inference_operator.py
@@ -9,10 +9,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import functools
-import uuid
-from abc import ABC, abstractmethod
-from typing import Any, TYPE_CHECKING, Union
+from abc import abstractmethod
+from typing import Any, Union
 
 from monai.deploy.core import ExecutionContext, Image, InputContext, Operator, OutputContext
 
@@ -25,8 +23,7 @@ class InferenceOperator(Operator):
     """
 
     def __init__(self, *args, **kwargs):
-        """Constructor of the operator.
-        """
+        """Constructor of the operator."""
         super().__init__()
 
     @abstractmethod
@@ -39,8 +36,7 @@ def pre_process(self, data: Any) -> Union[Image, Any]:
             NotImplementedError: When the subclass does not override this method.
         """
 
-        raise NotImplementedError(
-            f"Subclass {self.__class__.__name__} must implement this method.")
+        raise NotImplementedError(f"Subclass {self.__class__.__name__} must implement this method.")
 
     @abstractmethod
     def compute(self, input: InputContext, output: OutputContext, context: ExecutionContext):
@@ -54,7 +50,7 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
         pass
 
     @abstractmethod
-    def predict(self, data:Any) -> Union[Image, Any]:
+    def predict(self, data: Any) -> Union[Image, Any]:
         """Prdicts results using the models(s) with input tensors.
 
         This method must be overridden by a derived class.
@@ -62,11 +58,10 @@ def predict(self, data:Any) -> Union[Image, Any]:
         Raises:
             NotImplementedError: When the subclass does not override this method.
         """
-        raise NotImplementedError(
-            f"Subclass {self.__class__.__name__} must implement this method.")
+        raise NotImplementedError(f"Subclass {self.__class__.__name__} must implement this method.")
 
     @abstractmethod
-    def post_process(self, data:Any) -> Union[Image, Any]:
+    def post_process(self, data: Any) -> Union[Image, Any]:
         """Transform the prediction results from the model(s).
 
         This method must be overridden by a derived class.
@@ -74,5 +69,4 @@ def post_process(self, data:Any) -> Union[Image, Any]:
         Raises:
             NotImplementedError: When the subclass does not override this method.
         """
-        raise NotImplementedError(
-            f"Subclass {self.__class__.__name__} must implement this method.")
+        raise NotImplementedError(f"Subclass {self.__class__.__name__} must implement this method.")
diff --git a/monai/deploy/operators/monai_seg_inference_operator.py b/monai/deploy/operators/monai_seg_inference_operator.py
index fcfe7f57..3b259a65 100644
--- a/monai/deploy/operators/monai_seg_inference_operator.py
+++ b/monai/deploy/operators/monai_seg_inference_operator.py
@@ -10,10 +10,11 @@
 # limitations under the License.
 
 from threading import Lock
-from typing import TYPE_CHECKING, Any, Dict, List, Sequence, Optional, Union
+from typing import Any, Dict, List, Optional, Sequence, Union
+
 import numpy as np
 
-from monai.deploy.utils.importutil import dist_module_path, optional_import
+from monai.deploy.utils.importutil import optional_import
 
 torch, _ = optional_import("torch", "1.5")
 np_str_obj_array_pattern, _ = optional_import("torch.utils.data._utils.collate", name="np_str_obj_array_pattern")
@@ -26,22 +27,13 @@
 Compose, _ = optional_import("monai.transforms", name="Compose")
 sliding_window_inference, _ = optional_import("monai.inferers", name="sliding_window_inference")
 
-from monai.deploy.exceptions import UnknownTypeError
-from monai.deploy.core import (
-    ExecutionContext,
-    InputContext,
-    OutputContext,
-    IOType,
-    Image,
-    input,
-    output,
-    env
-)
+from monai.deploy.core import ExecutionContext, Image, InputContext, IOType, OutputContext, env, input, output
 
 from .inference_operator import InferenceOperator
 
 __all__ = ["MonaiSegInferenceOperator", "InMemImageReader"]
 
+
 @input("image", Image, IOType.IN_MEMORY)
 @output("seg_image", Image, IOType.IN_MEMORY)
 @env(pip_packages=["monai==0.6.0", "torch>=1.5", "numpy>=1.17"])
@@ -55,15 +47,12 @@ class MonaiSegInferenceOperator(InferenceOperator):
     If specified in the post transforms, results may also be saved to disk.
 
     """
+
     # For testing the app directly, the model should be at the following path.
-    MODEL_LOCAL_PATH = 'model/model.ts'
-
-    def __init__(self,
-        roi_size: Union[Sequence[int], int],
-        pre_transforms: Compose,
-        post_transforms: Compose,
-        *args,
-        **kwargs
+    MODEL_LOCAL_PATH = "model/model.ts"
+
+    def __init__(
+        self, roi_size: Union[Sequence[int], int], pre_transforms: Compose, post_transforms: Compose, *args, **kwargs
     ):
         """Creates a instance of this class.
 
@@ -71,14 +60,14 @@ def __init__(self,
             roi_size (Union[Sequence[int], int]): The tensor size used in inference.
             pre_transforms (Compose): Monai Compose oject used for pre-transforms.
             pre_transforms (Compose): Monai Compose oject used for pre-transforms.
-    """
+        """
 
         super().__init__()
         self._executing = False
         self._lock = Lock()
-        self._input_dataset_key = 'image'
-        self._pred_dataset_key = 'pred'
-        self._input_image = None # Image will come in when compute is called.
+        self._input_dataset_key = "image"
+        self._pred_dataset_key = "pred"
+        self._input_image = None  # Image will come in when compute is called.
         self._reader = None
         self._roi_size = ensure_tuple(roi_size)
         self._pre_transform = pre_transforms
@@ -88,16 +77,18 @@ def __init__(self,
     def roi_size(self):
         """The ROI size of tensors used in prediction."""
         return self._roi_size
+
     @roi_size.setter
     def roi_size(self, roi_size: Union[Sequence[int], int]):
-         self._roi_size = ensure_tuple(roi_size)
+        self._roi_size = ensure_tuple(roi_size)
 
     @property
     def input_dataset_key(self):
         """This is the input image key name used in dictionary based Monai pre-transforms."""
         return self._input_dataset_key
+
     @input_dataset_key.setter
-    def input_dataset_key(self, val:str):
+    def input_dataset_key(self, val: str):
         if not val or len(val) < 1:
             raise ValueError("Value cannot be None or blank.")
         self._input_dataset_key = val
@@ -106,8 +97,9 @@ def input_dataset_key(self, val:str):
     def pred_dataset_key(self):
         """This is the prediction key name used in dictionary based Monai post-transforms."""
         return self._pred_dataset_key
+
     @pred_dataset_key.setter
-    def pred_dataset_key(self, val:str):
+    def pred_dataset_key(self, val: str):
         if not val or len(val) < 1:
             raise ValueError("Value cannot be None or blank.")
         self._pred_dataset_key = val
@@ -128,7 +120,7 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
         try:
             input_image = input.get("image")
             if not input_image:
-                raise ValueError('Input is None.')
+                raise ValueError("Input is None.")
 
             img_name = "Img_in_Mem"
             try:
@@ -140,14 +132,12 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
             post_transforms = self._post_transforms
             self._reader = InMemImageReader(input_image)
 
-            pre_transforms = self._pre_transform if self._pre_transform else \
-                self.pre_process(self._reader)
+            pre_transforms = self._pre_transform if self._pre_transform else self.pre_process(self._reader)
 
             print("pre-transform:")
             print(vars(pre_transforms.flatten()))
 
-            post_transforms = self._post_transforms if self._post_transforms  else \
-                self.post_process(pre_transforms)
+            post_transforms = self._post_transforms if self._post_transforms else self.post_process(pre_transforms)
 
             print("post-transform:")
             print(vars(post_transforms.flatten()))
@@ -157,30 +147,30 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
                 # `context.models.get(model_name)` returns a model instance if exists.
                 # If model_name is not specified and only one model exists, it returns that model.
                 model = context.models.get()
-                print(f'Model path: {model.path}')
-                print(f'Model name (expected None): {model.name}')
+                print(f"Model path: {model.path}")
+                print(f"Model name (expected None): {model.name}")
             else:
-                print(f'Loading TorchScript model from: {MonaiSegInferenceOperator.MODEL_LOCAL_PATH}')
+                print(f"Loading TorchScript model from: {MonaiSegInferenceOperator.MODEL_LOCAL_PATH}")
                 model = torch.jit.load(MonaiSegInferenceOperator.MODEL_LOCAL_PATH)
 
-            dataset = Dataset(data=[{self._input_dataset_key:img_name}], transform=pre_transforms)
+            dataset = Dataset(data=[{self._input_dataset_key: img_name}], transform=pre_transforms)
             dataloader = DataLoader(dataset, batch_size=1, shuffle=False, num_workers=4)
             device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 
             with torch.no_grad():
                 for d in dataloader:
                     images = d[self._input_dataset_key].to(device)
-                    sw_batch_size=4
+                    sw_batch_size = 4
                     d[self._pred_dataset_key] = sliding_window_inference(
                         inputs=images,
                         roi_size=self._roi_size,
                         sw_batch_size=sw_batch_size,
                         overlap=0.5,
-                        predictor=model
+                        predictor=model,
                     )
                     d = [post_transforms(i) for i in decollate_batch(d)]
                     out_ndarray = d[0][self._pred_dataset_key].cpu().numpy()
-                    print(f'Post transformed ndarray shape: {out_ndarray.shape}')
+                    print(f"Post transformed ndarray shape: {out_ndarray.shape}")
                     # Need to squeeze out the channel dim fist
                     out_ndarray = np.squeeze(out_ndarray, 0)
                     # NOTE: The domain Image object simply contains a Arraylike obj as image as of now.
@@ -191,8 +181,8 @@ def compute(self, input: InputContext, output: OutputContext, context: Execution
                     #       dim moved back to first, otherwise the seg ndarray would be flipped compared to
                     #       the DICOM pixel array, causing the DICOM Seg Writer generate flipped seg images.
                     out_ndarray = np.swapaxes(out_ndarray, 2, 0)
-                    print(f'Output Seg image numpy array shaped: {out_ndarray.shape}')
-                    print(f'Output Seg image pixel max value: {np.amax(out_ndarray)}')
+                    print(f"Output Seg image numpy array shaped: {out_ndarray.shape}")
+                    print(f"Output Seg image pixel max value: {np.amax(out_ndarray)}")
                     out_image = Image(out_ndarray)
                     output.set(out_image, "seg_image")
         finally:
@@ -208,10 +198,9 @@ def pre_process(self, img_reader) -> Compose:
         Raises:
             NotImplementedError: When the subclass does not override this method.
         """
-        raise NotImplementedError(
-             f"Subclass {self.__class__.__name__} must implement this method.")
+        raise NotImplementedError(f"Subclass {self.__class__.__name__} must implement this method.")
 
-    def post_process(self, pre_transforms: Compose, out_dir:str="./infer_out") -> Compose:
+    def post_process(self, pre_transforms: Compose, out_dir: str = "./infer_out") -> Compose:
         """Transform the prediction results from the model(s).
 
         This method must be overridden by a derived class.
@@ -219,10 +208,9 @@ def post_process(self, pre_transforms: Compose, out_dir:str="./infer_out") -> Co
         Raises:
             NotImplementedError: When the subclass does not override this method.
         """
-        raise NotImplementedError(
-             f"Subclass {self.__class__.__name__} must implement this method.")
+        raise NotImplementedError(f"Subclass {self.__class__.__name__} must implement this method.")
 
-    def predict(self, data:Any, *args, **kwargs) -> Union[Image, Any]:
+    def predict(self, data: Any, *args, **kwargs) -> Union[Image, Any]:
         """Prdicts results using the models(s) with input tensors.
 
         This method must be overridden by a derived class.
@@ -230,8 +218,8 @@ def predict(self, data:Any, *args, **kwargs) -> Union[Image, Any]:
         Raises:
             NotImplementedError: When the subclass does not override this method.
         """
-        raise NotImplementedError(
-            f"Subclass {self.__class__.__name__} must implement this method.")
+        raise NotImplementedError(f"Subclass {self.__class__.__name__} must implement this method.")
+
 
 class InMemImageReader(ImageReader):
     """Loads the App SDK Image object from memory.
@@ -239,6 +227,7 @@ class InMemImageReader(ImageReader):
     This is derived from Monai ImageReader. Instead of reading image from file system, this
     class simply converts a in-memory SDK Image object to the expected formats from ImageReader.
     """
+
     def __init__(self, input_image: Image, channel_dim: Optional[int] = None, **kwargs):
         super().__init__()
         self.input_image = input_image
@@ -264,7 +253,7 @@ def get_data(self, input_image):
 
         for i in ensure_tuple(self.input_image):
             if not isinstance(i, Image):
-                raise TypeError('Only object of Image type is supported.')
+                raise TypeError("Only object of Image type is supported.")
             data = i.asnumpy()
             img_array.append(data)
             header = self._get_meta_dict(i)
@@ -287,14 +276,15 @@ def _get_meta_dict(self, img: Image) -> Dict:
         # So, for now have to get to the Image generator, namely DICOMSeriesToVolumeOperator, and
         # rely on its published metadata.
 
-
         # Recall that the column and row data for pydicom pixel_array had been switched, and the depth
         # is the last dim in DICOMSeriesToVolumeOperator
-        meta_dict["spacing"] = np.asarray([
-            img_meta_dict["col_pixel_spacing"],
-            img_meta_dict["row_pixel_spacing"],
-            img_meta_dict["depth_pixel_spacing"]
-        ])
+        meta_dict["spacing"] = np.asarray(
+            [
+                img_meta_dict["col_pixel_spacing"],
+                img_meta_dict["row_pixel_spacing"],
+                img_meta_dict["depth_pixel_spacing"],
+            ]
+        )
         meta_dict["original_affine"] = np.asarray(img_meta_dict["nifti_affine_transform"])
         meta_dict["affine"] = meta_dict["original_affine"]
         meta_dict["spatial_shape"] = np.asarray(img.asnumpy().shape)
@@ -303,6 +293,7 @@ def _get_meta_dict(self, img: Image) -> Dict:
 
         return meta_dict
 
+
 # Reuse Monai code for the derived ImageReader
 def _copy_compatible_dict(from_dict: Dict, to_dict: Dict):
     if not isinstance(to_dict, dict):
@@ -326,6 +317,7 @@ def _copy_compatible_dict(from_dict: Dict, to_dict: Dict):
                 f"Got {from_dict[shape_key]} and {to_dict[shape_key]}."
             )
 
+
 def _stack_images(image_list: List, meta_dict: Dict):
     if len(image_list) <= 1:
         return image_list[0]
@@ -333,4 +325,3 @@ def _stack_images(image_list: List, meta_dict: Dict):
         raise RuntimeError("can not read a list of images which already have channel dimension.")
     meta_dict["original_channel_dim"] = 0
     return np.stack(image_list, axis=0)
-
diff --git a/monai/deploy/operators/png_converter_operator.py b/monai/deploy/operators/png_converter_operator.py
index c8cc2a23..2ea57ffe 100644
--- a/monai/deploy/operators/png_converter_operator.py
+++ b/monai/deploy/operators/png_converter_operator.py
@@ -21,9 +21,9 @@
     IOType,
     Operator,
     OutputContext,
+    env,
     input,
     output,
-    env
 )
 from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator
 from monai.deploy.operators.dicom_series_to_volume_operator import DICOMSeriesToVolumeOperator
diff --git a/monai/deploy/packager/constants.py b/monai/deploy/packager/constants.py
index 9469344e..af159c11 100644
--- a/monai/deploy/packager/constants.py
+++ b/monai/deploy/packager/constants.py
@@ -9,10 +9,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+
 class DefaultValues:
     """
     This class contains default values for various parameters.
     """
+
     DOCKER_FILE_NAME = "dockerfile"
     # TODO(KavinKrishnan): Decide a default image to use.
     # BASE_IMAGE = "nvcr.io/nvidia/cuda:11.1-runtime-ubuntu20.04"
diff --git a/monai/deploy/packager/util.py b/monai/deploy/packager/util.py
index 5dcfb97d..d8e87679 100644
--- a/monai/deploy/packager/util.py
+++ b/monai/deploy/packager/util.py
@@ -19,6 +19,7 @@
 from argparse import Namespace
 from typing import Dict
 
+from monai.deploy.exceptions import WrongValueError
 from monai.deploy.packager.constants import DefaultValues
 from monai.deploy.packager.templates import Template
 from monai.deploy.utils.fileutil import checksum
@@ -57,7 +58,10 @@ def initialize_args(args: Namespace) -> Dict:
 
     # Obtain SDK provide application values
     app_obj = get_application(args.application)
-    processed_args["application_info"] = app_obj.get_package_info(args.model)
+    if app_obj:
+        processed_args["application_info"] = app_obj.get_package_info(args.model)
+    else:
+        raise WrongValueError("Application from '{}' not found".format(args.application))
 
     return processed_args
 
@@ -177,7 +181,8 @@ def build_spinning_wheel():
     print("Building MONAI Application Package... ")
 
     while proc.poll() is None:
-        logger.debug(proc.stdout.readline().decode("utf-8"))
+        if proc.stdout:
+            logger.debug(proc.stdout.readline().decode("utf-8"))
         sys.stdout.write(next(spinner))
         sys.stdout.flush()
         sys.stdout.write("\b")
diff --git a/monai/deploy/utils/argparse_types.py b/monai/deploy/utils/argparse_types.py
index bef5c321..4d180fcb 100644
--- a/monai/deploy/utils/argparse_types.py
+++ b/monai/deploy/utils/argparse_types.py
@@ -13,10 +13,9 @@
 import logging
 from pathlib import Path
 
-from monai.deploy.utils.spinner import ProgressSpinner
-
 logger = logging.getLogger(__name__)
 
+
 def valid_dir_path(path: str) -> Path:
     """Helper type checking and type converting method for ArgumentParser.add_argument
     to convert string input to pathlib.Path if the given path exists and it is a directory path.
diff --git a/monai/deploy/utils/importutil.py b/monai/deploy/utils/importutil.py
index b37576a6..ee439ec4 100644
--- a/monai/deploy/utils/importutil.py
+++ b/monai/deploy/utils/importutil.py
@@ -15,7 +15,7 @@
 import warnings
 from importlib import import_module
 from pathlib import Path
-from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple, Type, Union
+from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Type, Union
 
 import pkg_resources
 
@@ -82,7 +82,7 @@ def get_application(path: Union[str, Path]) -> Optional["Application"]:
     # Get the Application class from the module and return an instance of it
     for var in vars.keys():
         if not var.startswith("_"):  # skip private variables
-            app_cls = vars[var]
+            app_cls: Type[Application] = vars[var]
 
             if is_subclass(app_cls, Application._class_id):
                 if path.is_file():
@@ -270,7 +270,16 @@ def dist_module_path(project_name: str) -> str:
     return ""
 
 
-def dist_requires(project_name: str) -> str:
+def is_module_installed(project_name: str) -> bool:
+    distributions: Dict = {v.key: v for v in pkg_resources.working_set}
+    dist: Any = distributions.get(project_name)
+    if dist:
+        return True
+    else:
+        return False
+
+
+def dist_requires(project_name: str) -> List[str]:
     distributions: Dict = {v.key: v for v in pkg_resources.working_set}
     dist: Any = distributions.get(project_name)
     if hasattr(dist, "requires"):
@@ -279,6 +288,8 @@ def dist_requires(project_name: str) -> str:
 
 
 if __name__ == "__main__":
+    """Utility functions that can be used in the command line."""
+
     argv = sys.argv
     if len(argv) == 3 and argv[1] == "is_dist_editable":
         if is_dist_editable(argv[2]):
@@ -292,6 +303,12 @@ def dist_requires(project_name: str) -> str:
             sys.exit(0)
         else:
             sys.exit(1)
+    if len(argv) == 3 and argv[1] == "is_module_installed":
+        is_installed = is_module_installed(argv[2])
+        if is_installed:
+            sys.exit(0)
+        else:
+            sys.exit(1)
     if len(argv) == 3 and argv[1] == "dist_requires":
         requires = dist_requires(argv[2])
         if requires:
@@ -299,3 +316,9 @@ def dist_requires(project_name: str) -> str:
             sys.exit(0)
         else:
             sys.exit(1)
+    if len(argv) >= 3 and argv[1] == "get_package_info":
+        import json
+
+        app = get_application(argv[2])
+        if app:
+            print(json.dumps(app.get_package_info(argv[3] if len(argv) > 3 else ""), indent=2))
diff --git a/monai/deploy/utils/spinner.py b/monai/deploy/utils/spinner.py
index 578cd8f0..3a6ad0a6 100644
--- a/monai/deploy/utils/spinner.py
+++ b/monai/deploy/utils/spinner.py
@@ -20,7 +20,7 @@ class ProgressSpinner:
     """
 
     def __init__(self, message, delay=0.2):
-        self.spinner_symbols = itertools.cycle(['-', '/', '|', '\\'])
+        self.spinner_symbols = itertools.cycle(["-", "/", "|", "\\"])
         self.delay = delay
         self.stop_event = Event()
         self.spinner_visible = False
@@ -47,12 +47,12 @@ def _write_next_symbol(self):
     def _remove_spinner(self, cleanup=False):
         with self._spinner_lock:
             if self.spinner_visible:
-                sys.stdout.write('\b')
+                sys.stdout.write("\b")
                 self.spinner_visible = False
                 if cleanup:
                     # overwrite spinner symbol with whitespace
-                    sys.stdout.write(' ')
-                    sys.stdout.write('\r')
+                    sys.stdout.write(" ")
+                    sys.stdout.write("\r")
                 sys.stdout.flush()
 
     def start(self):
@@ -73,6 +73,6 @@ def stop(self):
             self.stop_event.set()
             self._remove_spinner(cleanup=True)
             self.spinner_process.join()
-            sys.stdout.write('\n')
+            sys.stdout.write("\n")
         else:
-            sys.stdout.write('\r')
+            sys.stdout.write("\r")
diff --git a/pyproject.toml b/pyproject.toml
index 32100139..372a4e33 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -26,8 +26,10 @@ exclude = '''
     | build
     | dist
   )/
-  # also separately exclude a file named versioneer.py
-  | monai/deploy/_version.py
+  # also separately exclude a file named versioneer.py and _version.py
+  | versioneer.py
+  | .+/versioneer.py
+  | .+/_version.py
 )
 '''
 
diff --git a/run b/run
index 4de5fbf1..e2c999d1 100755
--- a/run
+++ b/run
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright 2020 - 2021 MONAI Consortium
+# Copyright 2021 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
@@ -20,6 +20,10 @@ init_globals() {
     fi
 
     export TOP=$(git rev-parse --show-toplevel || $(dirname "${RUN_SCRIPT_FILE}"))
+    MONAI_PY_EXE=${MONAI_PY_EXE:-"python3"}
+    export MONAI_PY_EXE
+
+    DO_DRY_RUN="false"  # print commands but do not execute them. Used by run_command
 }
 
 ################################################################################
@@ -30,14 +34,14 @@ init_globals() {
 # Get list of available commands from a given input file.
 #
 # Available commands and command summary are extracted by checking a pattern
-# "_desc() { echo '".
+# "_desc() { c_echo '".
 # Section title is extracted by checking a pattern "# Section: ".
 # This command is used for listing available commands in CLI.
 #
 # e.g.)
 #   "# Section: String/IO functions"
 #     => "# String/IO functions"
-#   "to_lower_desc() { echo 'Convert to lower case"
+#   "to_lower_desc() { c_echo 'Convert to lower case"
 #     => "to_lower ----------------- Convert to lower case"
 #
 # Arguments:
@@ -46,23 +50,32 @@ init_globals() {
 #   Print list of available commands from $1
 #######################################
 get_list_of_available_commands() {
+    local mode="color"
+    if [ "${1:-}" = "color" ]; then
+        mode="color"
+        shift
+    elif [ "${1:-}" = "nocolor" ]; then
+        mode="nocolor"
+        shift
+    fi
+
     local file_name="$1"
     if [ ! -e "$1" ]; then
         echo "$1 doesn't exist!"
     fi
 
     local line_str='--------------------------------'
-    local IFS= cmd_lines="$(IFS= cat "$1" | grep -E -e "^(([[:alpha:]_[:digit:]]+)_desc\(\)|# Section: )" | sed "s/_desc() *{ *echo '/ : /")"
+    local IFS= cmd_lines="$(IFS= cat "$1" | grep -E -e "^(([[:alpha:]_[:digit:]]+)_desc\(\)|# Section: )" | sed "s/_desc() *{ *c_echo '/ : /")"
     local line
     while IFS= read -r line; do
         local cmd=$(echo "$line" | cut -d":" -f1)
         local desc=$(echo "$line" | cut -d":" -f2-)
         if [ "$cmd" = "# Section" ]; then
-            c_echo B "${desc}"
+            c_echo ${mode} B "${desc}"
         else
             # there is no substring operation in 'sh' so use 'cut'
             local dash_line="$(echo "${line_str}" | cut -c ${#cmd}-)"  #  = "${line_str:${#cmd}}"
-             c_echo Y "   ${cmd}" w " ${dash_line} ${desc}"
+             c_echo ${mode} Y "   ${cmd}" w " ${dash_line} ${desc}"
         fi
         # use <<EOF, not '<<<"$cmd_lines"' to be executable in sh
     done <<EOF
@@ -85,6 +98,15 @@ c_str() {
     local color=39
     local attr=0
     local text=""
+    local mode="color"
+    if [ "${1:-}" = "color" ]; then
+        mode="color"
+        shift
+    elif [ "${1:-}" = "nocolor" ]; then
+        mode="nocolor"
+        shift
+    fi
+
     for i in "$@"; do
         case "$i" in
             r|R)
@@ -126,20 +148,42 @@ c_str() {
             *)
                 text="${text}$i"
         esac
-        if [ ${old_color} -ne ${color} ] || [ ${old_attr} -ne ${attr} ]; then
-            text="${text}\033[${attr};${color}m"
-            old_color=$color
-            old_attr=$attr
+        if [ "${mode}" = "color" ]; then
+            if [ ${old_color} -ne ${color} ] || [ ${old_attr} -ne ${attr} ]; then
+                text="${text}\033[${attr};${color}m"
+                old_color=$color
+                old_attr=$attr
+            fi
         fi
     done
     /bin/echo -en "$text"
 }
 
 c_echo() {
+    # Select color/nocolor based on the first argument
+    local mode="color"
+    if [ "${1:-}" = "color" ]; then
+        mode="color"
+        shift
+    elif [ "${1:-}" = "nocolor" ]; then
+        mode="nocolor"
+        shift
+    else
+        if [ ! -t 1 ]; then
+            mode="nocolor"
+        fi
+    fi
+
     local old_opt="$(shopt -op xtrace)" # save old xtrace option
     set +x # unset xtrace
-    local text="$(c_str "$@")"
-    /bin/echo -e "$text\033[0m"
+
+    if [ "${mode}" = "color" ]; then
+        local text="$(c_str color "$@")"
+        /bin/echo -e "$text\033[0m"
+    else
+        local text="$(c_str nocolor "$@")"
+        /bin/echo -e "$text"
+    fi
     eval "${old_opt}" # restore old xtrace option
 }
 
@@ -196,12 +240,18 @@ run_command() {
     local status=0
     local cmd="$*"
 
-    c_echo B "$(date -u '+%Y-%m-%d %H:%M:%S') " W "\$ " G "${cmd}"
+    if [ "${DO_DRY_RUN}" != "true" ]; then
+        c_echo B "$(date -u '+%Y-%m-%d %H:%M:%S') " W "\$ " G "${cmd}"
+    else
+        c_echo B "$(date -u '+%Y-%m-%d %H:%M:%S') " C "[dryrun] " W "\$ " G "${cmd}"
+    fi
 
     [ "$(echo -n "$@")" = "" ] && return 1 # return 1 if there is no command available
 
-    "$@"
-    status=$?
+    if [ "${DO_DRY_RUN}" != "true" ]; then
+        "$@"
+        status=$?
+    fi
 
     return $status
 }
@@ -226,21 +276,41 @@ retry() {
     return 0
 }
 
+#==================================================================================
+# Section: Inspect
+#==================================================================================
+
+get_package_info_desc() { c_echo 'Get package info from app(& model) path
+
+Arguments:
+  $1 - Application folder or file path
+  $2 - Model path (optional)
+'
+}
+get_package_info() {
+    local app_path="${1:-}"
+    local model_path="${2:-}"
+
+    [ -z "${app_path}" ] && c_echo_err R "No application path specified." && return 1
+
+    ${MONAI_PY_EXE} $TOP/monai/deploy/utils/importutil.py get_package_info ${app_path} ${model_path}
+}
+
 #==================================================================================
 # Section: Build
 #==================================================================================
 
-install_python_dev_deps_() {
+install_python_dev_deps() {
     if [ -n "${VIRTUAL_ENV}" ] || [ -n "${CONDA_PREFIX}" ]; then
-        run_command python3 -m pip install -q -U setuptools pip wheel
-        run_command python3 -m pip install -q -r ${TOP}/requirements-dev.txt
-        run_command python3 -m pip install -q -r ${TOP}/requirements-examples.txt
+        run_command ${MONAI_PY_EXE} -m pip install -q -U setuptools pip wheel
+        run_command ${MONAI_PY_EXE} -m pip install -q -r ${TOP}/requirements-dev.txt
+        run_command ${MONAI_PY_EXE} -m pip install -q -r ${TOP}/requirements-examples.txt
 
     else
         c_echo_err R "You must be in a virtual environment to install dependencies."
         if [ ! -e "$TOP/.venv/dev/bin/python3" ]; then
             c_echo_err W "Installing a virtual environment at " G "$TOP/.venv/dev" W " ..."
-            run_command python3 -m venv "$TOP/.venv/dev"
+            run_command ${MONAI_PY_EXE} -m venv "$TOP/.venv/dev"
         fi
 
         c_echo_err W "Please activate the virtual environment at " G "$TOP/.venv/dev" W " and execute the setup command again."
@@ -254,10 +324,10 @@ install_python_dev_deps_() {
     # This solves an issue with separate package folders for 'monai' and 'monai-app-sdk' like below:
     # - 'monai': installed with 'pip install monai'
     # - 'monai-app-sdk': installed with 'pip install -e .  # installed with development(edit) mode
-    local monai_package_path=$(python3 $TOP/monai/deploy/utils/importutil.py dist_module_path monai)
-    local sdk_package_path=$(python3 $TOP/monai/deploy/utils/importutil.py dist_module_path monai-app-sdk)
+    local monai_package_path=$(${MONAI_PY_EXE} $TOP/monai/deploy/utils/importutil.py dist_module_path monai)
+    local sdk_package_path=$(${MONAI_PY_EXE} $TOP/monai/deploy/utils/importutil.py dist_module_path monai-app-sdk)
     local is_sdk_editable="false"
-    if python3 $TOP/monai/deploy/utils/importutil.py is_dist_editable monai-app-sdk; then
+    if ${MONAI_PY_EXE} $TOP/monai/deploy/utils/importutil.py is_dist_editable monai-app-sdk; then
         is_sdk_editable="true"
     fi
 
@@ -268,16 +338,16 @@ install_python_dev_deps_() {
     if [ "${is_sdk_editable}" == "false" ]; then
         c_echo W "Installing monai-app-sdk in edit mode..."
         if [ -n "${VIRTUAL_ENV}" ] || [ -n "${CONDA_PREFIX}" ]; then
-            run_command python3 -m pip install -e .
+            run_command ${MONAI_PY_EXE} -m pip install -e .
         else
             c_echo_err R "You must be in a virtual environment to install monai-app-sdk in edit mode."
         fi
 
-        if python3 $TOP/monai/deploy/utils/importutil.py is_dist_editable monai-app-sdk; then
+        if ${MONAI_PY_EXE} $TOP/monai/deploy/utils/importutil.py is_dist_editable monai-app-sdk; then
             is_sdk_editable="true"
         fi
 
-        sdk_package_path=$(python3 $TOP/monai/deploy/utils/importutil.py dist_module_path monai-app-sdk)
+        sdk_package_path=$(${MONAI_PY_EXE} $TOP/monai/deploy/utils/importutil.py dist_module_path monai-app-sdk)
         c_echo b "sdk_package_path  : " Z "${sdk_package_path}"
         c_echo b "is_sdk_editable   : " Z "${is_sdk_editable}"
     fi
@@ -295,18 +365,410 @@ install_python_dev_deps_() {
     hash -r
 }
 
-setup_desc() { echo 'Setup development environment
+setup_desc() { c_echo 'Setup development environment
 '
 }
 setup() {
-    install_python_dev_deps_
+    install_python_dev_deps
+}
+
+clean_desc() { c_echo 'Clean up temporary files and uninstall monai-app-sdk
+'
+}
+clean() {
+    c_echo W 'Cleaning up temporary files and run "' "${MONAI_PY_EXE}" ' setup.py develop --uninstall"...'
+
 }
 
 #==================================================================================
 # Section: Test
 #==================================================================================
 
-test_desc() { echo 'Execute test cases
+get_platform_name() {
+    ${MONAI_PY_EXE} -c "import platform; print(platform.system().lower())"
+}
+
+get_python_version() {
+    ${MONAI_PY_EXE} -c "from sys import version_info; print(f'{version_info.major}.{version_info.minor}')"
+}
+
+check_import() {
+    [ -z "${1:-}" ] && c_echo_err R "No module specified." && return 1
+
+    local module_name="${1:-}"
+    c_echo W "Checking import of module '" b "${module_name}" W "'..."
+    run_command ${MONAI_PY_EXE} -c "import ${1}"
+}
+
+is_module_installed() {
+    local module_name="${1:-}"
+    local result=0
+
+    [ -z "${module_name}" ] && c_echo_err R "No module name specified." && return 1
+
+    ${MONAI_PY_EXE} $TOP/monai/deploy/utils/importutil.py is_module_installed "${module_name}"
+    result=$?
+    return ${result}
+}
+
+# Edit 'setup.cfg' ([isort] section) if you want to skip formatting for particular files.
+isort_format() {
+    local command="${1:-}"
+    local result=0
+
+    local old_opt="$(shopt -op xtrace)" # save old xtrace option
+    set +e # unset error trap
+
+    if [ "${command}" = "fix" ]; then
+        c_echo W "Fixing import order..."
+    else
+        c_echo W "Checking import order..."
+    fi
+
+    # Ensure that the necessary packages for code format testing are installed
+    if ! is_module_installed isort; then
+        install_python_dev_deps
+    fi
+
+    run_command ${MONAI_PY_EXE} -m isort --version
+
+    if [ "${command}" = "fix" ]; then
+        run_command ${MONAI_PY_EXE} -m isort "${TOP}"
+    else
+        run_command ${MONAI_PY_EXE} -m isort --check "${TOP}"
+    fi
+    result=$?
+
+    if [ ${result} -ne 0 ]; then
+        c_echo_err R "isort check failed!"
+        c_echo_err W "Please run auto style fixes: " G "./run check --autofix"
+        exit ${result}
+    else
+        c_echo_err G "isort check passed!"
+    fi
+
+    eval "${old_opt}" # restore old xtrace option
+}
+
+# Edit 'pyproject.toml' ([tool.black] section) if you want to skip formatting for particular files.
+black_format() {
+    local command="${1:-}"
+    local result=0
+
+    local old_opt="$(shopt -op xtrace)" # save old xtrace option
+    set +e # unset error trap
+
+    if [ "${command}" = "fix" ]; then
+        c_echo W "Fixing styles using black..."
+    else
+        c_echo W "Checking styles using black..."
+    fi
+
+    # Ensure that the necessary packages for code format testing are installed
+    if ! is_module_installed black; then
+        install_python_dev_deps
+    fi
+
+    run_command ${MONAI_PY_EXE} -m black --version
+
+    if [ "${command}" = "fix" ]; then
+        run_command ${MONAI_PY_EXE} -m black "${TOP}"
+    else
+        run_command ${MONAI_PY_EXE} -m black --check "${TOP}"
+    fi
+    result=$?
+
+    if [ ${result} -ne 0 ]; then
+        c_echo_err R "black check failed!"
+        c_echo_err W "Please run auto style fixes: " G "./run check --autofix"
+        exit ${result}
+    else
+        c_echo_err G "black check passed!"
+    fi
+
+    eval "${old_opt}" # restore old xtrace option
+}
+
+# Edit 'setup.cfg' ([flake8] section) if you want to skip formatting for particular files.
+flake8_format() {
+    local command="${1:-}"
+    local result=0
+
+    local old_opt="$(shopt -op xtrace)" # save old xtrace option
+    set +e # unset error trap
+
+    c_echo W "Checking styles using flake8..."
+
+    # Ensure that the necessary packages for code format testing are installed
+    if ! is_module_installed flake8; then
+        install_python_dev_deps
+    fi
+
+    run_command ${MONAI_PY_EXE} -m flake8 --version
+
+    run_command ${MONAI_PY_EXE} -m flake8 "${TOP}" --count --statistics
+    result=$?
+
+    if [ ${result} -ne 0 ]; then
+        c_echo_err R "flake8 check failed!"
+        exit ${result}
+    else
+        c_echo_err G "flake8 check passed!"
+    fi
+
+    eval "${old_opt}" # restore old xtrace option
+}
+
+# Edit 'setup.cfg' ([pytype] section) if you want to skip formatting for particular files.
+# You can use '# type: ignore' to ignore a specific line in a file.
+pytype_format() {
+    local num_workers="${1:-$(nproc)}"
+    local result=0
+
+    local old_opt="$(shopt -op xtrace)" # save old xtrace option
+    set +e # unset error trap
+
+    c_echo W "Checking styles using pytype..."
+
+    local platform_name="$(get_platform_name)"
+
+    # Skip if it is MacOS
+    if [ "${platform_name}" = "darwin" ]; then
+        c_echo_err R "pytype does not work on MacOS (https://github.com/google/pytype/issues/661), skipping the checking."
+        return 0
+    fi
+
+    # Ensure that the necessary packages for code format testing are installed
+    if ! is_module_installed pytype; then
+        install_python_dev_deps
+    fi
+
+    run_command ${MONAI_PY_EXE} -m pytype --version
+
+    local python_version="$(get_python_version)"
+
+    pushd "${TOP}" > /dev/null
+    run_command ${MONAI_PY_EXE} -m pytype -j "${num_workers}" --python-version="${python_version}"
+    result=$?
+    popd > /dev/null
+
+    if [ ${result} -ne 0 ]; then
+        c_echo_err R "pytype check failed!"
+        exit ${result}
+    else
+        c_echo_err G "pytype check passed!"
+    fi
+
+    eval "${old_opt}" # restore old xtrace option
+}
+
+# Edit 'setup.cfg' ([mypy] section) if you want to skip formatting for particular files.
+# You can use '# type: ignore' to ignore a specific line in a file.
+mypy_format() {
+    local command="${1:-}"
+    local result=0
+
+    local old_opt="$(shopt -op xtrace)" # save old xtrace option
+    set +e # unset error trap
+
+    c_echo W "Checking styles using mypy..."
+
+    local platform_name="$(get_platform_name)"
+
+    # Ensure that the necessary packages for code format testing are installed
+    if ! is_module_installed mypy; then
+        install_python_dev_deps
+    fi
+
+    run_command ${MONAI_PY_EXE} -m mypy --version
+
+    local python_version="$(get_python_version)"
+    #MYPYPATH="${TOP}/monai/deploy"
+
+    # https://github.com/python/mypy/issues/8584: Redesign import handling
+    # https://github.com/python/mypy/issues/10172: Issue with `pip install -e .`
+    # - https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-explicit-package-bases
+    # - https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-paths-to-modules
+    #   - Using `--namespace-packages --explicit-package-bases` solves the issue with the current folder structure.
+    run_command ${MONAI_PY_EXE} -m mypy --namespace-packages --explicit-package-bases "${TOP}"
+    result=$?
+
+    if [ ${result} -ne 0 ]; then
+        c_echo_err R "mypy check failed!"
+        exit ${result}
+    else
+        c_echo_err G "mypy check passed!"
+    fi
+
+    eval "${old_opt}" # restore old xtrace option
+}
+
+check_desc() { c_echo 'Check code quality
+
+Examples:
+./run check -f                      # run coding style and static type checking.
+./run check --autofix               # run automatic code formatting using "isort" and "black".
+
+Code style check options:
+    --black           : perform "black" code format checks
+    --autofix         : format code using "isort" and "black"
+    --isort           : perform "isort" import sort checks
+    --flake8          : perform "flake8" code format checks
+
+Python type check options:
+    --pytype          : perform "pytype" static type checks
+    --mypy            : perform "mypy" static type checks
+    -j, --jobs        : number of parallel jobs to run "pytype" (default: ' $(nproc) ')
+
+Misc. options:
+    --dryrun          : display the commands to the screen without running
+    -f, --codeformat  : shorthand to run all code style and static analysis tests
+
+--------------------------------------------------------------------------------
+For bug reports and feature requests, please file an issue at:
+    https://github.com/Project-MONAI/monai-deploy-app-sdk/issues/new/choose
+
+To choose an alternative python executable, set the environmental variable, "MONAI_PY_EXE".
+'
+}
+check() {
+    local do_black_format="false"
+    local do_black_fix="false"
+    local do_isort_format="false"
+    local do_isort_fix="false"
+    local do_flake8_format="false"
+    local do_pytype_format="false"
+    local do_mypy_format="false"
+
+    local num_workers=$(nproc)
+
+    local arg
+
+    # parse arguments
+    while [ $# -gt 0 ]; do
+        arg="$1"
+
+        case ${arg} in
+            --dryrun)
+                DO_DRY_RUN="true"  # set to true to print commands to screen without running
+            ;;
+            -f|--codeformat)
+                do_black_format="true"
+                do_isort_format="true"
+                do_flake8_format="true"
+                do_pytype_format="true"
+                do_mypy_format="true"
+            ;;
+            --black)
+                do_black_format="true"
+            ;;
+            --autofix)
+                do_isort_fix="true"
+                do_black_fix="true"
+                do_isort_format="true"
+                do_black_format="true"
+            ;;
+            --isort)
+                do_isort_format="true"
+            ;;
+            --flake8)
+                do_flake8_format="true"
+            ;;
+            --pytype)
+                do_pytype_format="true"
+            ;;
+            --mypy)
+                do_mypy_format="true"
+            ;;
+            -j|--jobs)
+                num_workers=$2
+                shift
+            ;;
+            *)
+                c_echo_err R "Incorrect command is provided (invalid arg: " B "${arg}" R ")."
+                print_cmd_help_messages check
+            ;;
+        esac
+        shift
+    done
+
+    c_echo B "DO_DRY_RUN:" W " ${DO_DRY_RUN}"
+    c_echo B "do_black_format:" W " ${do_black_format}"
+    c_echo B "do_black_fix:" W " ${do_black_fix}"
+    c_echo B "do_isort_format:" W " ${do_isort_format}"
+    c_echo B "do_isort_fix:" W " ${do_isort_fix}"
+    c_echo B "do_flake8_format:" W " ${do_flake8_format}"
+    c_echo B "do_pytype_format:" W " ${do_pytype_format}"
+    c_echo B "do_mypy_format:" W " ${do_mypy_format}"
+
+    check_import "monai.deploy"
+
+    if [ "${do_isort_format}" = "true" ]; then
+        if [ "${do_isort_fix}" = "true" ]; then
+            isort_format "fix"
+        else
+            isort_format "check"
+        fi
+    fi
+
+    if [ "${do_black_format}" = "true" ]; then
+        if [ "${do_black_fix}" = "true" ]; then
+            black_format "fix"
+        else
+            black_format "check"
+        fi
+    fi
+
+    if [ "${do_flake8_format}" = "true" ]; then
+        flake8_format
+    fi
+
+    if [ "${do_pytype_format}" = "true" ]; then
+        pytype_format "${num_workers}"
+    fi
+
+    if [ "${do_mypy_format}" = "true" ]; then
+        mypy_format
+    fi
+}
+
+pytest_desc() { c_echo 'Run tests with pytest
+
+It executes the following command:
+
+  ' "${MONAI_PY_EXE}"' -m py.test --cache-clear -vv \
+      --cov=monai \
+      --junitxml="'"$TOP/junit-monai-app-sdk.xml"'" \
+      --cov-config="'"$TOP/.coveragerc"'" \
+      --cov-report=xml:"'"$TOP/monai-app-sdk-coverage.xml"'" \
+      --cov-report term \
+      "$@"
+
+Examples:
+  ./run pytest tests/unit
+
+Arguments:
+  $@ - arguments to pass to pytest
+'
+}
+pytest() {
+    local result=0
+
+    pushd $TOP > /dev/null
+    run_command ${MONAI_PY_EXE} -m py.test --cache-clear -vv \
+        --cov=monai \
+        --junitxml="$TOP/junit-monai-app-sdk.xml" \
+        --cov-config="$TOP/.coveragerc" \
+        --cov-report=xml:"$TOP/monai-app-sdk-coverage.xml" \
+        --cov-report term \
+        "$@"
+    result=$?
+    popd > /dev/null
+
+    return ${result}
+}
+
+test_desc() { c_echo 'Execute test cases
 
 Arguments:
   $1 - subcommand [all] (default: all)
@@ -330,27 +792,28 @@ test_python() {
     local result=0
 
     local testsuite=""
+    local testsuite_unit="tests/unit"
+    local testsuite_integration="tests/integration"
     local testsuite_performance="tests/performance"
+    local testsuite_system="tests/system"
 
-    install_python_dev_deps_
+    install_python_dev_deps
 
     if [ "$test_type" = "all" ] || [ "$test_type" = "unit" ]; then
-        local testsuite="tests/unit"
+        local testsuite="${testsuite_unit}"
+    fi
+    if [ "$test_type" = "all" ] || [ "$test_type" = "integration" ]; then
+        local testsuite="${testsuite} ${testsuite_integration}"
     fi
     if [ "$test_type" = "all" ] || [ "$test_type" = "performance" ]; then
         testsuite="${testsuite} ${testsuite_performance}"
     fi
+    if [ "$test_type" = "all" ] || [ "$test_type" = "system" ]; then
+        testsuite="${testsuite} ${testsuite_system}"
+    fi
 
-    pushd $TOP > /dev/null
-    run_command py.test --cache-clear -vv \
-        --cov=monai \
-        --junitxml="$TOP/junit-monai-app-sdk.xml" \
-        --cov-config=$TOP/.coveragerc \
-        --cov-report=xml:"$TOP/monai-app-sdk-coverage.xml" \
-        --cov-report term \
-        ${testsuite}
+    pytest ${testsuite}
     result=$?
-    popd > /dev/null
 
     return $result
 }
@@ -378,7 +841,7 @@ parse_args() {
     do
         case "${option}" in
             y)
-                ALWAYS_YES=true;
+                ALWAYS_YES="true"
                 ;;
             h)
                 print_usage
@@ -394,6 +857,15 @@ parse_args() {
     shift
 
     ARGS=("$@")
+    # Check if the command has `--help` or `-h` and override the CMD
+    local arg
+    for arg in "${ARGS[@]}"; do
+        if [ "$arg" = "--help" ] || [ "$arg" = "-h" ]; then
+            ARGS=("$CMD")
+            CMD="help"
+            break
+        fi
+    done
 }
 
 print_usage() {
@@ -405,7 +877,7 @@ print_usage() {
     echo_err
     c_echo_err W "Command List"
     c_echo_err Y "    help  " w "----------------------------  Print detailed description for a given argument (command name)"
-    echo_err "$(get_list_of_available_commands "${RUN_SCRIPT_FILE}" | my_cat_prefix " ")"
+    echo_err "$(get_list_of_available_commands color "${RUN_SCRIPT_FILE}" | my_cat_prefix " ")"
     echo_err
 }
 
@@ -461,10 +933,10 @@ fi
 # Description template
 
 # Globals:
-#   MOPNAI_OS
-#   MOPNAI_TARGET
-#   MOPNAI_USER (used if MOPNAI_OS is "linux")
-#   MOPNAI_HOST (used if MOPNAI_OS is "linux")
+#   MONAI_OS
+#   MONAI_TARGET
+#   MONAI_USER (used if MONAI_OS is "linux")
+#   MONAI_HOST (used if MONAI_OS is "linux")
 # Arguments:
 #   Command line to execute
 # Returns:
diff --git a/setup.cfg b/setup.cfg
index 3d8a14ee..1e949d9e 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -12,8 +12,8 @@ license_files =
     LICENSE
 project_urls =
     Documentation=https://docs.monai.io/
-    Bug Tracker=https://github.com/Project-MONAI/monai-app-sdk/issues
-    Source Code=https://github.com/Project-MONAI/monai-app-sdk
+    Bug Tracker=https://github.com/Project-MONAI/monai-deploy-app-sdk/issues
+    Source Code=https://github.com/Project-MONAI/monai-deploy-app-sdk
 
 [options]
 python_requires = >= 3.6
@@ -84,7 +84,7 @@ pretty = False
 # Ignores all non-fatal errors.
 ignore_errors = True
 
-[mypy-monai._version]
+[mypy-*._version]
 # Ignores all non-fatal errors.
 ignore_errors = True
 
diff --git a/setup.py b/setup.py
index 1762bc06..a95cd97d 100644
--- a/setup.py
+++ b/setup.py
@@ -23,5 +23,5 @@
         "console_scripts": [
             "monai-deploy = monai.deploy.cli.main:main",
         ]
-    }
+    },
 )


Test patch:
diff --git a/examples/apps/lung_seg_cv_app/lun_seg_test.py b/examples/apps/lung_seg_cv_app/lun_seg_test.py
index 4a8b3743..7f14e0be 100644
--- a/examples/apps/lung_seg_cv_app/lun_seg_test.py
+++ b/examples/apps/lung_seg_cv_app/lun_seg_test.py
@@ -1,240 +1,240 @@
-# Copyright 2020 - 2021 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.
+# # Copyright 2020 - 2021 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 os
-from glob import glob
+# import os
+# from glob import glob
 
-import matplotlib.pyplot as plt
-import numpy as np
-import pydicom as dicom
-import scipy.ndimage
-from mpl_toolkits.mplot3d.art3d import Poly3DCollection
-from plotly.graph_objs import *
-from plotly.offline import iplot
-from plotly.tools import FigureFactory as FF
-from skimage import measure, morphology
-from sklearn.cluster import KMeans
+# import matplotlib.pyplot as plt
+# import numpy as np
+# import pydicom as dicom
+# import scipy.ndimage
+# from mpl_toolkits.mplot3d.art3d import Poly3DCollection
+# from plotly.graph_objs import *
+# from plotly.offline import iplot
+# from plotly.tools import FigureFactory as FF
+# from skimage import measure, morphology
+# from sklearn.cluster import KMeans
 
 
-def load_scan(path):
-    slices = [dicom.read_file(path + "/" + s) for s in os.listdir(path)]
-    slices.sort(key=lambda x: int(x.InstanceNumber))
-    try:
-        slice_thickness = np.abs(slices[0].ImagePositionPatient[2] - slices[1].ImagePositionPatient[2])
-    except RuntimeError:
-        slice_thickness = np.abs(slices[0].SliceLocation - slices[1].SliceLocation)
+# def load_scan(path):
+#     slices = [dicom.read_file(path + "/" + s) for s in os.listdir(path)]
+#     slices.sort(key=lambda x: int(x.InstanceNumber))
+#     try:
+#         slice_thickness = np.abs(slices[0].ImagePositionPatient[2] - slices[1].ImagePositionPatient[2])
+#     except RuntimeError:
+#         slice_thickness = np.abs(slices[0].SliceLocation - slices[1].SliceLocation)
 
-    for s in slices:
-        s.SliceThickness = slice_thickness
+#     for s in slices:
+#         s.SliceThickness = slice_thickness
 
-    return slices
+#     return slices
 
 
-def get_pixels_hu(scans):
-    image = np.stack([s.pixel_array for s in scans])
-    image = image.astype(np.int16)
-    image[image == -2000] = 0
-
-    intercept = scans[0].RescaleIntercept
-    slope = scans[0].RescaleSlope
-
-    if slope != 1:
-        image = slope * image.astype(np.float64)
-        image = image.astype(np.int16)
-
-    image += np.int16(intercept)
-
-    return np.array(image, dtype=np.int16)
-
-
-def save_images_to_npy(full_filename, imgs):
-    np.save(full_filename, imgs)
-
-
-def load_images_from_npy(full_filename):
-    imgs = np.load(full_filename)
-    return imgs
-
-
-def sample_stack(stack, rows=6, cols=6, start_with=10, show_every=3):
-    fig, ax = plt.subplots(rows, cols, figsize=[12, 12])
-    for i in range(rows * cols):
-        ind = start_with + i * show_every
-        ax[int(i / rows), int(i % rows)].set_title("slice %d" % ind)
-        ax[int(i / rows), int(i % rows)].imshow(stack[ind], cmap="gray")
-        ax[int(i / rows), int(i % rows)].axis("off")
-    plt.show()
-
-
-def resample(image, scan, new_spacing=[1, 1, 1]):
-    px = scan[0].PixelSpacing
-    spacing_temp = []
-    spacing_temp.append(scan[0].SliceThickness)
-    spacing_temp.append(px[0])
-    spacing_temp.append(px[1])
-    spacing = np.array(spacing_temp)
-    resize_factor = spacing / new_spacing
-    new_real_shape = image.shape * resize_factor
-    new_shape = np.round(new_real_shape)
-    real_resize_factor = new_shape / image.shape
-    new_spacing = spacing / real_resize_factor
-
-    image = scipy.ndimage.interpolation.zoom(image, real_resize_factor)
-
-    return image, new_spacing
-
-
-def make_mesh(image, threshold=-300, step_size=1):
-
-    print("Transposing surface")
-    p = image.transpose(2, 1, 0)
-
-    print("Calculating surface")
-    verts, faces, norm, val = measure.marching_cubes(p, threshold, step_size=step_size, allow_degenerate=True)
-    return verts, faces
-
-
-def plotly_3d(verts, faces):
-    x, y, z = zip(*verts)
-
-    print("Drawing")
-
-    # Make the colormap single color since the axes are positional not intensity.
-    # colormap=['rgb(255,105,180)','rgb(255,255,51)','rgb(0,191,255)']
-    colormap = ["rgb(236, 236, 212)", "rgb(236, 236, 212)"]
-
-    fig = FF.create_trisurf(
-        x=x,
-        y=y,
-        z=z,
-        plot_edges=False,
-        colormap=colormap,
-        simplices=faces,
-        backgroundcolor="rgb(64, 64, 64)",
-        title="Interactive Visualization",
-    )
-    iplot(fig)
-
-
-def plt_3d(verts, faces):
-    print("Drawing")
-    x, y, z = zip(*verts)
-    fig = plt.figure(figsize=(10, 10))
-    ax = fig.add_subplot(111, projection="3d")
-    mesh = Poly3DCollection(verts[faces], linewidths=0.05, alpha=1)
-    face_color = [1, 1, 0.9]
-    mesh.set_facecolor(face_color)
-    ax.add_collection3d(mesh)
-
-    ax.set_xlim(0, max(x))
-    ax.set_ylim(0, max(y))
-    ax.set_zlim(0, max(z))                #print("appending")
-
-    img = img/std
-    # Find the average pixel value near the lungs
-    # to renormalize washed out images
-    middle = img[int(col_size / 5) : int(col_size / 5 * 4), int(row_size / 5) : int(row_size / 5 * 4)]
-    mean = np.mean(middle)
-    max = np.max(img)
-    min = np.min(img)
-    # To improve threshold finding, I'm moving the
-    # underflow and overflow on the pixel spectrum
-    img[img == max] = mean
-    img[img == min] = mean
-    #
-    # Using Kmeans to separate foreground (soft tissue / bone) and background (lung/air)
-    #
-    kmeans = KMeans(n_clusters=2).fit(np.reshape(middle, [np.prod(middle.shape), 1]))
-    centers = sorted(kmeans.cluster_centers_.flatten())
-    threshold = np.mean(centers)
-    thresh_img = np.where(img < threshold, 1.0, 0.0)  # threshold the image
-
-    # First erode away the finer elements, then dilate to include some of the pixels surrounding the lung.
-    # We don't want to accidentally clip the lung.
-
-    eroded = morphology.erosion(thresh_img, np.ones([3, 3]))
-    dilation = morphology.dilation(eroded, np.ones([8, 8]))
-
-    labels = measure.label(dilation)  # Different labels are displayed in different colors
-    label_vals = np.unique(labels)
-    regions = measure.regionprops(labels)
-    good_labels = []
-    for prop in regions:
-        B = prop.bbox
-        if (
-            B[2] - B[0] < row_size / 10 * 9
-            and B[3] - B[1] < col_size / 10 * 9
-            and B[0] > row_size / 5
-            and B[2] < col_size / 5 * 4
-        ):
-            good_labels.append(prop.label)
-    mask = np.ndarray([row_size, col_size], dtype=np.int8)
-    mask[:] = 0
-
-    #
-    #  After just the lungs are left, we do another large dilation
-    #  in order to fill in and out the lung mask
-    #
-    for N in good_labels:
-        mask = mask + np.where(labels == N, 1, 0)
-    mask = morphology.dilation(mask, np.ones([10, 10]))  # one last dilation
-
-    if display:
-        fig, ax = plt.subplots(3, 2, figsize=[12, 12])
-        ax[0, 0].set_title("Original")
-        ax[0, 0].imshow(img, cmap="gray")
-        ax[0, 0].axis("off")
-        ax[0, 1].set_title("Threshold")
-        ax[0, 1].imshow(thresh_img, cmap="gray")
-        ax[0, 1].axis("off")
-        ax[1, 0].set_title("After Erosion and Dilation")
-        ax[1, 0].imshow(dilation, cmap="gray")
-        ax[1, 0].axis("off")
-        ax[1, 1].set_title("Color Labels")
-        ax[1, 1].imshow(labels)
-        ax[1, 1].axis("off")
-        ax[2, 0].set_title("Final Mask")
-        ax[2, 0].imshow(mask, cmap="gray")
-        ax[2, 0].axis("off")
-        ax[2, 1].set_title("Apply Mask on Original")
-        ax[2, 1].imshow(mask * img, cmap="gray")
-        ax[2, 1].axis("off")
-
-        plt.show()
-    return mask * img
-
-
-data_path = "/home/rahul/medical-images/lung-ct-2/"
-output_path = working_path = "/home/rahul/monai-output/"
-g = glob(data_path + "/*.dcm")
-
-# Print out the first 5 file names to verify we're in the right folder.
-print("Total of %d DICOM images.\nFirst 5 filenames:" % len(g))
-print("\n".join(g[:5]))
-
-patient = load_scan(data_path)
-imgs = get_pixels_hu(patient)
-np.save(output_path + "fullimages.npy", imgs)
-
-imgs_to_process = np.load(output_path + "fullimages.npy")
-sample_stack(imgs_to_process)
-
-print("Shape before resampling\t", imgs_to_process.shape)
-imgs_after_resamp, spacing = resample(imgs_to_process, patient, [1, 1, 1])
-print("Shape after resampling\t", imgs_after_resamp.shape)
-
-
-masked_lung = []
-for img in imgs_after_resamp:
-    masked_lung.append(make_lungmask(img))
-
-sample_stack(masked_lung, show_every=2)
-np.save(output_path + "maskedimages.npy", masked_lung)
+# def get_pixels_hu(scans):
+#     image = np.stack([s.pixel_array for s in scans])
+#     image = image.astype(np.int16)
+#     image[image == -2000] = 0
+
+#     intercept = scans[0].RescaleIntercept
+#     slope = scans[0].RescaleSlope
+
+#     if slope != 1:
+#         image = slope * image.astype(np.float64)
+#         image = image.astype(np.int16)
+
+#     image += np.int16(intercept)
+
+#     return np.array(image, dtype=np.int16)
+
+
+# def save_images_to_npy(full_filename, imgs):
+#     np.save(full_filename, imgs)
+
+
+# def load_images_from_npy(full_filename):
+#     imgs = np.load(full_filename)
+#     return imgs
+
+
+# def sample_stack(stack, rows=6, cols=6, start_with=10, show_every=3):
+#     fig, ax = plt.subplots(rows, cols, figsize=[12, 12])
+#     for i in range(rows * cols):
+#         ind = start_with + i * show_every
+#         ax[int(i / rows), int(i % rows)].set_title("slice %d" % ind)
+#         ax[int(i / rows), int(i % rows)].imshow(stack[ind], cmap="gray")
+#         ax[int(i / rows), int(i % rows)].axis("off")
+#     plt.show()
+
+
+# def resample(image, scan, new_spacing=[1, 1, 1]):
+#     px = scan[0].PixelSpacing
+#     spacing_temp = []
+#     spacing_temp.append(scan[0].SliceThickness)
+#     spacing_temp.append(px[0])
+#     spacing_temp.append(px[1])
+#     spacing = np.array(spacing_temp)
+#     resize_factor = spacing / new_spacing
+#     new_real_shape = image.shape * resize_factor
+#     new_shape = np.round(new_real_shape)
+#     real_resize_factor = new_shape / image.shape
+#     new_spacing = spacing / real_resize_factor
+
+#     image = scipy.ndimage.interpolation.zoom(image, real_resize_factor)
+
+#     return image, new_spacing
+
+
+# def make_mesh(image, threshold=-300, step_size=1):
+
+#     print("Transposing surface")
+#     p = image.transpose(2, 1, 0)
+
+#     print("Calculating surface")
+#     verts, faces, norm, val = measure.marching_cubes(p, threshold, step_size=step_size, allow_degenerate=True)
+#     return verts, faces
+
+
+# def plotly_3d(verts, faces):
+#     x, y, z = zip(*verts)
+
+#     print("Drawing")
+
+#     # Make the colormap single color since the axes are positional not intensity.
+#     # colormap=['rgb(255,105,180)','rgb(255,255,51)','rgb(0,191,255)']
+#     colormap = ["rgb(236, 236, 212)", "rgb(236, 236, 212)"]
+
+#     fig = FF.create_trisurf(
+#         x=x,
+#         y=y,
+#         z=z,
+#         plot_edges=False,
+#         colormap=colormap,
+#         simplices=faces,
+#         backgroundcolor="rgb(64, 64, 64)",
+#         title="Interactive Visualization",
+#     )
+#     iplot(fig)
+
+
+# def plt_3d(verts, faces):
+#     print("Drawing")
+#     x, y, z = zip(*verts)
+#     fig = plt.figure(figsize=(10, 10))
+#     ax = fig.add_subplot(111, projection="3d")
+#     mesh = Poly3DCollection(verts[faces], linewidths=0.05, alpha=1)
+#     face_color = [1, 1, 0.9]
+#     mesh.set_facecolor(face_color)
+#     ax.add_collection3d(mesh)
+
+#     ax.set_xlim(0, max(x))
+#     ax.set_ylim(0, max(y))
+#     ax.set_zlim(0, max(z))  # print("appending")
+
+#     img = img / std
+#     # Find the average pixel value near the lungs
+#     # to renormalize washed out images
+#     middle = img[int(col_size / 5) : int(col_size / 5 * 4), int(row_size / 5) : int(row_size / 5 * 4)]
+#     mean = np.mean(middle)
+#     max = np.max(img)
+#     min = np.min(img)
+#     # To improve threshold finding, I'm moving the
+#     # underflow and overflow on the pixel spectrum
+#     img[img == max] = mean
+#     img[img == min] = mean
+#     #
+#     # Using Kmeans to separate foreground (soft tissue / bone) and background (lung/air)
+#     #
+#     kmeans = KMeans(n_clusters=2).fit(np.reshape(middle, [np.prod(middle.shape), 1]))
+#     centers = sorted(kmeans.cluster_centers_.flatten())
+#     threshold = np.mean(centers)
+#     thresh_img = np.where(img < threshold, 1.0, 0.0)  # threshold the image
+
+#     # First erode away the finer elements, then dilate to include some of the pixels surrounding the lung.
+#     # We don't want to accidentally clip the lung.
+
+#     eroded = morphology.erosion(thresh_img, np.ones([3, 3]))
+#     dilation = morphology.dilation(eroded, np.ones([8, 8]))
+
+#     labels = measure.label(dilation)  # Different labels are displayed in different colors
+#     label_vals = np.unique(labels)
+#     regions = measure.regionprops(labels)
+#     good_labels = []
+#     for prop in regions:
+#         B = prop.bbox
+#         if (
+#             B[2] - B[0] < row_size / 10 * 9
+#             and B[3] - B[1] < col_size / 10 * 9
+#             and B[0] > row_size / 5
+#             and B[2] < col_size / 5 * 4
+#         ):
+#             good_labels.append(prop.label)
+#     mask = np.ndarray([row_size, col_size], dtype=np.int8)
+#     mask[:] = 0
+
+#     #
+#     #  After just the lungs are left, we do another large dilation
+#     #  in order to fill in and out the lung mask
+#     #
+#     for N in good_labels:
+#         mask = mask + np.where(labels == N, 1, 0)
+#     mask = morphology.dilation(mask, np.ones([10, 10]))  # one last dilation
+
+#     if display:
+#         fig, ax = plt.subplots(3, 2, figsize=[12, 12])
+#         ax[0, 0].set_title("Original")
+#         ax[0, 0].imshow(img, cmap="gray")
+#         ax[0, 0].axis("off")
+#         ax[0, 1].set_title("Threshold")
+#         ax[0, 1].imshow(thresh_img, cmap="gray")
+#         ax[0, 1].axis("off")
+#         ax[1, 0].set_title("After Erosion and Dilation")
+#         ax[1, 0].imshow(dilation, cmap="gray")
+#         ax[1, 0].axis("off")
+#         ax[1, 1].set_title("Color Labels")
+#         ax[1, 1].imshow(labels)
+#         ax[1, 1].axis("off")
+#         ax[2, 0].set_title("Final Mask")
+#         ax[2, 0].imshow(mask, cmap="gray")
+#         ax[2, 0].axis("off")
+#         ax[2, 1].set_title("Apply Mask on Original")
+#         ax[2, 1].imshow(mask * img, cmap="gray")
+#         ax[2, 1].axis("off")
+
+#         plt.show()
+#     return mask * img
+
+
+# data_path = "/home/rahul/medical-images/lung-ct-2/"
+# output_path = working_path = "/home/rahul/monai-output/"
+# g = glob(data_path + "/*.dcm")
+
+# # Print out the first 5 file names to verify we're in the right folder.
+# print("Total of %d DICOM images.\nFirst 5 filenames:" % len(g))
+# print("\n".join(g[:5]))
+
+# patient = load_scan(data_path)
+# imgs = get_pixels_hu(patient)
+# np.save(output_path + "fullimages.npy", imgs)
+
+# imgs_to_process = np.load(output_path + "fullimages.npy")
+# sample_stack(imgs_to_process)
+
+# print("Shape before resampling\t", imgs_to_process.shape)
+# imgs_after_resamp, spacing = resample(imgs_to_process, patient, [1, 1, 1])
+# print("Shape after resampling\t", imgs_after_resamp.shape)
+
+
+# masked_lung = []
+# for img in imgs_after_resamp:
+#     masked_lung.append(make_lungmask(img))
+
+# sample_stack(masked_lung, show_every=2)
+# np.save(output_path + "maskedimages.npy", masked_lung)
diff --git a/tests/system/packager/test_packager.py b/tests/system/packager/test_packager.py
index 74f7cd39..aacd77db 100644
--- a/tests/system/packager/test_packager.py
+++ b/tests/system/packager/test_packager.py
@@ -36,23 +36,18 @@ def test_packager():
     test_params_values["command"] = "/usr/bin/python3 -u /opt/monai/app/main.py"
     test_params_values["pip-packages"] = []
     test_params_values["models"] = []
-    test_params_values["resource"] = {"cpu": 1,
-                                      "gpu": 2,
-                                      "memory": "4Gi"}
+    test_params_values["resource"] = {"cpu": 1, "gpu": 2, "memory": "4Gi"}
 
-    test_params_string = json.dumps(test_params_values, 
-                                    sort_keys=True,
-                                    indent=4,
-                                    separators=(',', ': '))
+    test_params_string = json.dumps(test_params_values, sort_keys=True, indent=4, separators=(",", ": "))
 
-    with open(test_params_file[1], 'w') as tmp_params:
+    with open(test_params_file[1], "w") as tmp_params:
         tmp_params.write(test_params_string)
 
     parser = argparse.ArgumentParser()
     args = parser.parse_args([])
-    args.application=test_app
-    args.tag=test_map_tag
-    args.params=test_params_file[1]
+    args.application = test_app
+    args.tag = test_map_tag
+    args.params = test_params_file[1]
     args.base = None
     args.working_dir = None
     args.input_dir = None
diff --git a/tests/unit/test_runner.py b/tests/unit/test_runner.py
index 28f42f24..53dd0a6d 100644
--- a/tests/unit/test_runner.py
+++ b/tests/unit/test_runner.py
@@ -18,8 +18,6 @@
 import pytest
 from pytest_lazyfixture import lazy_fixture
 
-from tests.fixtures.runner_fixtures import faux_input_file, faux_input_folder
-
 
 class ContainsString(str):
     def __eq__(self, other):
@@ -65,7 +63,7 @@ def test_fetch_map_manifest(
 @pytest.mark.parametrize(
     "return_value, input_path, output_path, quiet",
     [
-        (0, lazy_fixture("faux_input_file"), Path("output/"), False),
+        # (0, lazy_fixture("faux_input_file"), Path("output/"), False),
         (0, lazy_fixture("faux_input_folder"), Path("output/"), False),
         (0, lazy_fixture("faux_input_file"), Path("output/"), True),
         (0, lazy_fixture("faux_input_folder"), Path("output/"), True),
diff --git a/tests/unit/test_runner_utils.py b/tests/unit/test_runner_utils.py
index 6873b6cf..38f06929 100644
--- a/tests/unit/test_runner_utils.py
+++ b/tests/unit/test_runner_utils.py
@@ -15,8 +15,6 @@
 import pytest
 from pytest_lazyfixture import lazy_fixture
 
-from monai.deploy.runner.utils import run_cmd
-
 
 class ContainsString(str):
     def __eq__(self, other):
@@ -63,7 +61,7 @@ def test_verify_image(mock_run_cmd, mock_check_output, image_name, docker_images
 
     actual_response = utils.verify_image(image_name)
 
-    assert actual_response == image_present or (image_pulled is 0)
+    assert actual_response == image_present or (image_pulled == 0)
 
     if not image_present:
         mock_run_cmd.assert_called_once_with(ContainsString("docker pull"))