<jupyter_start><jupyter_text>Executing app locally Executing and Inspecting App in Jupyter NotebookYou can define Operators and Application in Jupyter Notebook.<jupyter_code>from typing import Any, List, Union

import monai.deploy.core as md  # 'md' stands for MONAI Deploy (or can use 'core' instead)
from monai.deploy.core import (Application, DataPath, ExecutionContext, Image,
                               InputContext, IOType, Operator, OutputContext)

# @md.input("", DataPath, IOType.DISK)
@md.output("list", List[Union[str,int]], IOType.IN_MEMORY)
@md.env(pip_packages=["numpy"])
class TaskA(Operator):
    def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
        input_path = op_input.get().path  # input path (current path). not used here.
        model_path = context.models.get().path  # model path. This would be "" if the path (default: 'models') doesn't exist.

        op_output.set(["A", 1])

@md.input("list", List[Union[str,int]], IOType.IN_MEMORY)
# @md.output("", DataPath, IOType.DISK)
@md.env(pip_packages=["scikit-image"])
class TaskB(Operator):
    def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
        input_data = op_input.get()
        print(input_data)
        
        output_path = op_output.get().path  #  output path (current path). not used here.

@md.env(pip_packages=["Pillow"])
class App(Application):
    def compose(self):
        taskA = TaskA()
        taskB = TaskB()
        self.add_flow(taskA, taskB)<jupyter_output><empty_output><jupyter_text>Once an Application class (`App`) is defined, you can instentiate the application and execute with Application.run() method.At least one parameter (whose value is not `None` or `""`) needs to be specified to execute the application inside Jupyter Notebook.Since the above example doesn't use input or output paths, we specify `"."` to locate current path.(If we specify other path for `output` and the path doesn't exist, the output path would be created during the execution.)<jupyter_code>app = App()
print(app.context)  # print app context
app.run(input=".", output=".")  # override 'input_path' and 'output_path' in app.context
app.context  # 'input_path' and 'output_path' are now overwritten<jupyter_output><empty_output><jupyter_text>You can access [Graph](/modules/_autosummary/monai.deploy.core.graphs.Graph) object through `Application.graph`<jupyter_code>graph = app.graph
print(f"root_operators: {list(graph.get_root_operators())}")
print(f"operators: {list(graph.get_operators())}")
worklist = list(graph.gen_worklist())
print(f"worklist: {worklist}")
print(f"graph.is_root(worklist[0]): {graph.is_root(worklist[0])}")
print(f"graph.is_leaf(worklist[1]): {graph.is_leaf(worklist[1])}")<jupyter_output>root_operators: [<__main__.TaskA object at 0x7fc749451358>]
operators: [<__main__.TaskA object at 0x7fc749451358>, <__main__.TaskB object at 0x7fc749451438>]
worklist: [<__main__.TaskA object at 0x7fc749451358>, <__main__.TaskB object at 0x7fc749451438>]
graph.is_root(worklist[0]): True
graph.is_leaf(worklist[1]): True<jupyter_text>Executing Application through CLIOnce the application is verified inside Jupyter notebook, we can write the whole application as a file(`app.py`) with the following lines at the end of the file:```pythonif __name__ == "__main__":    App(do_run=True)```Above lines are needed to execute the application code by using `python` interpreter.<jupyter_code>%%writefile app.py
from typing import Any, List, Union

import monai.deploy.core as md  # 'md' stands for MONAI Deploy (or can use 'core' instead)
from monai.deploy.core import (Application, DataPath, ExecutionContext, Image,
                               InputContext, IOType, Operator, OutputContext)

# @md.input("", DataPath, IOType.DISK)
@md.output("list", List[Union[str,int]], IOType.IN_MEMORY)
@md.env(pip_packages=["numpy"])
class TaskA(Operator):
    def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
        input_path = op_input.get().path  # input path (current path). not used here.
        model_path = context.models.get().path  # model path. This would be "" if the path (default: 'models') doesn't exist.

        op_output.set(["A", 1])

@md.input("list", List[Union[str,int]], IOType.IN_MEMORY)
# @md.output("", DataPath, IOType.DISK)
@md.env(pip_packages=["scikit-image"])
class TaskB(Operator):
    def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
        input_data = op_input.get()
        print(input_data)
        
        output_path = op_output.get().path  #  output path (current path). not used here.

@md.env(pip_packages=["Pillow"])
class App(Application):
    def compose(self):
        taskA = TaskA()
        taskB = TaskB()
        self.add_flow(taskA, taskB)

if __name__ == "__main__":
    App(do_run=True)<jupyter_output>Overwriting app.py<jupyter_text>You can load the Application object from file through `monai.deploy.utils.importutil.get_application()` method.For the Application object, you can get the package information through Application.get_package_info() method<jupyter_code>import json
from monai.deploy.utils.importutil import get_application
app = get_application("app.py")  # the parameter can be a main application file or an application folder
print(json.dumps(app.get_package_info(), indent=2))<jupyter_output>{
  "app-name": "App",
  "app-version": "0.0.0",
  "sdk-version": "0.1.0-rc.2+1.g217d6b1.dirty",
  "command": "python3 -u /opt/monai/app/app.py",
  "resource": {
    "cpu": 0,
    "gpu": 0,
    "memory": "0Mi"
  },
  "models": [],
  "pip-packages": [
    "pillow",
    "numpy",
    "scikit-image"
  ]
}<jupyter_text>Let's run the application through CLI<jupyter_code>!python app.py --input . --output .<jupyter_output>[34mGoing to initiate execution of operator TaskA[39m
[32mExecuting operator TaskA [33m(Process ID: 9567, Operator ID: cc8b6114-7bab-4d80-9e82-0c6c42493986)[39m
[34mDone performing execution of operator TaskA
[39m
[34mGoing to initiate execution of operator TaskB[39m
[32mExecuting operator TaskB [33m(Process ID: 9567, Operator ID: acd67d8b-fb1a-4642-aa65-a32a411f7174)[39m
['A', 1]
[34mDone performing execution of operator TaskB
[39m<jupyter_text>monai-deploy execAbove command is same with the following command line:<jupyter_code>!monai-deploy exec app.py --input . --output .<jupyter_output>[34mGoing to initiate execution of operator TaskA[39m
[32mExecuting operator TaskA [33m(Process ID: 9724, Operator ID: 2c697da1-831f-49ce-84b1-6451413ce367)[39m
[34mDone performing execution of operator TaskA
[39m
[34mGoing to initiate execution of operator TaskB[39m
[32mExecuting operator TaskB [33m(Process ID: 9724, Operator ID: a1c07a95-a5fd-4d58-809e-e4f2fbc101ce)[39m
['A', 1]
[34mDone performing execution of operator TaskB
[39m
{'fraction_non_alphanumeric': 0.12860854503464203, 'fraction_numerical': 0.034064665127020784, 'mean_word_length': 5.046247818499127, 'pattern_counts': {'":': 12, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '86424', 'license': 'Apache-2.0', 'n_tokens_mistral': 2502, 'n_tokens_neox': 2315, 'n_words': 609, 'path': 'docs/source/developing_with_sdk/executing_app_locally.ipynb', 'repo_name': 'jlvahldiek/monai-deploy-app-sdk', 'size': '6928'}