Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3482 add run API for common training, evaluation and inference #3832

Merged
merged 101 commits into from
Mar 11, 2022
Merged
Show file tree
Hide file tree
Changes from 98 commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
42a45e0
Merge pull request #19 from Project-MONAI/master
Nic-Ma Feb 1, 2021
cd16a13
Merge pull request #32 from Project-MONAI/master
Nic-Ma Feb 24, 2021
6f87afd
Merge pull request #180 from Project-MONAI/dev
Nic-Ma Jul 22, 2021
f398298
Merge pull request #214 from Project-MONAI/dev
Nic-Ma Sep 8, 2021
85604cf
Merge pull request #373 from Project-MONAI/dev
Nic-Ma Feb 19, 2022
a3193ba
[DLMED] add config parser
Nic-Ma Feb 19, 2022
04e3ee7
[DLMED] simplify parse logic
Nic-Ma Feb 20, 2022
9abb571
[DLMED] add more function tests
Nic-Ma Feb 21, 2022
32aac56
Merge branch 'dev' into 3482-add-config-parser
Nic-Ma Feb 21, 2022
2ab8fd5
Merge pull request #374 from Project-MONAI/dev
Nic-Ma Feb 21, 2022
fe3f7c2
[DLMED] fix torchvision tests
Nic-Ma Feb 21, 2022
24c4ca1
[DLMED] add standard run API
Nic-Ma Feb 21, 2022
35dacfb
Merge branch 'dev' into 3482-add-config-reader
Nic-Ma Feb 21, 2022
5dc87f0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 21, 2022
d4cb4b0
Merge branch 'dev' into 3482-add-config-parser
Nic-Ma Feb 21, 2022
886b607
[DLMED] enhance update_config to support multiple items
Nic-Ma Feb 21, 2022
d7cd6cb
[DLMED] update API
Nic-Ma Feb 21, 2022
67d19be
[DLMED] simplify API
Nic-Ma Feb 21, 2022
b90b732
[DLMED] enhance doc and unit tests
Nic-Ma Feb 22, 2022
9056a9f
Merge branch 'dev' into 3482-add-config-parser
Nic-Ma Feb 22, 2022
9292450
Merge branch 'dev' into 3482-add-config-parser
Nic-Ma Feb 22, 2022
bfc74fc
[DLMED] clear API
Nic-Ma Feb 22, 2022
ac3e893
Merge branch 'dev' into 3482-add-config-parser
Nic-Ma Feb 23, 2022
0551374
Merge branch 'dev' into 3482-add-config-parser
Nic-Ma Feb 23, 2022
362e336
[DLMED] simplify usage APIs
Nic-Ma Feb 23, 2022
e7559c5
[DLMED] support root config
Nic-Ma Feb 23, 2022
420346b
[DLMED] fix update reference typo
Nic-Ma Feb 23, 2022
4492a91
[DLMED] update usage API
Nic-Ma Feb 23, 2022
3c1205c
revise APIs and docstrings
wyli Feb 23, 2022
43ce0e5
remove->discard
wyli Feb 23, 2022
5fff7d3
[DLMED] minor change
Nic-Ma Feb 24, 2022
be4630e
Merge branch 'dev' into 3482-add-config-reader
Nic-Ma Feb 24, 2022
e70d663
Merge branch '3482-add-config-reader' into 3482-add-config-parser
Nic-Ma Feb 24, 2022
f0c9a48
Merge pull request #376 from Nic-Ma/3482-add-config-parser
Nic-Ma Feb 24, 2022
b86f897
[DLMED] update code
Nic-Ma Feb 24, 2022
c8bba6a
update usage
wyli Feb 24, 2022
28c5c07
[DLMED] update doc
Nic-Ma Feb 24, 2022
72f37b1
Merge branch '3482-add-config-parser' of https://github.com/Nic-Ma/MO…
Nic-Ma Feb 24, 2022
a9c984c
Merge branch '3482-add-config-reader' into 3482-add-config-parser
Nic-Ma Feb 24, 2022
824e80e
Merge pull request #377 from Nic-Ma/3482-add-config-parser
Nic-Ma Feb 24, 2022
273e968
[DLMED] add end-to-end test
Nic-Ma Feb 24, 2022
3db14f7
[DLMED] update doc
Nic-Ma Feb 24, 2022
ba67151
[DLMED] fix flake8
Nic-Ma Feb 24, 2022
e1fcb30
[DLMED] fix optional import
Nic-Ma Feb 28, 2022
babea2b
[DLMED] refine APIs
Nic-Ma Feb 28, 2022
3aac99f
[DLMED] fix typo
Nic-Ma Feb 28, 2022
dc10f5d
[DLMED] add support to only use part of the file to override
Nic-Ma Mar 1, 2022
053bd6b
[DLMED] add more tests
Nic-Ma Mar 1, 2022
8b390e6
[DLMED] update to latest
Nic-Ma Mar 1, 2022
2b325ca
Merge branch 'dev' of https://github.com/Project-MONAI/MONAI into 348…
Nic-Ma Mar 1, 2022
e2710d4
Merge branch 'dev' into 3482-add-config-reader
Nic-Ma Mar 1, 2022
facd0ef
Merge branch 'dev' into 3482-add-config-reader
Nic-Ma Mar 2, 2022
c5a2c33
[DLMED] update according to comments
Nic-Ma Mar 2, 2022
ac83c02
[DLMED] fix flake8
Nic-Ma Mar 2, 2022
e3f9639
[DLMED] update according to comments
Nic-Ma Mar 2, 2022
bbdfc05
[DLMED] update `fire` supported dict arg
Nic-Ma Mar 2, 2022
248f300
[DLMED] add examples to doc-string
Nic-Ma Mar 2, 2022
fa67a39
[DLMED] skip windows test for paths
Nic-Ma Mar 2, 2022
0abb8e5
[DLMED] skip windows
Nic-Ma Mar 2, 2022
c1fefc8
[DLMED] update windows
Nic-Ma Mar 3, 2022
2ab3847
[DLMED] update command
Nic-Ma Mar 3, 2022
a3ce5ac
[DLMED] fix windows test
Nic-Ma Mar 3, 2022
605d630
[DLMED] construct class
Nic-Ma Mar 7, 2022
9bbd57e
[DLMED] restore design
Nic-Ma Mar 7, 2022
75120a6
Merge branch 'dev' into 3482-add-config-reader
Nic-Ma Mar 7, 2022
1810d0d
[DLMED] fix args override
Nic-Ma Mar 7, 2022
a1f8699
[DLMED] fix typo
Nic-Ma Mar 7, 2022
7adf4a9
[DLMED] test windows
Nic-Ma Mar 7, 2022
4469f38
[DLMED] test windows
Nic-Ma Mar 8, 2022
fa232fb
Merge branch 'dev' into 3482-add-config-reader
Nic-Ma Mar 8, 2022
c1aeaf2
[DLMED] update according to comments
Nic-Ma Mar 8, 2022
bed62ba
[DLMED] refactor config reading logic
Nic-Ma Mar 8, 2022
894ca88
[DLMED] add doc-string
Nic-Ma Mar 8, 2022
682c991
[DLMED] add export and test
Nic-Ma Mar 8, 2022
737ccc3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 8, 2022
5292db6
python -m monai.bundle
wyli Mar 8, 2022
45b240d
fixes doc tests
wyli Mar 8, 2022
d7022ec
Merge branch 'dev' into 3482-add-config-reader
Nic-Ma Mar 8, 2022
7db7264
[DLMED] enhance test
Nic-Ma Mar 8, 2022
469874a
rel import
wyli Mar 9, 2022
e769e55
[DLMED] refine macro
Nic-Ma Mar 9, 2022
efbdb21
fixes flake8 f401
wyli Mar 9, 2022
d3fd2c4
mv to monai.bundle
wyli Mar 9, 2022
74faa8e
fixes split_path_id, update docstrings
wyli Mar 9, 2022
7958161
fixes mypy
wyli Mar 9, 2022
ffb8087
update cli, update according to the comments
wyli Mar 9, 2022
5cd5425
[DLMED] fix typo in doc-string
Nic-Ma Mar 10, 2022
d8beeca
[DLMED] update according to discussion
Nic-Ma Mar 10, 2022
81fabd3
[DLMED] fix path_id match
Nic-Ma Mar 10, 2022
c89e3a2
revise according to the comments
wyli Mar 10, 2022
ca16681
[DLMED] update config item
Nic-Ma Mar 10, 2022
f9cb68a
[DLMED] update patterns
Nic-Ma Mar 10, 2022
2aaa23a
[DLMED] enhance disabled
Nic-Ma Mar 10, 2022
91dd87f
special chars to utils
wyli Mar 10, 2022
194b113
remove circular import
wyli Mar 10, 2022
056a119
configreader -> configparser following cpython/configparser
wyli Mar 10, 2022
fe83f07
printing
wyli Mar 10, 2022
1403909
fixes typing
wyli Mar 10, 2022
9d4ea6b
[DLMED] unify "_name_" and "_path_"
Nic-Ma Mar 11, 2022
2780530
[DLMED] update to "_target_"
Nic-Ma Mar 11, 2022
194f21e
fixes typos
wyli Mar 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ mlflow
tensorboardX
imagecodecs; platform_system == "Linux"
tifffile; platform_system == "Linux"
pyyaml
fire
4 changes: 4 additions & 0 deletions docs/source/bundle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ Model Bundle
---------------
.. autoclass:: ConfigParser
:members:

