Skip to content

Commit f9cb68a

Browse files
committed
[DLMED] update patterns
Signed-off-by: Nic Ma <nma@nvidia.com>
1 parent ca16681 commit f9cb68a

File tree

10 files changed

+208
-268
lines changed

10 files changed

+208
-268
lines changed

monai/bundle/config_parser.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,17 @@ class ConfigParser:
3838
config = {
3939
"my_dims": 2,
4040
"dims_1": "$@my_dims + 1",
41-
"my_xform": {"<name>": "LoadImage"},
42-
"my_net": {"<name>": "BasicUNet",
43-
"<args>": {"spatial_dims": "@dims_1", "in_channels": 1, "out_channels": 4}},
44-
"trainer": {"<name>": "SupervisedTrainer",
45-
"<args>": {"network": "@my_net", "preprocessing": "@my_xform"}}
41+
"my_xform": {"_name_": "LoadImage"},
42+
"my_net": {"_name_": "BasicUNet", "spatial_dims": "@dims_1", "in_channels": 1, "out_channels": 4},
43+
"trainer": {"_name_": "SupervisedTrainer", "network": "@my_net", "preprocessing": "@my_xform"}
4644
}
4745
# in the example $@my_dims + 1 is an expression, which adds 1 to the value of @my_dims
4846
parser = ConfigParser(config)
4947
5048
# get/set configuration content, the set method should happen before calling parse()
51-
print(parser["my_net"]["<args>"]["in_channels"]) # original input channels 1
52-
parser["my_net"]["<args>"]["in_channels"] = 4 # change input channels to 4
53-
print(parser["my_net"]["<args>"]["in_channels"])
49+
print(parser["my_net"]["in_channels"]) # original input channels 1
50+
parser["my_net"]["in_channels"] = 4 # change input channels to 4
51+
print(parser["my_net"]["in_channels"])
5452
5553
# instantiate the network component
5654
parser.parse(True)
@@ -107,7 +105,7 @@ def __getitem__(self, id: Union[str, int]):
107105
id: id of the ``ConfigItem``, ``"#"`` in id are interpreted as special characters to
108106
go one level further into the nested structures.
109107
Use digits indexing from "0" for list or other strings for dict.
110-
For example: ``"xform#5"``, ``"net#<args>#channels"``. ``""`` indicates the entire ``self.config``.
108+
For example: ``"xform#5"``, ``"net#channels"``. ``""`` indicates the entire ``self.config``.
111109
112110
"""
113111
if id == "":
@@ -129,7 +127,7 @@ def __setitem__(self, id: Union[str, int], config: Any):
129127
id: id of the ``ConfigItem``, ``"#"`` in id are interpreted as special characters to
130128
go one level further into the nested structures.
131129
Use digits indexing from "0" for list or other strings for dict.
132-
For example: ``"xform#5"``, ``"net#<args>#channels"``. ``""`` indicates the entire ``self.config``.
130+
For example: ``"xform#5"``, ``"net#channels"``. ``""`` indicates the entire ``self.config``.
133131
config: config to set at location ``id``.
134132
135133
"""
@@ -171,7 +169,7 @@ def _do_resolve(self, config: Any):
171169
"""
172170
Recursively resolve the config content to replace the macro tokens with target content.
173171
The macro tokens start with "%", can be from another structured file, like:
174-
``{"net": "%default_net"}``, ``{"net": "%/data/config.json#net#<args>"}``.
172+
``{"net": "%default_net"}``, ``{"net": "%/data/config.json#net"}``.
175173
176174
Args:
177175
config: input config file to resolve.
@@ -190,7 +188,7 @@ def resolve_macro(self):
190188
"""
191189
Recursively resolve `self.config` to replace the macro tokens with target content.
192190
The macro tokens are marked as starting with "%", can be from another structured file, like:
193-
``"%default_net"``, ``"%/data/config.json#net#<args>"``.
191+
``"%default_net"``, ``"%/data/config.json#net"``.
194192
195193
"""
196194
self.set(self._do_resolve(config=deepcopy(self.get())))
@@ -204,7 +202,7 @@ def _do_parse(self, config, id: str = ""):
204202
id: id of the ``ConfigItem``, ``"#"`` in id are interpreted as special characters to
205203
go one level further into the nested structures.
206204
Use digits indexing from "0" for list or other strings for dict.
207-
For example: ``"xform#5"``, ``"net#<args>#channels"``. ``""`` indicates the entire ``self.config``.
205+
For example: ``"xform#5"``, ``"net#channels"``. ``""`` indicates the entire ``self.config``.
208206
209207
"""
210208
if isinstance(config, (dict, list)):
@@ -248,7 +246,7 @@ def get_parsed_content(self, id: str = "", **kwargs):
248246
id: id of the ``ConfigItem``, ``"#"`` in id are interpreted as special characters to
249247
go one level further into the nested structures.
250248
Use digits indexing from "0" for list or other strings for dict.
251-
For example: ``"xform#5"``, ``"net#<args>#channels"``. ``""`` indicates the entire ``self.config``.
249+
For example: ``"xform#5"``, ``"net#channels"``. ``""`` indicates the entire ``self.config``.
252250
kwargs: additional keyword arguments to be passed to ``_resolve_one_item``.
253251
Currently support ``reset`` (for parse), ``instantiate`` and ``eval_expr``. All defaulting to True.
254252

