Skip to content

Commit 3947d4e

Browse files
3482 - update bundle doc (#3982)
* update bundle doc Signed-off-by: Wenqi Li <[email protected]> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * update meta Signed-off-by: Wenqi Li <[email protected]> * update intro Signed-off-by: Wenqi Li <[email protected]> * update examples Signed-off-by: Wenqi Li <[email protected]> * adds yaml demo Signed-off-by: Wenqi Li <[email protected]> * update schema Signed-off-by: Wenqi Li <[email protected]> * update toc Signed-off-by: Wenqi Li <[email protected]> * update doc page Signed-off-by: Wenqi Li <[email protected]> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * $import Signed-off-by: Wenqi Li <[email protected]> * adds recommendations Signed-off-by: Wenqi Li <[email protected]> * update config Signed-off-by: Wenqi Li <[email protected]> * update based on comments Signed-off-by: Wenqi Li <[email protected]> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * adds a link on CLI parsing Signed-off-by: Wenqi Li <[email protected]> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent df19315 commit 3947d4e

File tree

9 files changed

+212
-14
lines changed

9 files changed

+212
-14
lines changed

docs/source/bundle_intro.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
:github_url: https://github.com/Project-MONAI/MONAI
2+
3+
Bundle
4+
======
5+
6+
.. toctree::
7+
:maxdepth: 1
8+
9+
mb_specification
10+
config_syntax.md

docs/source/config_syntax.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# MONAI Bundle Configuration
2+
3+
The `monai.bundle` module supports building Python-based workflows via structured configurations.
4+
5+
The main benefits are threefold:
6+
7+
- it provides good readability and usability by separating system parameter settings from the Python code.
8+
- it describes workflow at a relatively high level and allows for different low-level implementations.
9+
- learning paradigms at a higher level such as federated learning and AutoML can be decoupled from the component details.
10+
11+
Content:
12+
13+
- [A basic example](#a-basic-example)
14+
- [Syntax examples explained](#syntax-examples-explained)
15+
- [`@` to interpolate with Python objects](#1--to-interpolate-with-python-objects)
16+
- [`$` to evaluate as Python expressions](#2--to-evaluate-as-python-expressions)
17+
- [`%` to textually replace configuration elements](#3--to-textually-replace-configuration-elements)
18+
- [`_target_` (`_disabled_` and `_requires_`) to instantiate a Python object](#4-instantiate-a-python-object)
19+
- [The command line interface](#the-command-line-interface)
20+
- [Recommendations](#recommendations)
21+
22+
## A basic example
23+
24+
Components as part of a workflow can be specified using `JSON` or `YAML` syntax, for example, a network architecture
25+
definition could be stored in a `demo_config.json` file with the following content:
26+
27+
```json
28+
{
29+
"demo_net": {
30+
"_target_": "monai.networks.nets.BasicUNet",
31+
"spatial_dims": 3,
32+
"in_channels": 1,
33+
"out_channels": 2,
34+
"features": [16, 16, 32, 32, 64, 64]
35+
}
36+
}
37+
```
38+
39+
or alternatively, in `YAML` format (`demo_config.yaml`):
40+
41+
```yaml
42+
demo_net:
43+
_target_: monai.networks.nets.BasicUNet
44+
spatial_dims: 3
45+
in_channels: 1
46+
out_channels: 2
47+
features: [16, 16, 32, 32, 64, 64]
48+
```
49+
50+
The configuration parser can instantiate the component as a Python object:
51+
52+
```py
53+
>>> from monai.bundle import ConfigParser
54+
>>> config = ConfigParser()
55+
>>> config.read_config("demo_config.json")
56+
>>> net = config.get_parsed_content("demo_net", instantiate=True)
57+
BasicUNet features: (16, 16, 32, 32, 64, 64).
58+
>>> print(type(net))
59+
<class 'monai.networks.nets.basic_unet.BasicUNet'>
60+
```
61+
62+
or additionally, tune the input parameters then instantiate the component:
63+
64+
```py
65+
>>> config["demo_net"]["features"] = [32, 32, 32, 64, 64, 64]
66+
>>> net = config.get_parsed_content("demo_net", instantiate=True)
67+
BasicUNet features: (32, 32, 32, 64, 64, 64).
68+
```
69+
70+
For more details on the `ConfigParser` API, please see https://docs.monai.io/en/latest/bundle.html#config-parser.
71+
72+
## Syntax examples explained
73+
74+
A few characters and keywords are interpreted beyond the plain texts, here are examples of the syntax:
75+
76+
### 1. `@` to interpolate with Python objects
77+
78+
```json
79+
"@preprocessing#transforms#keys"
80+
```
81+
82+
_Description:_ A reference to another configuration value defined at `preprocessing#transforms#keys`.
83+
where `#` indicates a sub-structure of this configuration file.
84+
85+
```json
86+
"@preprocessing#1"
87+
```
88+
89+
_Description:_ `1` is interpreted as an integer, which is used to index (zero-based indexing) the `preprocessing` sub-structure.
90+
91+
### 2. `$` to evaluate as Python expressions
92+
93+
```json
94+
"$print(42)"
95+
```
96+
97+
_Description:_ `$` is a special character to indicate evaluating `print(42)` at runtime.
98+
99+
```json
100+
"$[i for i in @datalist]"
101+
```
102+
103+
_Description:_ Create a list at runtime using the values in `datalist` as input.
104+
105+
```json
106+
"$from torchvision.models import resnet18"
107+
```
108+
109+
_Description:_ `$` followed by an import statement is handled slightly differently from the
110+
Python expressions. The imported module `resnet18` will be available as a global variable
111+
to the other configuration sections. This is to simplify the use of external modules in the configuration.
112+
113+
### 3. `%` to textually replace configuration elements
114+
115+
```json
116+
"%demo_config.json#demo_net#in_channels"
117+
```
118+
119+
_Description:_ A macro to replace the current configuration element with the texts at `demo_net#in_channels` in the
120+
`demo_config.json` file. The replacement is done before instantiating or evaluating the components.
121+
122+
### 4. instantiate a Python object
123+
124+
```json
125+
{
126+
"demo_name":{
127+
"_target_": "my.python.module.Class",
128+
"args1": "string",
129+
"args2": 42}
130+
}
131+
```
132+
133+
_Description:_ This dictionary defines an object with a reference name `demo_name`, with an instantiable type
134+
specified at `_target_` and with input arguments `args1` and `args2`.
135+
This dictionary will be instantiated as a Pytorch object at runtime.
136+
137+
`_target_` is a required key by monai bundle syntax for the Python object name.
138+
`args1` and `args2` should be compatible with the Python object to instantiate.
139+
140+
```json
141+
{
142+
"component_name": {
143+
"_target_": "my.module.Class",
144+
"_requires_": "@cudnn_opt",
145+
"_disabled_": "true"}
146+
}
147+
```
148+
149+
_Description:_ `_requires_` and `_disabled_` are optional keys.
150+
`_requires_` specifies references (string starts with `@`) or
151+
Python expression that will be evaluated/instantiated before `_target_` object is instantiated.
152+
It is useful when the component does not explicitly depend on the other ConfigItems via
153+
its arguments, but requires the dependencies to be instantiated/evaluated beforehand.
154+
`_disabled_` specifies a flag to indicate whether to skip the instantiation.
155+
156+
## The command line interface
157+
158+
In addition to the Pythonic APIs, a few command line interfaces (CLI) are provided to interact with the bundle.
159+
The primary usage is:
160+
```bash
161+
python -m monai.bundle COMMANDS
162+
```
163+
164+
where `COMMANDS` is one of the following: `run`, `verify_metadata`, `ckpt_export`, ...
165+
(please see `python -m monai.bundle --help` for a list of available options).
166+
167+
To display a usage page for a command, for example `run`:
168+
```bash
169+
python -m monai.bundle run -- --help
170+
```
171+
172+
The support is provided by [Python Fire](https://github.com/google/python-fire), please
173+
make sure the optional dependency is installed, for example,
174+
using `pip install monai[fire]` or `pip install fire`.
175+
Details on the CLI argument parsing is provided in the
176+
[Python Fire Guide](https://github.com/google/python-fire/blob/master/docs/guide.md#argument-parsing).
177+
178+
## Recommendations
179+
- Both `YAML` and `JSON` are supported, but the advanced features of these formats are not supported.
180+
- Using meaningful names for the configuration elements can improve the readability.
181+
- While it is possible to build complex configurations with the bundle syntax,
182+
simple structures with sparse uses of expressions or references are preferred.
183+
- For `$import <module>` in the configuration, please make sure there are instructions for the users to install
184+
the `<module>` if it is not a (optional) dependency of MONAI.

docs/source/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Technical documentation is available at `docs.monai.io <https://docs.monai.io>`_
7070
:maxdepth: 1
7171
:caption: Specifications
7272

73-
mb_specification
73+
bundle_intro
7474

7575
Links
7676
-----

docs/source/mb_specification.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ This specification defines the directory structure a bundle must have and the ne
1313
Directory Structure
1414
===================
1515

16-
A MONAI Bundle is defined primarily as a directory with a set of specifically named subdirectories containing the model and metadata files. The root directory should be named for the model, given as "ModelName" in this exmaple, and should contain the following structure:
16+
A MONAI Bundle is defined primarily as a directory with a set of specifically named subdirectories containing the model and metadata files. The root directory should be named for the model, given as "ModelName" in this example, and should contain the following structure:
1717

1818
::
1919

@@ -55,7 +55,7 @@ This file contains the metadata information relating to the model, including wha
5555
* **optional_packages_version**: dictionary relating optional package names to their versions, these packages are not needed but are recommended to be installed with this stated minimum version.
5656
* **task**: plain-language description of what the model is meant to do.
5757
* **description**: longer form plain-language description of what the model is, what it does, etc.
58-
* **authorship**: state author(s) of the model.
58+
* **authors**: state author(s) of the model.
5959
* **copyright**: state model copyright.
6060
* **network_data_format**: defines the format, shape, and meaning of inputs and outputs to the model, contains keys "inputs" and "outputs" relating named inputs/outputs to their format specifiers (defined below).
6161

@@ -98,7 +98,7 @@ An example JSON metadata file:
9898
"optional_packages_version": {"nibabel": "3.2.1"},
9999
"task": "Decathlon spleen segmentation",
100100
"description": "A pre-trained model for volumetric (3D) segmentation of the spleen from CT image",
101-
"authorship": "MONAI team",
101+
"authors": "MONAI team",
102102
"copyright": "Copyright (c) MONAI Consortium",
103103
"data_source": "Task09_Spleen.tar from http://medicaldecathlon.com/",
104104
"data_type": "dicom",

monai/bundle/config_item.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from monai.bundle.utils import EXPR_KEY
2222
from monai.utils import ensure_tuple, first, instantiate, optional_import
2323

24-
__all__ = ["ComponentLocator", "ConfigItem", "ConfigExpression", "ConfigComponent"]
24+
__all__ = ["ComponentLocator", "ConfigItem", "ConfigExpression", "ConfigComponent", "Instantiable"]
2525

2626

2727
class Instantiable(ABC):
@@ -173,7 +173,7 @@ class ConfigComponent(ConfigItem, Instantiable):
173173
- ``"_requires_"`` (optional): specifies reference IDs (string starts with ``"@"``) or ``ConfigExpression``
174174
of the dependencies for this ``ConfigComponent`` object. These dependencies will be
175175
evaluated/instantiated before this object is instantiated. It is useful when the
176-
component doesn't explicitly depends on the other `ConfigItems` via its arguments,
176+
component doesn't explicitly depend on the other `ConfigItems` via its arguments,
177177
but requires the dependencies to be instantiated/evaluated beforehand.
178178
- ``"_disabled_"`` (optional): a flag to indicate whether to skip the instantiation.
179179
@@ -302,7 +302,7 @@ class ConfigExpression(ConfigItem):
302302
303303
config = "$monai.__version__"
304304
expression = ConfigExpression(config, id="test", globals={"monai": monai})
305-
print(expression.execute())
305+
print(expression.evaluate())
306306
307307
Args:
308308
config: content of a config item.

monai/bundle/config_parser.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,16 @@ def get_parsed_content(self, id: str = "", **kwargs):
211211
Use digits indexing from "0" for list or other strings for dict.
212212
For example: ``"xform#5"``, ``"net#channels"``. ``""`` indicates the entire ``self.config``.
213213
kwargs: additional keyword arguments to be passed to ``_resolve_one_item``.
214-
Currently support ``reset`` (for parse), ``instantiate`` and ``eval_expr``. All defaulting to True.
214+
Currently support ``lazy`` (whether to retain the current config cache, default to `False`),
215+
``instantiate`` (whether to instantiate the `ConfigComponent`, default to `True`) and
216+
``eval_expr`` (whether to evaluate the `ConfigExpression`, default to `True`).
215217
216218
"""
217219
if not self.ref_resolver.is_resolved():
218220
# not parsed the config source yet, parse it
219-
self.parse(kwargs.get("reset", True))
221+
self.parse(reset=True)
222+
elif not kwargs.get("lazy", False):
223+
self.parse(reset=not kwargs.get("lazy", False))
220224
return self.ref_resolver.get_resolved_content(id=id, **kwargs)
221225

222226
def read_meta(self, f: Union[PathLike, Sequence[PathLike], Dict], **kwargs):

monai/bundle/scripts.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def verify_metadata(
207207
):
208208
"""
209209
Verify the provided `metadata` file based on the predefined `schema`.
210-
`metadata` content must contain the `schema` field for the URL of shcema file to download.
210+
`metadata` content must contain the `schema` field for the URL of schema file to download.
211211
The schema standard follows: http://json-schema.org/.
212212
213213
Args:

tests/testing_data/data_config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@
7070
},
7171
"configs": {
7272
"test_meta_file": {
73-
"url": "https://github.com/Project-MONAI/MONAI-extra-test-data/releases/download/0.8.1/meta_schema_202203171008.json",
73+
"url": "https://github.com/Project-MONAI/MONAI-extra-test-data/releases/download/0.8.1/meta_schema_20220324.json",
7474
"hash_type": "md5",
75-
"hash_val": "e3a7e23d1113a1f3e6c69f09b6f9ce2c"
75+
"hash_val": "e12813de2c15672a8c8fa8466b3dfc95"
7676
}
7777
}
7878
}

tests/testing_data/metadata.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"schema": "https://github.com/Project-MONAI/MONAI-extra-test-data/releases/download/0.8.1/meta_schema_202203171008.json",
2+
"schema": "https://github.com/Project-MONAI/MONAI-extra-test-data/releases/download/0.8.1/meta_schema_20220324.json",
33
"version": "0.1.0",
44
"changelog": {
55
"0.1.0": "complete the model package",
@@ -13,7 +13,7 @@
1313
},
1414
"task": "Decathlon spleen segmentation",
1515
"description": "A pre-trained model for volumetric (3D) segmentation of the spleen from CT image",
16-
"authorship": "MONAI team",
16+
"authors": "MONAI team",
1717
"copyright": "Copyright (c) MONAI Consortium",
1818
"data_source": "Task09_Spleen.tar from http://medicaldecathlon.com/",
1919
"data_type": "dicom",

0 commit comments

Comments
 (0)