`Scripts`
---------
.. autofunction:: run
5 changes: 2 additions & 3 deletions docs/source/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,9 @@ Since MONAI v0.2.0, the extras syntax such as `pip install 'monai[nibabel]'` is

- The options are
```
[nibabel, skimage, pillow, tensorboard, gdown, ignite, torchvision, itk, tqdm, lmdb, psutil, cucim, openslide, pandas, einops, transformers, mlflow, matplotlib, tensorboardX, tifffile, imagecodecs]
[nibabel, skimage, pillow, tensorboard, gdown, ignite, torchvision, itk, tqdm, lmdb, psutil, cucim, openslide, pandas, einops, transformers, mlflow, matplotlib, tensorboardX, tifffile, imagecodecs, pyyaml, fire]
```
which correspond to `nibabel`, `scikit-image`, `pillow`, `tensorboard`,
`gdown`, `pytorch-ignite`, `torchvision`, `itk`, `tqdm`, `lmdb`, `psutil`, `cucim`, `openslide-python`, `pandas`, `einops`, `transformers`, `mlflow`, `matplotlib`, `tensorboardX`,
`tifffile`, `imagecodecs`, respectively.
`gdown`, `pytorch-ignite`, `torchvision`, `itk`, `tqdm`, `lmdb`, `psutil`, `cucim`, `openslide-python`, `pandas`, `einops`, `transformers`, `mlflow`, `matplotlib`, `tensorboardX`, `tifffile`, `imagecodecs`, `pyyaml`, `fire`, respectively.