monai/bundle/config_reader.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class ConfigReader:
3838
suffixes = ("json", "yaml", "yml")
3939
suffix_match = rf"\.({'|'.join(suffixes)})"
4040
path_match = rf"(.*{suffix_match}$)"
41-
meta_key = "<meta>" # field key to save metadata
41+
meta_key = "_meta_" # field key to save metadata
4242
sep = "#" # separator for file path and the id of content in the file
4343

4444
def __init__(self):
@@ -122,7 +122,7 @@ def split_path_id(cls, src: str) -> Tuple[str, str]:
122122
def read_meta(self, f: Union[PathLike, Sequence[PathLike], Dict], **kwargs):
123123
"""
124124
Read the metadata from specified JSON or YAML file.
125-
The metadata as a dictionary will be stored at ``self.config["<meta>"]``.
125+
The metadata as a dictionary will be stored at ``self.config["_meta_"]``.
126126
127127
Args:
128128
f: filepath of the metadata file, the content must be a dictionary,

monai/bundle/reference_resolver.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ class ReferenceResolver:
4747
_vars = "__local_refs"
4848
sep = "#" # separator for key indexing
4949
ref = "@" # reference prefix
50-
# match a reference string, e.g. "@id#key", "@id#key#0", "@<test>#<args>#key"
51-
id_matcher = re.compile(rf"{ref}(?:(?:<\w*>)|(?:\w*))(?:(?:{sep}<\w*>)|(?:{sep}\w*))*")
50+
# match a reference string, e.g. "@id#key", "@id#key#0", "@_name_#key"
51+
id_matcher = re.compile(rf"{ref}(?:\w*)(?:{sep}\w*)*")
5252

5353
def __init__(self, items: Optional[Sequence[ConfigItem]] = None):
5454
# save the items in a dictionary with the `ConfigItem.id` as key

monai/bundle/scripts.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ def run(
3434
python -m monai.bundle run --meta_file <meta path> --config_file <config path> --target_id trainer
3535
3636
# Override config values at runtime by specifying the component id and its new value:
37-
python -m monai.bundle run --"net#<args>#input_chns" 1 ...
37+
python -m monai.bundle run --net#input_chns 1 ...
3838
3939
# Override config values with another config file `/path/to/another.json`:
40-
python -m monai.bundle run --"net#<args>" "%/path/to/another.json" ...
40+
python -m monai.bundle run --net %/path/to/another.json ...
4141
4242
# Override config values with part content of another config file:
43-
python -m monai.bundle run --"net#<args>" "%/data/other.json#net_arg" ...
43+
python -m monai.bundle run --net %/data/other.json#net_arg ...
4444
4545
# Set default args of `run` in a JSON / YAML file, help to record and simplify the command line.
4646
# Other args still can override the default args at runtime:
@@ -55,7 +55,7 @@ def run(
5555
args_file: a JSON or YAML file to provide default values for `meta_file`, `config_file`,
5656
`target_id` and override pairs. so that the command line inputs can be simplified.
5757
override: id-value pairs to override or add the corresponding config content.
58-
e.g. ``--"net#<args>#input_chns" 42``.
58+
e.g. ``--net#input_chns 42``.
5959
6060
"""
6161
k_v = zip(["meta_file", "config_file", "target_id"], [meta_file, config_file, target_id])

