Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions docs/source/bundle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ Model Bundle
.. autofunction:: run
.. autofunction:: verify_metadata
.. autofunction:: verify_net_in_out
.. autofunction:: init_bundle
7 changes: 4 additions & 3 deletions docs/source/mb_specification.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,21 +104,22 @@ The format for tensors used as inputs and outputs can be used to specify semanti
* **latent**: ND tensor of data from the latent space from some layer of a network
* **gradient**: ND tensor of gradients from some layer of a network

Spatial shape definition can be complex for models accepting inputs of varying shapes, especially if there are specific conditions on what those shapes can be. Shapes are specified as lists of either positive integers for fixed sizes or strings containing expressions defining the condition a size depends on. This can be "*" to mean any size, or use an expression with Python mathematical operators and one character variables to represent dependence on an unknown quantity. For example, "2**n" represents a size which must be a power of 2, "2**n*m" must be a multiple of a power of 2. Variables are shared between dimension expressions, so a spatial shape of `["2**n", "2**n"]` states that the dimensions must be the same powers of 2 given by `n`.
Spatial shape definition can be complex for models accepting inputs of varying shapes, especially if there are specific conditions on what those shapes can be. Shapes are specified as lists of either positive integers for fixed sizes or strings containing expressions defining the condition a size depends on. This can be "*" to mean any size, or use an expression with Python mathematical operators and one character variables to represent dependence on an unknown quantity. For example, "2**p" represents a size which must be a power of 2, "2**p*n" must be a multiple of a power of 2. Variables are shared between dimension expressions, a spatial shape example: `["*", "16*n", "2**p*n"]`.

A JSON schema for this file can be found at https://github.com/Project-MONAI/MONAI/blob/3049e280f2424962bb2a69261389fcc0b98e0036/monai/apps/mmars/schema/metadata.json
The download link of a JSON schema to verify this file can be found within it with key "schema".

An example JSON metadata file:

::