- `pip install 'monai[all]'` installs all the optional dependencies.
2 changes: 2 additions & 0 deletions environment-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ dependencies:
- transformers
- mlflow
- tensorboardX
- pyyaml
- fire
- pip
- pip:
# pip for itk as conda-forge version only up to v5.1
Expand Down
2 changes: 1 addition & 1 deletion monai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

# handlers_* have some external decorators the users may not have installed
# *.so files and folder "_C" may not exist when the cpp extensions are not compiled
excludes = "(^(monai.handlers))|((\\.so)$)|(^(monai._C))"
excludes = "(^(monai.handlers))|(^(monai.bundle))|((\\.so)$)|(^(monai._C))"

# load directory modules only, skip loading individual files
load_submodules(sys.modules[__name__], False, exclude_pattern=excludes)
Expand Down
2 changes: 2 additions & 0 deletions monai/bundle/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@
from .config_item import ComponentLocator, ConfigComponent, ConfigExpression, ConfigItem, Instantiable
from .config_parser import ConfigParser
from .reference_resolver import ReferenceResolver
from .scripts import run
from .utils import EXPR_KEY, ID_REF_KEY, ID_SEP_KEY, MACRO_KEY
19 changes: 19 additions & 0 deletions monai/bundle/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (c) 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 monai.bundle.scripts import run

if __name__ == "__main__":
from monai.utils import optional_import

fire, _ = optional_import("fire")
fire.Fire()
50 changes: 26 additions & 24 deletions monai/bundle/config_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from importlib import import_module
from typing import Any, Dict, List, Mapping, Optional, Sequence, Union

from monai.bundle.utils import EXPR_KEY
from monai.utils import ensure_tuple, instantiate

__all__ = ["ComponentLocator", "ConfigItem", "ConfigExpression", "ConfigComponent"]
Expand Down Expand Up @@ -160,25 +161,24 @@ def __repr__(self) -> str:

class ConfigComponent(ConfigItem, Instantiable):
"""
Subclass of :py:class:`monai.apps.ConfigItem`, this class uses a dictionary with string keys to
Subclass of :py:class:`monai.bundle.ConfigItem`, this class uses a dictionary with string keys to
represent a component of `class` or `function` and supports instantiation.

Currently, four special keys (strings surrounded by ``<>``) are defined and interpreted beyond the regular literals:
Currently, four special keys (strings surrounded by ``_``) are defined and interpreted beyond the regular literals:

- class or function identifier of the python module, specified by one of the two keys.
- ``"<name>"``: indicates build-in python classes or functions such as "LoadImageDict".
- ``"<path>"``: full module name, such as "monai.transforms.LoadImageDict".
- ``"<args>"``: input arguments to the python module.
- ``"<disabled>"``: a flag to indicate whether to skip the instantiation.
- ``"_name_"``: indicates build-in python classes or functions such as "LoadImageDict".
- ``"_path_"``: full module name, such as "monai.transforms.LoadImageDict".
- ``"_disabled_"``: a flag to indicate whether to skip the instantiation.

Other fields in the config content are input arguments to the python module.

.. code-block:: python

locator = ComponentLocator(excludes=["modules_to_exclude"])
config = {
"<name>": "LoadImaged",
"<args>": {
"keys": ["image", "label"]
}
"_name_": "LoadImaged",
"keys": ["image", "label"]
}

configer = ConfigComponent(config, id="test", locator=locator)
Expand All @@ -195,6 +195,8 @@ class ConfigComponent(ConfigItem, Instantiable):

"""

non_arg_keys = {"_name_", "_path_", "_disabled_"}

def __init__(
self,
config: Any,
Expand All @@ -214,35 +216,35 @@ def is_instantiable(config: Any) -> bool:
config: input config content to check.

"""
return isinstance(config, Mapping) and ("<path>" in config or "<name>" in config)
return isinstance(config, Mapping) and ("_path_" in config or "_name_" in config)

def resolve_module_name(self):
"""
Resolve the target module name from current config content.
The config content must have ``"<path>"`` or ``"<name>"``.
When both are specified, ``"<path>"`` will be used.
The config content must have ``"_path_"`` or ``"_name_"`` key.
When both are specified, ``"_path_"`` will be used.

"""
config = dict(self.get_config())
path = config.get("<path>")
path = config.get("_path_")
if path is not None:
if not isinstance(path, str):
raise ValueError(f"'<path>' must be a string, but got: {path}.")
if "<name>" in config:
warnings.warn(f"both '<path>' and '<name>', default to use '<path>': {path}.")
raise ValueError(f"'_path_' must be a string, but got: {path}.")
if "_name_" in config:
warnings.warn(f"both '_path_' and '_name_', default to use '_path_': {path}.")
return path

name = config.get("<name>")
name = config.get("_name_")
if not isinstance(name, str):
raise ValueError("must provide a string for `<path>` or `<name>` of target component to instantiate.")
raise ValueError("must provide a string for `_path_` or `_name_` of target component to instantiate.")

module = self.locator.get_component_module_name(name)
if module is None:
raise ModuleNotFoundError(f"can not find component '{name}' in {self.locator.MOD_START} modules.")
if isinstance(module, list):
warnings.warn(
f"there are more than 1 component have name `{name}`: {module}, use the first one `{module[0]}."
f" if want to use others, please set its module path in `<path>` directly."
f" if want to use others, please set its module path in `_path_` directly."
)
module = module[0]
return f"{module}.{name}"
Expand All @@ -252,14 +254,14 @@ def resolve_args(self):
Utility function used in `instantiate()` to resolve the arguments from current config content.

"""
return self.get_config().get("<args>", {})
return {k: v for k, v in self.get_config().items() if k not in self.non_arg_keys}

def is_disabled(self) -> bool: # type: ignore
"""
Utility function used in `instantiate()` to check whether to skip the instantiation.

"""
_is_disabled = self.get_config().get("<disabled>", False)
_is_disabled = self.get_config().get("_disabled_", False)
return _is_disabled.lower().strip() == "true" if isinstance(_is_disabled, str) else bool(_is_disabled)

def instantiate(self, **kwargs) -> object: # type: ignore
Expand All @@ -283,7 +285,7 @@ def instantiate(self, **kwargs) -> object: # type: ignore

class ConfigExpression(ConfigItem):
"""
Subclass of :py:class:`monai.apps.ConfigItem`, the `ConfigItem` represents an executable expression
Subclass of :py:class:`monai.bundle.ConfigItem`, the `ConfigItem` represents an executable expression
(execute based on ``eval()``).

See also:
Expand All @@ -308,7 +310,7 @@ class ConfigExpression(ConfigItem):

"""

prefix = "$"
prefix = EXPR_KEY
wyli marked this conversation as resolved.
Show resolved Hide resolved
run_eval = False if os.environ.get("MONAI_EVAL_EXPR", "1") == "0" else True

def __init__(self, config: Any, id: str = "", globals: Optional[Dict] = None) -> None:
Expand Down
Loading