tests/test_bundle_run.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,20 @@ def test_shape(self, config_file, expected_shape):
6060
saver = LoadImage(image_only=True)
6161

6262
if sys.platform == "win32":
63-
override = "--network $@network_def.to(@device) --dataset#<name> Dataset"
63+
override = "--network $@network_def.to(@device) --dataset#_name_ Dataset"
6464
else:
65-
override = f"--network %{overridefile1}#move_net --dataset#<name> %{overridefile2}"
65+
override = f"--network %{overridefile1}#move_net --dataset#_name_ %{overridefile2}"
6666
# test with `monai.bundle` as CLI entry directly
6767
cmd = "-m monai.bundle run --target_id evaluator"
68-
cmd += f" --postprocessing#<args>#transforms#2#<args>#output_postfix seg {override}"
68+
cmd += f" --postprocessing#transforms#2#output_postfix seg {override}"
6969
la = [f"{sys.executable}"] + cmd.split(" ") + ["--meta_file", meta_file] + ["--config_file", config_file]
7070
ret = subprocess.check_call(la + ["--args_file", def_args_file])
7171
self.assertEqual(ret, 0)
7272
self.assertTupleEqual(saver(os.path.join(tempdir, "image", "image_seg.nii.gz")).shape, expected_shape)
7373

7474
# here test the script with `google fire` tool as CLI
7575
cmd = "-m fire monai.bundle.scripts run --target_id evaluator"
76-
cmd += f" --evaluator#<args>#amp False {override}"
76+
cmd += f" --evaluator#amp False {override}"
7777
la = [f"{sys.executable}"] + cmd.split(" ") + ["--meta_file", meta_file] + ["--config_file", config_file]
7878
ret = subprocess.check_call(la)
7979
self.assertEqual(ret, 0)

tests/test_config_item.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@
3434
# test `_disabled_` with string
3535
TEST_CASE_5 = [{"_name_": "LoadImaged", "_disabled_": "true", "keys": ["image"]}, dict]
3636
# test non-monai modules and excludes
37-
TEST_CASE_6 = [
38-
{"_path_": "torch.optim.Adam", "params": torch.nn.PReLU().parameters(), "lr": 1e-4},
39-
torch.optim.Adam,
40-
]
37+
TEST_CASE_6 = [{"_path_": "torch.optim.Adam", "params": torch.nn.PReLU().parameters(), "lr": 1e-4}, torch.optim.Adam]
4138
TEST_CASE_7 = [{"_name_": "decollate_batch", "detach": True, "pad": True}, partial]
4239
# test args contains "name" field
4340
TEST_CASE_8 = [

tests/test_config_parser.py

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,21 @@
2525
TEST_CASE_1 = [
2626
{
2727
"transform": {
28-
"<name>": "Compose",
29-
"<args>": {
30-
"transforms": [
31-
{"<name>": "LoadImaged", "<args>": {"keys": "image"}},
32-
{
33-
"<name>": "RandTorchVisiond",
34-
"<args>": {"keys": "image", "name": "ColorJitter", "brightness": 0.25},
35-
},
36-
]
37-
},
28+
"_name_": "Compose",
29+
"transforms": [
30+
{"_name_": "LoadImaged", "keys": "image"},
31+
{"_name_": "RandTorchVisiond", "keys": "image", "name": "ColorJitter", "brightness": 0.25},
32+
],
3833
},
39-
"dataset": {"<name>": "Dataset", "<args>": {"data": [1, 2], "transform": "@transform"}},
34+
"dataset": {"_name_": "Dataset", "data": [1, 2], "transform": "@transform"},
4035
"dataloader": {
41-
"<name>": "DataLoader",
42-
"<args>": {"dataset": "@dataset", "batch_size": 2, "collate_fn": "monai.data.list_data_collate"},
36+
"_name_": "DataLoader",
37+
"dataset": "@dataset",
38+
"batch_size": 2,
39+
"collate_fn": "monai.data.list_data_collate",
4340
},
4441
},
45-
["transform", "transform#<args>#transforms#0", "transform#<args>#transforms#1", "dataset", "dataloader"],
42+
["transform", "transform#transforms#0", "transform#transforms#1", "dataset", "dataloader"],
4643
[Compose, LoadImaged, RandTorchVisiond, Dataset, DataLoader],
4744
]
4845

@@ -67,9 +64,9 @@ def __call__(self, a, b):
6764
"cls_func": "$TestClass.cls_compute",
6865
"lambda_static_func": "$lambda x, y: TestClass.compute(x, y)",
6966
"lambda_cls_func": "$lambda x, y: TestClass.cls_compute(x, y)",
70-
"compute": {"<path>": "tests.test_config_parser.TestClass.compute", "<args>": {"func": "@basic_func"}},
71-
"cls_compute": {"<path>": "tests.test_config_parser.TestClass.cls_compute", "<args>": {"func": "@basic_func"}},
72-
"call_compute": {"<path>": "tests.test_config_parser.TestClass"},
67+
"compute": {"_path_": "tests.test_config_parser.TestClass.compute", "func": "@basic_func"},
68+
"cls_compute": {"_path_": "tests.test_config_parser.TestClass.cls_compute", "func": "@basic_func"},
69+
"call_compute": {"_path_": "tests.test_config_parser.TestClass"},
7370
"error_func": "$TestClass.__call__",
7471
"<test>": "$lambda x, y: x + y",
7572
}
@@ -78,17 +75,17 @@ def __call__(self, a, b):
7875