{
"schema": "https://github.com/Project-MONAI/MONAI-extra-test-data/releases/download/0.8.1/meta_schema_20220324.json",
"version": "0.1.0",
"changelog": {
"0.1.0": "complete the model package",
"0.0.1": "initialize the model package structure"
},
"monai_version": "0.8.0",
"monai_version": "0.9.0",
"pytorch_version": "1.10.0",
"numpy_version": "1.21.2",
"optional_packages_version": {"nibabel": "3.2.1"},
Expand Down
2 changes: 1 addition & 1 deletion monai/bundle/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
from .config_item import ComponentLocator, ConfigComponent, ConfigExpression, ConfigItem, Instantiable
from .config_parser import ConfigParser
from .reference_resolver import ReferenceResolver
from .scripts import ckpt_export, download, load, run, verify_metadata, verify_net_in_out
from .scripts import ckpt_export, download, init_bundle, load, run, verify_metadata, verify_net_in_out
from .utils import EXPR_KEY, ID_REF_KEY, ID_SEP_KEY, MACRO_KEY, load_bundle_config
11 changes: 6 additions & 5 deletions monai/data/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
BlendMode,
Method,
NumpyPadMode,
PytorchPadMode,
convert_data_type,
convert_to_dst_type,
ensure_tuple,
Expand Down Expand Up @@ -557,8 +558,8 @@ def decollate_batch(batch, detach: bool = True, pad=True, fill_value=None):
def pad_list_data_collate(
batch: Sequence,
method: Union[Method, str] = Method.SYMMETRIC,
mode: Union[NumpyPadMode, str] = NumpyPadMode.CONSTANT,
**np_kwargs,
mode: Union[NumpyPadMode, PytorchPadMode, str] = NumpyPadMode.CONSTANT,
**kwargs,
):
"""
Function version of :py:class:`monai.transforms.croppad.batch.PadListDataCollate`.
Expand All @@ -576,13 +577,13 @@ def pad_list_data_collate(
batch: batch of data to pad-collate
method: padding method (see :py:class:`monai.transforms.SpatialPad`)
mode: padding mode (see :py:class:`monai.transforms.SpatialPad`)
np_kwargs: other args for `np.pad` API, note that `np.pad` treats channel dimension as the first dimension.
more details: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
kwargs: other arguments for the `np.pad` or `torch.pad` function.
note that `np.pad` treats channel dimension as the first dimension.

"""
from monai.transforms.croppad.batch import PadListDataCollate # needs to be here to avoid circular import

return PadListDataCollate(method=method, mode=mode, **np_kwargs)(batch)
return PadListDataCollate(method=method, mode=mode, **kwargs)(batch)


def no_collation(x):
Expand Down
43 changes: 24 additions & 19 deletions monai/transforms/croppad/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ def __init__(
return_coords: bool = False,
k_divisible: Union[Sequence[int], int] = 1,
mode: Optional[Union[NumpyPadMode, PytorchPadMode, str]] = NumpyPadMode.CONSTANT,
**np_kwargs,
**pad_kwargs,
) -> None:
"""
Args:
Expand All @@ -715,8 +715,8 @@ def __init__(
One of the listed string values or a user supplied function. Defaults to ``"constant"``.
See also: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
https://pytorch.org/docs/stable/generated/torch.nn.functional.pad.html
np_kwargs: other args for `np.pad` API, note that `np.pad` treats channel dimension as the first dimension.
more details: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
pad_kwargs: other arguments for the `np.pad` or `torch.pad` function.
note that `np.pad` treats channel dimension as the first dimension.

"""
self.select_fn = select_fn
Expand All @@ -726,7 +726,7 @@ def __init__(
self.return_coords = return_coords
self.k_divisible = k_divisible
self.mode: NumpyPadMode = look_up_option(mode, NumpyPadMode)
self.np_kwargs = np_kwargs
self.pad_kwargs = pad_kwargs

def compute_bounding_box(self, img: NdarrayOrTensor):
"""
Expand Down Expand Up @@ -762,9 +762,9 @@ def crop_pad(
pad_to_start = np.maximum(-box_start, 0)
pad_to_end = np.maximum(box_end - np.asarray(img.shape[1:]), 0)
pad = list(chain(*zip(pad_to_start.tolist(), pad_to_end.tolist())))
return BorderPad(spatial_border=pad, mode=mode or self.mode, **self.np_kwargs)(cropped)
return BorderPad(spatial_border=pad, mode=mode or self.mode, **self.pad_kwargs)(cropped)

def __call__(self, img: NdarrayOrTensor, mode: Optional[Union[NumpyPadMode, str]] = None):
def __call__(self, img: NdarrayOrTensor, mode: Optional[Union[NumpyPadMode, PytorchPadMode, str]] = None):
"""
Apply the transform to `img`, assuming `img` is channel-first and
slicing doesn't change the channel dim.
Expand Down Expand Up @@ -1139,14 +1139,16 @@ class ResizeWithPadOrCrop(Transform):
Args:
spatial_size: the spatial size of output data after padding or crop.
If has non-positive values, the corresponding size of input image will be used (no padding).
mode: {``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``, ``"mean"``,
``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``}
One of the listed string values or a user supplied function for padding. Defaults to ``"constant"``.
mode: available modes for numpy array:{``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``,
``"mean"``, ``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``}
available modes for PyTorch Tensor: {``"constant"``, ``"reflect"``, ``"replicate"``, ``"circular"``}.
One of the listed string values or a user supplied function. Defaults to ``"constant"``.
See also: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
https://pytorch.org/docs/stable/generated/torch.nn.functional.pad.html
method: {``"symmetric"``, ``"end"``}
Pad image symmetrically on every side or only pad at the end sides. Defaults to ``"symmetric"``.
np_kwargs: other args for `np.pad` API, note that `np.pad` treats channel dimension as the first dimension.
more details: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
pad_kwargs: other arguments for the `np.pad` or `torch.pad` function.
note that `np.pad` treats channel dimension as the first dimension.

"""

Expand All @@ -1155,23 +1157,26 @@ class ResizeWithPadOrCrop(Transform):
def __init__(
self,
spatial_size: Union[Sequence[int], int],
mode: Union[NumpyPadMode, str] = NumpyPadMode.CONSTANT,
mode: Union[NumpyPadMode, PytorchPadMode, str] = NumpyPadMode.CONSTANT,
method: Union[Method, str] = Method.SYMMETRIC,
**np_kwargs,
**pad_kwargs,
):
self.padder = SpatialPad(spatial_size=spatial_size, method=method, mode=mode, **np_kwargs)
self.padder = SpatialPad(spatial_size=spatial_size, method=method, mode=mode, **pad_kwargs)
self.cropper = CenterSpatialCrop(roi_size=spatial_size)

def __call__(self, img: NdarrayOrTensor, mode: Optional[Union[NumpyPadMode, str]] = None) -> NdarrayOrTensor:
def __call__(
self, img: NdarrayOrTensor, mode: Optional[Union[NumpyPadMode, PytorchPadMode, str]] = None
) -> NdarrayOrTensor:
"""
Args:
img: data to pad or crop, assuming `img` is channel-first and
padding or cropping doesn't apply to the channel dim.
mode: {``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``, ``"mean"``,
``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``}
One of the listed string values or a user supplied function for padding.
If None, defaults to the ``mode`` in construction.
mode: available modes for numpy array:{``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``,
``"mean"``, ``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``}
available modes for PyTorch Tensor: {``"constant"``, ``"reflect"``, ``"replicate"``, ``"circular"``}.
One of the listed string values or a user supplied function. Defaults to ``"constant"``.
See also: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
https://pytorch.org/docs/stable/generated/torch.nn.functional.pad.html
"""
return self.padder(self.cropper(img), mode=mode)

Expand Down
14 changes: 7 additions & 7 deletions monai/transforms/croppad/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from monai.data.utils import list_data_collate
from monai.transforms.croppad.array import CenterSpatialCrop, SpatialPad
from monai.transforms.inverse import InvertibleTransform
from monai.utils.enums import Method, NumpyPadMode, TraceKeys
from monai.utils.enums import Method, NumpyPadMode, PytorchPadMode, TraceKeys

__all__ = ["PadListDataCollate"]

Expand Down Expand Up @@ -57,20 +57,20 @@ class PadListDataCollate(InvertibleTransform):
Args:
method: padding method (see :py:class:`monai.transforms.SpatialPad`)
mode: padding mode (see :py:class:`monai.transforms.SpatialPad`)
np_kwargs: other args for `np.pad` API, note that `np.pad` treats channel dimension as the first dimension.
more details: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
kwargs: other arguments for the `np.pad` or `torch.pad` function.
note that `np.pad` treats channel dimension as the first dimension.

"""

def __init__(
self,
method: Union[Method, str] = Method.SYMMETRIC,
mode: Union[NumpyPadMode, str] = NumpyPadMode.CONSTANT,
**np_kwargs,
mode: Union[NumpyPadMode, PytorchPadMode, str] = NumpyPadMode.CONSTANT,
**kwargs,
) -> None:
self.method = method
self.mode = mode
self.np_kwargs = np_kwargs
self.kwargs = kwargs

def __call__(self, batch: Any):
"""
Expand All @@ -96,7 +96,7 @@ def __call__(self, batch: Any):
continue

# Use `SpatialPad` to match sizes, Default params are central padding, padding with 0's
padder = SpatialPad(spatial_size=max_shape, method=self.method, mode=self.mode, **self.np_kwargs)
padder = SpatialPad(spatial_size=max_shape, method=self.method, mode=self.mode, **self.kwargs)
for idx, batch_i in enumerate(batch):
orig_size = batch_i[key_or_idx].shape[1:]
padded = padder(batch_i[key_or_idx])
Expand Down
33 changes: 17 additions & 16 deletions monai/transforms/croppad/dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@
"RandCropByLabelClassesDict",
]

NumpyPadModeSequence = Union[Sequence[Union[NumpyPadMode, str]], NumpyPadMode, str]
PadModeSequence = Union[Sequence[Union[NumpyPadMode, PytorchPadMode, str]], NumpyPadMode, PytorchPadMode, str]
DEFAULT_POST_FIX = PostFix.meta()

Expand Down Expand Up @@ -287,8 +286,8 @@ def __init__(
``"mean"``, ``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``}
available modes for PyTorch Tensor: {``"constant"``, ``"reflect"``, ``"replicate"``, ``"circular"``}.
One of the listed string values or a user supplied function. Defaults to ``"constant"``.
See also: https://numpy.org/doc/1.18/reference/ghttps://pytorch.orgenerated/numpy.pad.html
/docs/stable/generated/torch.nn.functional.pad.html
See also: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
https://pytorch.org/docs/stable/generated/torch.nn.functional.pad.html
It also can be a sequence of string, each element corresponds to a key in ``keys``.
method: {``"symmetric"``, ``"end"``}
Pad image symmetrically on every side or only pad at the end sides. Defaults to ``"symmetric"``.
Expand Down Expand Up @@ -836,11 +835,11 @@ def __init__(
margin: Union[Sequence[int], int] = 0,
allow_smaller: bool = True,
k_divisible: Union[Sequence[int], int] = 1,
mode: Optional[Union[NumpyPadMode, PytorchPadMode, str]] = NumpyPadMode.CONSTANT,
mode: PadModeSequence = NumpyPadMode.CONSTANT,
start_coord_key: str = "foreground_start_coord",
end_coord_key: str = "foreground_end_coord",
allow_missing_keys: bool = False,
**np_kwargs,
**pad_kwargs,
) -> None:
"""
Args:
Expand All @@ -866,8 +865,8 @@ def __init__(
start_coord_key: key to record the start coordinate of spatial bounding box for foreground.
end_coord_key: key to record the end coordinate of spatial bounding box for foreground.
allow_missing_keys: don't raise exception if key is missing.
np_kwargs: other args for `np.pad` API, note that `np.pad` treats channel dimension as the first dimension.
more details: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
pad_kwargs: other arguments for the `np.pad` or `torch.pad` function.
note that `np.pad` treats channel dimension as the first dimension.

"""
super().__init__(keys, allow_missing_keys)
Expand All @@ -880,7 +879,7 @@ def __init__(
margin=margin,
allow_smaller=allow_smaller,
k_divisible=k_divisible,
**np_kwargs,
**pad_kwargs,
)
self.mode = ensure_tuple_rep(mode, len(self.keys))

Expand Down Expand Up @@ -1415,16 +1414,18 @@ class ResizeWithPadOrCropd(MapTransform, InvertibleTransform):
See also: monai.transforms.MapTransform
spatial_size: the spatial size of output data after padding or crop.
If has non-positive values, the corresponding size of input image will be used (no padding).
mode: {``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``, ``"mean"``,
``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``}
One of the listed string values or a user supplied function for padding. Defaults to ``"constant"``.
mode: available modes for numpy array:{``"constant"``, ``"edge"``, ``"linear_ramp"``, ``"maximum"``,
``"mean"``, ``"median"``, ``"minimum"``, ``"reflect"``, ``"symmetric"``, ``"wrap"``, ``"empty"``}
available modes for PyTorch Tensor: {``"constant"``, ``"reflect"``, ``"replicate"``, ``"circular"``}.
One of the listed string values or a user supplied function. Defaults to ``"constant"``.
See also: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
https://pytorch.org/docs/stable/generated/torch.nn.functional.pad.html
It also can be a sequence of string, each element corresponds to a key in ``keys``.
allow_missing_keys: don't raise exception if key is missing.
method: {``"symmetric"``, ``"end"``}
Pad image symmetrically on every side or only pad at the end sides. Defaults to ``"symmetric"``.
np_kwargs: other args for `np.pad` API, note that `np.pad` treats channel dimension as the first dimension.
more details: https://numpy.org/doc/1.18/reference/generated/numpy.pad.html
pad_kwargs: other arguments for the `np.pad` or `torch.pad` function.
note that `np.pad` treats channel dimension as the first dimension.

"""

Expand All @@ -1434,14 +1435,14 @@ def __init__(
self,
keys: KeysCollection,
spatial_size: Union[Sequence[int], int],
mode: NumpyPadModeSequence = NumpyPadMode.CONSTANT,
mode: PadModeSequence = NumpyPadMode.CONSTANT,
allow_missing_keys: bool = False,
method: Union[Method, str] = Method.SYMMETRIC,
**np_kwargs,
**pad_kwargs,
) -> None:
super().__init__(keys, allow_missing_keys)
self.mode = ensure_tuple_rep(mode, len(self.keys))
self.padcropper = ResizeWithPadOrCrop(spatial_size=spatial_size, method=method, **np_kwargs)
self.padcropper = ResizeWithPadOrCrop(spatial_size=spatial_size, method=method, **pad_kwargs)

def __call__(self, data: Mapping[Hashable, NdarrayOrTensor]) -> Dict[Hashable, NdarrayOrTensor]:
d = dict(data)
Expand Down
2 changes: 1 addition & 1 deletion tests/testing_data/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"0.1.0": "complete the model package",
"0.0.1": "initialize the model package structure"
},
"monai_version": "0.8.0",
"monai_version": "0.9.0",
"pytorch_version": "1.10.0",
"numpy_version": "1.21.2",
"optional_packages_version": {
Expand Down