Skip to content

Commit

Permalink
Merge branch 'Project-MONAI:dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
K-Rilla authored Sep 18, 2024
2 parents 4bdc89b + d2d492e commit c3343b3
Show file tree
Hide file tree
Showing 52 changed files with 2,408 additions and 271 deletions.
13 changes: 7 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ jobs:
rm dist/monai*.tar.gz
ls -al dist/
- if: matrix.python-version == '3.9' && startsWith(github.ref, 'refs/tags/')
name: Publish to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.TEST_PYPI }}
repository-url: https://test.pypi.org/legacy/
# remove publishing to Test PyPI as it is moved to blossom
# - if: matrix.python-version == '3.9' && startsWith(github.ref, 'refs/tags/')
# name: Publish to Test PyPI
# uses: pypa/gh-action-pypi-publish@release/v1
# with:
# password: ${{ secrets.TEST_PYPI }}
# repository-url: https://test.pypi.org/legacy/

versioning:
# compute versioning file from python setup.py
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,5 @@ RUN apt-get update \
&& rm -rf /var/lib/apt/lists/*
# append /opt/tools to runtime path for NGC CLI to be accessible from all file system locations
ENV PATH=${PATH}:/opt/tools
ENV POLYGRAPHY_AUTOINSTALL_DEPS=1
WORKDIR /opt/monai
42 changes: 42 additions & 0 deletions docs/source/config_syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Content:
- [`$` to evaluate as Python expressions](#to-evaluate-as-python-expressions)
- [`%` to textually replace configuration elements](#to-textually-replace-configuration-elements)
- [`_target_` (`_disabled_`, `_desc_`, `_requires_`, `_mode_`) to instantiate a Python object](#instantiate-a-python-object)
- [`+` to alter semantics of merging config keys from multiple configuration files](#multiple-config-files)
- [The command line interface](#the-command-line-interface)
- [Recommendations](#recommendations)

Expand Down Expand Up @@ -175,6 +176,47 @@ _Description:_ `_requires_`, `_disabled_`, `_desc_`, and `_mode_` are optional k
- `"debug"` -- execute with debug prompt and return the return value of ``pdb.runcall(_target_, **kwargs)``,
see also [`pdb.runcall`](https://docs.python.org/3/library/pdb.html#pdb.runcall).

## Multiple config files

_Description:_ Multiple config files may be specified on the command line.
The content of those config files is being merged. When same keys are specifiled in more than one config file,
the value associated with the key is being overridden, in the order config files are specified.
If the desired behaviour is to merge values from both files, the key in second config file should be prefixed with `+`.
The value types for the merged contents must match and be both of `dict` or both of `list` type.
`dict` values will be merged via update(), `list` values - concatenated via extend().
Here's an example. In this case, "amp" value will be overridden by extra_config.json.
`imports` and `preprocessing#transforms` lists will be merged. An error would be thrown if the value type in `"+imports"` is not `list`:

config.json:
```json
{
"amp": "$True"
"imports": [
"$import torch"
],
"preprocessing": {
"_target_": "Compose",
"transforms": [
"$@t1",
"$@t2"
]
},
}
```

extra_config.json:
```json
{
"amp": "$False"
"+imports": [
"$from monai.networks import trt_compile"
],
"+preprocessing#transforms": [
"$@t3"
]
}
```

## The command line interface

In addition to the Pythonic APIs, a few command line interfaces (CLI) are provided to interact with the bundle.
Expand Down
36 changes: 36 additions & 0 deletions docs/source/transforms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,18 @@ Spatial
:members:
:special-members: __call__

`ConvertBoxToPoints`
""""""""""""""""""""
.. autoclass:: ConvertBoxToPoints
:members:
:special-members: __call__

`ConvertPointsToBoxes`
""""""""""""""""""""""
.. autoclass:: ConvertPointsToBoxes
:members:
:special-members: __call__


Smooth Field
^^^^^^^^^^^^
Expand Down Expand Up @@ -1222,6 +1234,12 @@ Utility
:members:
:special-members: __call__

`ApplyTransformToPoints`
""""""""""""""""""""""""
.. autoclass:: ApplyTransformToPoints
:members:
:special-members: __call__

Dictionary Transforms
---------------------

Expand Down Expand Up @@ -1973,6 +1991,18 @@ Spatial (Dict)
:members:
:special-members: __call__

`ConvertBoxToPointsd`
"""""""""""""""""""""
.. autoclass:: ConvertBoxToPointsd
:members:
:special-members: __call__

`ConvertPointsToBoxesd`
"""""""""""""""""""""""
.. autoclass:: ConvertPointsToBoxesd
:members:
:special-members: __call__


Smooth Field (Dict)
^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -2277,6 +2307,12 @@ Utility (Dict)
:members:
:special-members: __call__

`ApplyTransformToPointsd`
"""""""""""""""""""""""""
.. autoclass:: ApplyTransformToPointsd
:members:
:special-members: __call__


MetaTensor
^^^^^^^^^^
Expand Down
44 changes: 43 additions & 1 deletion monai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,51 @@

import os
import sys

import logging
import warnings
from ._version import get_versions


old_showwarning = warnings.showwarning


def custom_warning_handler(message, category, filename, lineno, file=None, line=None):
ignore_files = ["ignite/handlers/checkpoint", "modelopt/torch/quantization/tensor_quant"]
if any(ignore in filename for ignore in ignore_files):
return
old_showwarning(message, category, filename, lineno, file, line)


class DeprecatedTypesWarningFilter(logging.Filter):
def filter(self, record):
message_bodies_to_ignore = [
"np.bool8",
"np.object0",
"np.int0",
"np.uint0",
"np.void0",
"np.str0",
"np.bytes0",
"@validator",
"@root_validator",
"class-based `config`",
"pkg_resources",
"Implicitly cleaning up",
]
for message in message_bodies_to_ignore:
if message in record.getMessage():
return False
return True


# workaround for https://github.com/Project-MONAI/MONAI/issues/8060
# TODO: remove this workaround after upstream fixed the warning
# Set the custom warning handler to filter warning
warnings.showwarning = custom_warning_handler
# Get the logger for warnings and add the filter to the logger
logging.getLogger("py.warnings").addFilter(DeprecatedTypesWarningFilter())


PY_REQUIRED_MAJOR = 3
PY_REQUIRED_MINOR = 9

Expand Down
2 changes: 1 addition & 1 deletion monai/apps/vista3d/inferer.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def point_based_window_inferer(
point_labels=point_labels,
class_vector=class_vector,
prompt_class=prompt_class,
patch_coords=unravel_slice,
patch_coords=[unravel_slice],
prev_mask=prev_mask,
**kwargs,
)
Expand Down
8 changes: 5 additions & 3 deletions monai/bundle/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from monai.bundle.config_item import ComponentLocator, ConfigComponent, ConfigExpression, ConfigItem
from monai.bundle.reference_resolver import ReferenceResolver
from monai.bundle.utils import ID_REF_KEY, ID_SEP_KEY, MACRO_KEY
from monai.bundle.utils import ID_REF_KEY, ID_SEP_KEY, MACRO_KEY, merge_kv
from monai.config import PathLike
from monai.utils import ensure_tuple, look_up_option, optional_import
from monai.utils.misc import CheckKeyDuplicatesYamlLoader, check_key_duplicates
Expand Down Expand Up @@ -423,8 +423,10 @@ def load_config_files(cls, files: PathLike | Sequence[PathLike] | dict, **kwargs
if isinstance(files, str) and not Path(files).is_file() and "," in files:
files = files.split(",")
for i in ensure_tuple(files):
for k, v in (cls.load_config_file(i, **kwargs)).items():
parser[k] = v
config_dict = cls.load_config_file(i, **kwargs)
for k, v in config_dict.items():
merge_kv(parser, k, v)

return parser.get() # type: ignore

@classmethod
Expand Down
5 changes: 3 additions & 2 deletions monai/bundle/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from monai.apps.utils import _basename, download_url, extractall, get_logger
from monai.bundle.config_item import ConfigComponent
from monai.bundle.config_parser import ConfigParser
from monai.bundle.utils import DEFAULT_INFERENCE, DEFAULT_METADATA
from monai.bundle.utils import DEFAULT_INFERENCE, DEFAULT_METADATA, merge_kv
from monai.bundle.workflows import BundleWorkflow, ConfigWorkflow
from monai.config import IgniteInfo, PathLike
from monai.data import load_net_with_metadata, save_net_with_metadata
Expand Down Expand Up @@ -105,7 +105,7 @@ def update_kwargs(args: str | dict | None = None, ignore_none: bool = True, **kw
if isinstance(v, dict) and isinstance(args_.get(k), dict):
args_[k] = update_kwargs(args_[k], ignore_none, **v)
else:
args_[k] = v
merge_kv(args_, k, v)
return args_


Expand Down Expand Up @@ -255,6 +255,7 @@ def _download_from_ngc_private(
else:
raise ValueError("NGC API requires requests package. Please install it.")

os.makedirs(download_path, exist_ok=True)
zip_path = download_path / f"{filename}_v{version}.zip"
with open(zip_path, "wb") as f:
f.write(response.content)
Expand Down
36 changes: 35 additions & 1 deletion monai/bundle/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import json
import os
import warnings
import zipfile
from typing import Any

Expand All @@ -21,12 +22,21 @@

yaml, _ = optional_import("yaml")

__all__ = ["ID_REF_KEY", "ID_SEP_KEY", "EXPR_KEY", "MACRO_KEY", "DEFAULT_MLFLOW_SETTINGS", "DEFAULT_EXP_MGMT_SETTINGS"]
__all__ = [
"ID_REF_KEY",
"ID_SEP_KEY",
"EXPR_KEY",
"MACRO_KEY",
"MERGE_KEY",
"DEFAULT_MLFLOW_SETTINGS",
"DEFAULT_EXP_MGMT_SETTINGS",
]

ID_REF_KEY = "@" # start of a reference to a ConfigItem
ID_SEP_KEY = "::" # separator for the ID of a ConfigItem
EXPR_KEY = "$" # start of a ConfigExpression
MACRO_KEY = "%" # start of a macro of a config
MERGE_KEY = "+" # prefix indicating merge instead of override in case of multiple configs.

_conf_values = get_config_values()

Expand Down Expand Up @@ -233,3 +243,27 @@ def load_bundle_config(bundle_path: str, *config_names: str, **load_kw_args: Any
parser.read_config(f=cdata)

return parser


def merge_kv(args: dict | Any, k: str, v: Any) -> None:
"""
Update the `args` dict-like object with the key/value pair `k` and `v`.
"""
if k.startswith(MERGE_KEY):
"""
Both values associated with `+`-prefixed key pair must be of `dict` or `list` type.
`dict` values will be merged, `list` values - concatenated.
"""
id = k[1:]
if id in args:
if isinstance(v, dict) and isinstance(args[id], dict):
args[id].update(v)
elif isinstance(v, list) and isinstance(args[id], list):
args[id].extend(v)
else:
raise ValueError(ValueError(f"config must be dict or list for key `{k}`, but got {type(v)}: {v}."))
else:
warnings.warn(f"Can't merge entry ['{k}'], '{id}' is not in target dict - copying instead.")
args[id] = v
else:
args[k] = v
7 changes: 3 additions & 4 deletions monai/bundle/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from monai.bundle.properties import InferProperties, MetaProperties, TrainProperties
from monai.bundle.utils import DEFAULT_EXP_MGMT_SETTINGS, EXPR_KEY, ID_REF_KEY, ID_SEP_KEY
from monai.config import PathLike
from monai.utils import BundleProperty, BundlePropertyConfig, deprecated_arg, deprecated_arg_default, ensure_tuple
from monai.utils import BundleProperty, BundlePropertyConfig, deprecated_arg, ensure_tuple

__all__ = ["BundleWorkflow", "ConfigWorkflow"]

Expand All @@ -43,7 +43,7 @@ class BundleWorkflow(ABC):
workflow_type: specifies the workflow type: "train" or "training" for a training workflow,
or "infer", "inference", "eval", "evaluation" for a inference workflow,
other unsupported string will raise a ValueError.
default to `None` for common workflow.
default to `train` for train workflow.
workflow: specifies the workflow type: "train" or "training" for a training workflow,
or "infer", "inference", "eval", "evaluation" for a inference workflow,
other unsupported string will raise a ValueError.
Expand Down Expand Up @@ -274,7 +274,6 @@ class ConfigWorkflow(BundleWorkflow):
new_name="workflow_type",
msg_suffix="please use `workflow_type` instead.",
)
@deprecated_arg_default("workflow_type", None, "train", since="1.2", replaced="1.4")
def __init__(
self,
config_file: str | Sequence[str],
Expand All @@ -284,7 +283,7 @@ def __init__(
run_id: str = "run",
final_id: str = "finalize",
tracking: str | dict | None = None,
workflow_type: str | None = None,
workflow_type: str | None = "train",
workflow: str | None = None,
properties_path: PathLike | None = None,
**override: Any,
Expand Down
2 changes: 1 addition & 1 deletion monai/data/image_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1359,7 +1359,7 @@ def _get_affine(self, header: dict) -> np.ndarray:
x, y = direction.shape
affine_diam = min(x, y) + 1
affine: np.ndarray = np.eye(affine_diam)
affine[:x, :y] = direction
affine[:x, :y] = direction.T
affine[: (affine_diam - 1), -1] = origin # len origin is always affine_diam - 1
return affine

Expand Down
3 changes: 2 additions & 1 deletion monai/handlers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from .earlystop_handler import EarlyStopHandler
from .garbage_collector import GarbageCollector
from .hausdorff_distance import HausdorffDistance
from .ignite_metric import IgniteMetric, IgniteMetricHandler
from .ignite_metric import IgniteMetricHandler
from .logfile_handler import LogfileHandler
from .lr_schedule_handler import LrScheduleHandler
from .mean_dice import MeanDice
Expand All @@ -40,5 +40,6 @@
from .stats_handler import StatsHandler
from .surface_distance import SurfaceDistance
from .tensorboard_handlers import TensorBoardHandler, TensorBoardImageHandler, TensorBoardStatsHandler
from .trt_handler import TrtHandler
from .utils import from_engine, ignore_data, stopping_fn_from_loss, stopping_fn_from_metric, write_metrics_reports
from .validation_handler import ValidationHandler
Loading

0 comments on commit c3343b3

Please sign in to comment.