7976
class TestConfigComponent(unittest.TestCase):
8077
def test_config_content(self):
81-
test_config = {"preprocessing": [{"<name>": "LoadImage"}], "dataset": {"<name>": "Dataset"}}
78+
test_config = {"preprocessing": [{"_name_": "LoadImage"}], "dataset": {"_name_": "Dataset"}}
8279
parser = ConfigParser(config=test_config)
8380
# test `get`, `set`, `__getitem__`, `__setitem__`
8481
self.assertEqual(str(parser.get()), str(test_config))
8582
parser.set(config=test_config)
8683
self.assertListEqual(parser["preprocessing"], test_config["preprocessing"])
87-
parser["dataset"] = {"<name>": "CacheDataset"}
88-
self.assertEqual(parser["dataset"]["<name>"], "CacheDataset")
84+
parser["dataset"] = {"_name_": "CacheDataset"}
85+
self.assertEqual(parser["dataset"]["_name_"], "CacheDataset")
8986
# test nested ids
90-
parser["dataset#<name>"] = "Dataset"
91-
self.assertEqual(parser["dataset#<name>"], "Dataset")
87+
parser["dataset#_name_"] = "Dataset"
88+
self.assertEqual(parser["dataset#_name_"], "Dataset")
9289
# test int id
9390
parser.set(["test1", "test2", "test3"])
9491
parser[1] = "test4"
@@ -99,11 +96,11 @@ def test_config_content(self):
9996
def test_parse(self, config, expected_ids, output_types):
10097
parser = ConfigParser(config=config, globals={"monai": "monai"})
10198
# test lazy instantiation with original config content
102-
parser["transform"]["<args>"]["transforms"][0]["<args>"]["keys"] = "label1"
103-
self.assertEqual(parser.get_parsed_content(id="transform#<args>#transforms#0").keys[0], "label1")
99+
parser["transform"]["transforms"][0]["keys"] = "label1"
100+
self.assertEqual(parser.get_parsed_content(id="transform#transforms#0").keys[0], "label1")
104101
# test nested id
105-
parser["transform#<args>#transforms#0#<args>#keys"] = "label2"
106-
self.assertEqual(parser.get_parsed_content(id="transform#<args>#transforms#0").keys[0], "label2")
102+
parser["transform#transforms#0#keys"] = "label2"
103+
self.assertEqual(parser.get_parsed_content(id="transform#transforms#0").keys[0], "label2")
107104
for id, cls in zip(expected_ids, output_types):
108105
self.assertTrue(isinstance(parser.get_parsed_content(id), cls))
109106
# test root content

tests/test_reference_resolver.py

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,10 @@
2727
TEST_CASE_1 = [
2828
{
2929
# all the recursively parsed config items
30-
"transform#1": {"<name>": "LoadImaged", "<args>": {"keys": ["image"]}},
31-
"transform#1#<name>": "LoadImaged",
32-
"transform#1#<args>": {"keys": ["image"]},
33-
"transform#1#<args>#keys": ["image"],
34-
"transform#1#<args>#keys#0": "image",
30+
"transform#1": {"_name_": "LoadImaged", "keys": ["image"]},
31+
"transform#1#_name_": "LoadImaged",
32+
"transform#1#keys": ["image"],
33+
"transform#1#keys#0": "image",
3534
},
3635
"transform#1",
3736
LoadImaged,
@@ -40,20 +39,15 @@
4039
TEST_CASE_2 = [
4140
{
4241
# some the recursively parsed config items
43-
"dataloader": {
44-
"<name>": "DataLoader",
45-
"<args>": {"dataset": "@dataset", "collate_fn": "$monai.data.list_data_collate"},
46-
},
47-
"dataset": {"<name>": "Dataset", "<args>": {"data": [1, 2]}},
48-
"dataloader#<name>": "DataLoader",
49-
"dataloader#<args>": {"dataset": "@dataset", "collate_fn": "$monai.data.list_data_collate"},
50-
"dataloader#<args>#dataset": "@dataset",
51-
"dataloader#<args>#collate_fn": "$monai.data.list_data_collate",
52-
"dataset#<name>": "Dataset",
53-
"dataset#<args>": {"data": [1, 2]},
54-
"dataset#<args>#data": [1, 2],
55-
"dataset#<args>#data#0": 1,
56-
"dataset#<args>#data#1": 2,
42+
"dataloader": {"_name_": "DataLoader", "dataset": "@dataset", "collate_fn": "$monai.data.list_data_collate"},
43+
"dataset": {"_name_": "Dataset", "data": [1, 2]},
44+
"dataloader#_name_": "DataLoader",
45+
"dataloader#dataset": "@dataset",
46+
"dataloader#collate_fn": "$monai.data.list_data_collate",
47+
"dataset#_name_": "Dataset",
48+
"dataset#data": [1, 2],
49+
"dataset#data#0": 1,
50+
"dataset#data#1": 2,
5751
},
5852
"dataloader",
5953
DataLoader,
@@ -62,15 +56,11 @@
6256
TEST_CASE_3 = [
6357
{
6458
# all the recursively parsed config items
65-
"transform#1": {
66-
"<name>": "RandTorchVisiond",
67-
"<args>": {"keys": "image", "name": "ColorJitter", "brightness": 0.25},
68-
},
69-
"transform#1#<name>": "RandTorchVisiond",
70-
"transform#1#<args>": {"keys": "image", "name": "ColorJitter", "brightness": 0.25},
71-
"transform#1#<args>#keys": "image",
72-
"transform#1#<args>#name": "ColorJitter",
73-
"transform#1#<args>#brightness": 0.25,
59+
"transform#1": {"_name_": "RandTorchVisiond", "keys": "image", "name": "ColorJitter", "brightness": 0.25},
60+
"transform#1#_name_": "RandTorchVisiond",
61+
"transform#1#keys": "image",
62+
"transform#1#name": "ColorJitter",
63+
"transform#1#brightness": 0.25,
7464
},
7565
"transform#1",
7666
RandTorchVisiond,
@@ -97,7 +87,7 @@ def test_resolve(self, configs, expected_id, output_type):
9787
# test lazy instantiation
9888
item = resolver.get_item(expected_id, resolve=True)
9989
config = item.get_config()
100-
config["<disabled>"] = False
90+
config["_disabled_"] = False
10191
item.update_config(config=config)
10292
if isinstance(item, ConfigComponent):
10393
result = item.instantiate()

0 commit comments

Comments
 (0)