From fefa39a9d47faafadc763bfb237dd8a06ac87d74 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 16 Dec 2021 10:40:08 +0800 Subject: [PATCH 01/17] [DLMED] add folder structure Signed-off-by: Nic Ma --- .../spleen_segmentation/commands/export.sh | 0 .../spleen_segmentation/commands/infer.sh | 0 .../configs/inference.json | 0 .../spleen_segmentation/configs/metadata.json | 0 .../spleen_segmentation/docs/README.md | 31 +++++++++++++++++++ .../spleen_segmentation/docs/license.txt | 6 ++++ .../spleen_segmentation/programs/__init__.py | 0 7 files changed, 37 insertions(+) create mode 100644 modules/model_package/spleen_segmentation/commands/export.sh create mode 100644 modules/model_package/spleen_segmentation/commands/infer.sh create mode 100644 modules/model_package/spleen_segmentation/configs/inference.json create mode 100644 modules/model_package/spleen_segmentation/configs/metadata.json create mode 100644 modules/model_package/spleen_segmentation/docs/README.md create mode 100644 modules/model_package/spleen_segmentation/docs/license.txt create mode 100644 modules/model_package/spleen_segmentation/programs/__init__.py diff --git a/modules/model_package/spleen_segmentation/commands/export.sh b/modules/model_package/spleen_segmentation/commands/export.sh new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/model_package/spleen_segmentation/commands/infer.sh b/modules/model_package/spleen_segmentation/commands/infer.sh new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/model_package/spleen_segmentation/configs/inference.json b/modules/model_package/spleen_segmentation/configs/inference.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/model_package/spleen_segmentation/configs/metadata.json b/modules/model_package/spleen_segmentation/configs/metadata.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/model_package/spleen_segmentation/docs/README.md b/modules/model_package/spleen_segmentation/docs/README.md new file mode 100644 index 0000000000..e8839a7fe8 --- /dev/null +++ b/modules/model_package/spleen_segmentation/docs/README.md @@ -0,0 +1,31 @@ +# Description +A pre-trained model for volumetric (3D) segmentation of the spleen from CT image. + +# Model Overview +This model is trained using the runnerup [1] awarded pipeline of the "Medical Segmentation Decathlon Challenge 2018" using the UNet architecture [2] with 32 training images and 9 validation images. + +## Data +The training dataset is Task09_Spleen.tar from http://medicaldecathlon.com/. + +## Training configuration +The training was performed with command train.sh, which required 12GB-memory GPUs. + +Actual Model Input: 96 x 96 x 96 + +## Input and output formats +Input: 1 channel CT image + +Output: 2 channels: Label 1: spleen; Label 0: everything else + +## Scores +This model achieve the following Dice score on the validation data (our own split from the training dataset): + +Mean dice = 0.96 + +# Disclaimer +This is an example, not to be used for diagnostic purposes. + +# References +[1] Xia, Yingda, et al. "3D Semi-Supervised Learning with Uncertainty-Aware Multi-View Co-Training." arXiv preprint arXiv:1811.12506 (2018). https://arxiv.org/abs/1811.12506. + +[2] Kerfoot E., Clough J., Oksuz I., Lee J., King A.P., Schnabel J.A. (2019) Left-Ventricle Quantification Using Residual U-Net. In: Pop M. et al. (eds) Statistical Atlases and Computational Models of the Heart. Atrial Segmentation and LV Quantification Challenges. STACOM 2018. Lecture Notes in Computer Science, vol 11395. Springer, Cham. https://doi.org/10.1007/978-3-030-12029-0_40 diff --git a/modules/model_package/spleen_segmentation/docs/license.txt b/modules/model_package/spleen_segmentation/docs/license.txt new file mode 100644 index 0000000000..5cffccb114 --- /dev/null +++ b/modules/model_package/spleen_segmentation/docs/license.txt @@ -0,0 +1,6 @@ +Third Party Licenses +----------------------------------------------------------------------- + +/*********************************************************************/ +i. Medical Segmentation Decathlon + http://medicaldecathlon.com/ diff --git a/modules/model_package/spleen_segmentation/programs/__init__.py b/modules/model_package/spleen_segmentation/programs/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 97ebc382637c2d0e153251b78fa55fd7c2fa11df Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 16 Dec 2021 12:10:14 +0800 Subject: [PATCH 02/17] [DLMED] add more components Signed-off-by: Nic Ma --- .../spleen_segmentation/commands/export.sh | 1 + .../spleen_segmentation/commands/inference.sh | 1 + .../configs/inference.json | 144 ++++++++++++++++++ .../spleen_segmentation/configs/metadata.json | 26 ++++ .../{commands/infer.sh => models/model.pt} | 0 .../spleen_segmentation/models/model.ts | 0 .../spleen_segmentation/programs/__init__.py | 11 ++ .../spleen_segmentation/programs/export.py | 13 ++ .../spleen_segmentation/programs/inference.py | 13 ++ 9 files changed, 209 insertions(+) create mode 100644 modules/model_package/spleen_segmentation/commands/inference.sh rename modules/model_package/spleen_segmentation/{commands/infer.sh => models/model.pt} (100%) create mode 100644 modules/model_package/spleen_segmentation/models/model.ts create mode 100644 modules/model_package/spleen_segmentation/programs/export.py create mode 100644 modules/model_package/spleen_segmentation/programs/inference.py diff --git a/modules/model_package/spleen_segmentation/commands/export.sh b/modules/model_package/spleen_segmentation/commands/export.sh index e69de29bb2..ca843f1c49 100644 --- a/modules/model_package/spleen_segmentation/commands/export.sh +++ b/modules/model_package/spleen_segmentation/commands/export.sh @@ -0,0 +1 @@ +python ../programs/export.py diff --git a/modules/model_package/spleen_segmentation/commands/inference.sh b/modules/model_package/spleen_segmentation/commands/inference.sh new file mode 100644 index 0000000000..d573c03cf6 --- /dev/null +++ b/modules/model_package/spleen_segmentation/commands/inference.sh @@ -0,0 +1 @@ +python ../programs/inference.py diff --git a/modules/model_package/spleen_segmentation/configs/inference.json b/modules/model_package/spleen_segmentation/configs/inference.json index e69de29bb2..4cbe128cb9 100644 --- a/modules/model_package/spleen_segmentation/configs/inference.json +++ b/modules/model_package/spleen_segmentation/configs/inference.json @@ -0,0 +1,144 @@ +{ + "multi_gpu": false, + "amp": true, + "model": { + "ts_path": "../models/model.ts" + }, + "network": { + "name": "UNet", + "args": { + "spatial_dims": 3, + "in_channels": 1, + "out_channels": 2, + "channels": [16, 32, 64, 128, 256], + "strides": [2, 2, 2, 2], + "num_res_units": 2, + "norm": "batch" + } + }, + "pre_transforms": [ + { + "name": "LoadImaged", + "args": { + "keys": "image" + } + }, + { + "name": "Spacingd", + "args": { + "keys": "image", + "pixdim": [1.5, 1.5, 2], + "mode": "bilinear" + } + }, + { + "name": "Orientationd", + "args": { + "keys": "image", + "axcodes": "RAS" + } + }, + { + "name": "EnsureChannelFirstd", + "args": { + "keys": "image" + } + }, + { + "name": "ScaleIntensityRanged", + "args": { + "keys": "image", + "a_min": -57, + "a_max": 164, + "b_min": 0, + "b_max": 1, + "clip": true + } + }, + { + "name": "CropForegroundd", + "args": { + "keys": "image", + "source_key": "image" + } + }, + { + "name": "ToTensord", + "args": { + "keys": "image" + } + } + ], + "datalist": { + "name": "DatasetFunc", + "args": { + "data": "#@dataset_dir + '/dataset.json'", + "func": "monai.data.load_decathlon_datalist", + "is_segmentation": true, + "data_list_key": "test", + "base_dir": "@dataset_dir" + } + }, + "dataset": { + "name": "Dataset", + "args": { + "data": "@datalist", + "transform": "@pre_transforms" + } + }, + "dataloader": { + "name": "DataLoader", + "args": { + "dataset": "@dataset", + "batch_size": 1, + "shuffle": false, + "num_workers": 4 + } + }, + "inferer": { + "name": "SlidingWindowInferer", + "args": { + "roi_size": [160, 160, 160], + "sw_batch_size": 4, + "overlap": 0.5 + } + }, + "post_transforms": [ + { + "name": "Activationsd", + "args": { + "keys": "pred", + "softmax": true + } + }, + { + "name": "Invertd", + "args": { + "keys": "pred", + "transform": "@pre_transforms", + "orig_keys": "image", + "meta_keys": "pred_meta_dict", + "nearest_interp": false, + "to_tensor": true, + "device": "cuda" + } + }, + { + "name": "AsDiscreted", + "args": { + "keys": "pred", + "argmax": true + } + }, + { + "name": "SaveImaged", + "args": { + "keys": "pred", + "meta_keys": "pred_meta_dict", + "output_dir": "{MMAR_EVAL_OUTPUT_PATH}", + "resample": false, + "squeeze_end_dims": true + } + } + ] +} diff --git a/modules/model_package/spleen_segmentation/configs/metadata.json b/modules/model_package/spleen_segmentation/configs/metadata.json index e69de29bb2..4de86335b3 100644 --- a/modules/model_package/spleen_segmentation/configs/metadata.json +++ b/modules/model_package/spleen_segmentation/configs/metadata.json @@ -0,0 +1,26 @@ +{ + "version": "0.1.0", + "monai_version": "0.8.0", + "pytorch_version": "1.10.0", + "numpy_version": "1.21.2", + "optional_packages_version": {"nibabel": "3.2.1"}, + "task": "Decathlon spleen segmentation", + "description": "A pre-trained model for volumetric (3D) segmentation of the spleen from CT image", + "authorship": "MONAI team", + "data_source": "Task09_Spleen.tar from http://medicaldecathlon.com/", + "dataset_dir": "/workspace/data/Task09_Spleen", + "image_classes": "single channel data, intensity scaled to [0, 1]", + "label_classes": "single channel data, 1 is spleen, 0 is everything else", + "pred_classes": "2 channels OneHot data, channel 1 is spleen, channel 0 is background", + "image_shape": [1, 160, 160, 160], + "label_shape": [1, 160, 160, 160], + "pred_shape": [2, 160, 160, 160], + "eval_metrics": { + "mean_dice": 0.96 + }, + "intended_use": "This is an example, not to be used for diagnostic purposes", + "references": [ + "Xia, Yingda, et al. '3D Semi-Supervised Learning with Uncertainty-Aware Multi-View Co-Training.' arXiv preprint arXiv:1811.12506 (2018). https://arxiv.org/abs/1811.12506.", + "Kerfoot E., Clough J., Oksuz I., Lee J., King A.P., Schnabel J.A. (2019) Left-Ventricle Quantification Using Residual U-Net. In: Pop M. et al. (eds) Statistical Atlases and Computational Models of the Heart. Atrial Segmentation and LV Quantification Challenges. STACOM 2018. Lecture Notes in Computer Science, vol 11395. Springer, Cham. https://doi.org/10.1007/978-3-030-12029-0_40" + ] +} diff --git a/modules/model_package/spleen_segmentation/commands/infer.sh b/modules/model_package/spleen_segmentation/models/model.pt similarity index 100% rename from modules/model_package/spleen_segmentation/commands/infer.sh rename to modules/model_package/spleen_segmentation/models/model.pt diff --git a/modules/model_package/spleen_segmentation/models/model.ts b/modules/model_package/spleen_segmentation/models/model.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/model_package/spleen_segmentation/programs/__init__.py b/modules/model_package/spleen_segmentation/programs/__init__.py index e69de29bb2..7e5ba0883c 100644 --- a/modules/model_package/spleen_segmentation/programs/__init__.py +++ b/modules/model_package/spleen_segmentation/programs/__init__.py @@ -0,0 +1,11 @@ + +# Copyright 2020 - 2021 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. diff --git a/modules/model_package/spleen_segmentation/programs/export.py b/modules/model_package/spleen_segmentation/programs/export.py new file mode 100644 index 0000000000..b04c9f82e1 --- /dev/null +++ b/modules/model_package/spleen_segmentation/programs/export.py @@ -0,0 +1,13 @@ + +# Copyright 2020 - 2021 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. + +# TODO diff --git a/modules/model_package/spleen_segmentation/programs/inference.py b/modules/model_package/spleen_segmentation/programs/inference.py new file mode 100644 index 0000000000..b04c9f82e1 --- /dev/null +++ b/modules/model_package/spleen_segmentation/programs/inference.py @@ -0,0 +1,13 @@ + +# Copyright 2020 - 2021 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. + +# TODO From 1c56a479a94d4951c85fd0ccf95f9a9e4781f69f Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 16 Dec 2021 12:15:35 +0800 Subject: [PATCH 03/17] [DLMED] add changelog Signed-off-by: Nic Ma --- .../model_package/spleen_segmentation/configs/metadata.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/model_package/spleen_segmentation/configs/metadata.json b/modules/model_package/spleen_segmentation/configs/metadata.json index 4de86335b3..108e07b395 100644 --- a/modules/model_package/spleen_segmentation/configs/metadata.json +++ b/modules/model_package/spleen_segmentation/configs/metadata.json @@ -1,5 +1,9 @@ { "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", "pytorch_version": "1.10.0", "numpy_version": "1.21.2", From 607c817fcff5a054af6354744f5ebbb58d180e6b Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 16 Dec 2021 16:02:46 +0800 Subject: [PATCH 04/17] [DLMED] add export logic Signed-off-by: Nic Ma --- .../spleen_segmentation/commands/export.sh | 3 ++ .../spleen_segmentation/programs/export.py | 47 ++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/modules/model_package/spleen_segmentation/commands/export.sh b/modules/model_package/spleen_segmentation/commands/export.sh index ca843f1c49..e29559708e 100644 --- a/modules/model_package/spleen_segmentation/commands/export.sh +++ b/modules/model_package/spleen_segmentation/commands/export.sh @@ -1 +1,4 @@ python ../programs/export.py + --weights ../models/model.pt + --config ../configs/inference.json + --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/programs/export.py b/modules/model_package/spleen_segmentation/programs/export.py index b04c9f82e1..e668740e44 100644 --- a/modules/model_package/spleen_segmentation/programs/export.py +++ b/modules/model_package/spleen_segmentation/programs/export.py @@ -10,4 +10,49 @@ # See the License for the specific language governing permissions and # limitations under the License. -# TODO +import argparse +import json + +import torch +from ignite.handlers import Checkpoint +from monai.data import save_net_with_metadata +from monai.networks import convert_to_torchscript + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--weights', '-w', type=str, help='file path of the trained model weights', required=True) + parser.add_argument('--config', '-c', type=str, help='file path of config file that defines network', required=True) + parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') + args = parser.parse_args() + + with open(args.config, "r") as f: + cofnig_dict = json.load(f) + + net: torch.nn.Module = None + # TODO: parse network definiftion from config file and construct network instance + # net = parse_config(config_dict).get_component("network") + + checkpoint = torch.load(args.weights) + # here we use ignite Checkpoint to support nested weights and be compatible with MONAI CheckpointSaver + Checkpoint.load_objects(to_load={"model": net}, checkpoint=checkpoint) + + # convert to TorchScript model and save with meta data + net = convert_to_torchscript(model=net) + + # load meta data + with open(args.meta, "r") as f: + meta_dict = json.load(f) + + save_net_with_metadata( + jit_obj=net, + filename_prefix_or_stream="model.ts", + include_config_vals=False, + append_timestamp=False, + meta_values=meta_dict, + more_extra_files={args.config: json.dumps(cofnig_dict).encode()}, + ) + + +if __name__ == '__main__': + main() From e87bc37d9c5c59f45fa6fad44e94b4626f90f5d6 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 16 Dec 2021 16:35:02 +0800 Subject: [PATCH 05/17] [DLMED] add inference logic Signed-off-by: Nic Ma --- .../spleen_segmentation/commands/inference.sh | 2 + .../configs/inference.json | 4 +- .../spleen_segmentation/programs/export.py | 11 +++-- .../spleen_segmentation/programs/inference.py | 49 ++++++++++++++++++- 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/modules/model_package/spleen_segmentation/commands/inference.sh b/modules/model_package/spleen_segmentation/commands/inference.sh index d573c03cf6..12a5bf58a8 100644 --- a/modules/model_package/spleen_segmentation/commands/inference.sh +++ b/modules/model_package/spleen_segmentation/commands/inference.sh @@ -1 +1,3 @@ python ../programs/inference.py + --config ../configs/inference.json + --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/configs/inference.json b/modules/model_package/spleen_segmentation/configs/inference.json index 4cbe128cb9..933db5ca1e 100644 --- a/modules/model_package/spleen_segmentation/configs/inference.json +++ b/modules/model_package/spleen_segmentation/configs/inference.json @@ -1,9 +1,7 @@ { "multi_gpu": false, "amp": true, - "model": { - "ts_path": "../models/model.ts" - }, + "model": "monai.data.load_net_with_metadata('../models/model.ts')[0]", "network": { "name": "UNet", "args": { diff --git a/modules/model_package/spleen_segmentation/programs/export.py b/modules/model_package/spleen_segmentation/programs/export.py index e668740e44..5740f7fc3a 100644 --- a/modules/model_package/spleen_segmentation/programs/export.py +++ b/modules/model_package/spleen_segmentation/programs/export.py @@ -26,12 +26,17 @@ def main(): parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') args = parser.parse_args() + # load config file with open(args.config, "r") as f: cofnig_dict = json.load(f) + # load meta data + with open(args.meta, "r") as f: + meta_dict = json.load(f) net: torch.nn.Module = None # TODO: parse network definiftion from config file and construct network instance - # net = parse_config(config_dict).get_component("network") + # config_parser = ConfigParser(config_dict, meta_dict) + # net = config_parser.get_component("network") checkpoint = torch.load(args.weights) # here we use ignite Checkpoint to support nested weights and be compatible with MONAI CheckpointSaver @@ -40,10 +45,6 @@ def main(): # convert to TorchScript model and save with meta data net = convert_to_torchscript(model=net) - # load meta data - with open(args.meta, "r") as f: - meta_dict = json.load(f) - save_net_with_metadata( jit_obj=net, filename_prefix_or_stream="model.ts", diff --git a/modules/model_package/spleen_segmentation/programs/inference.py b/modules/model_package/spleen_segmentation/programs/inference.py index b04c9f82e1..98e8f5f358 100644 --- a/modules/model_package/spleen_segmentation/programs/inference.py +++ b/modules/model_package/spleen_segmentation/programs/inference.py @@ -10,4 +10,51 @@ # See the License for the specific language governing permissions and # limitations under the License. -# TODO +import argparse +import json + +import torch +from monai.data import decollate_batch +from monai.inferers import Inferer +from monai.transforms import Transform +from monai.utils.enums import CommonKeys + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--config', '-c', type=str, help='file path of config file that defines network', required=True) + parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') + args = parser.parse_args() + + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + # load config file + with open(args.config, "r") as f: + cofnig_dict = json.load(f) + # load meta data + with open(args.meta, "r") as f: + meta_dict = json.load(f) + + net: torch.nn.Module = None + dataloader: torch.utils.data.DataLoader = None + inferer: Inferer = None + post_transforms: Transform = None + # TODO: parse inference config file and construct instances + # config_parser = ConfigParser(config_dict, meta_dict) + # net = config_parser.get_component("model").to(device) + # dataloader = config_parser.get_component("dataloader") + # inferer = config_parser.get_component("inferer") + # post_transforms = config_parser.get_component("post_transforms") + + net.eval() + with torch.no_grad(): + for d in dataloader: + images = d[CommonKeys.IMAGE].to(device) + # define sliding window size and batch size for windows inference + d[CommonKeys.PRED] = inferer(inputs=images, predictor=net) + # decollate the batch data into a list of dictionaries, then execute postprocessing transforms + d = [post_transforms(i) for i in decollate_batch(d)] + + +if __name__ == '__main__': + main() From a6e282d0f98c7fa6ae93045f9bea9118a1a4a5b5 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Fri, 17 Dec 2021 09:09:14 +0800 Subject: [PATCH 06/17] [DLMED] update to pre / post processing according to Wenqi's comments Signed-off-by: Nic Ma --- .../spleen_segmentation/configs/inference.json | 8 ++++---- .../spleen_segmentation/programs/inference.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/model_package/spleen_segmentation/configs/inference.json b/modules/model_package/spleen_segmentation/configs/inference.json index 933db5ca1e..f98d90b592 100644 --- a/modules/model_package/spleen_segmentation/configs/inference.json +++ b/modules/model_package/spleen_segmentation/configs/inference.json @@ -14,7 +14,7 @@ "norm": "batch" } }, - "pre_transforms": [ + "preprocessing": [ { "name": "LoadImaged", "args": { @@ -81,7 +81,7 @@ "name": "Dataset", "args": { "data": "@datalist", - "transform": "@pre_transforms" + "transform": "@preprocessing" } }, "dataloader": { @@ -101,7 +101,7 @@ "overlap": 0.5 } }, - "post_transforms": [ + "postprocessing": [ { "name": "Activationsd", "args": { @@ -113,7 +113,7 @@ "name": "Invertd", "args": { "keys": "pred", - "transform": "@pre_transforms", + "transform": "@preprocessing", "orig_keys": "image", "meta_keys": "pred_meta_dict", "nearest_interp": false, diff --git a/modules/model_package/spleen_segmentation/programs/inference.py b/modules/model_package/spleen_segmentation/programs/inference.py index 98e8f5f358..7a91d1165a 100644 --- a/modules/model_package/spleen_segmentation/programs/inference.py +++ b/modules/model_package/spleen_segmentation/programs/inference.py @@ -38,13 +38,13 @@ def main(): net: torch.nn.Module = None dataloader: torch.utils.data.DataLoader = None inferer: Inferer = None - post_transforms: Transform = None + postprocessing: Transform = None # TODO: parse inference config file and construct instances # config_parser = ConfigParser(config_dict, meta_dict) # net = config_parser.get_component("model").to(device) # dataloader = config_parser.get_component("dataloader") # inferer = config_parser.get_component("inferer") - # post_transforms = config_parser.get_component("post_transforms") + # postprocessing = config_parser.get_component("postprocessing") net.eval() with torch.no_grad(): @@ -53,7 +53,7 @@ def main(): # define sliding window size and batch size for windows inference d[CommonKeys.PRED] = inferer(inputs=images, predictor=net) # decollate the batch data into a list of dictionaries, then execute postprocessing transforms - d = [post_transforms(i) for i in decollate_batch(d)] + d = [postprocessing(i) for i in decollate_batch(d)] if __name__ == '__main__': From 0a88da14d794420d099b28d448de830f9a152c32 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 5 Jan 2022 00:30:12 +0800 Subject: [PATCH 07/17] [DLMED] update according to comments Signed-off-by: Nic Ma --- modules/model_package/spleen_segmentation/commands/export.sh | 2 +- modules/model_package/spleen_segmentation/commands/inference.sh | 2 +- .../spleen_segmentation/{programs => scripts}/__init__.py | 0 .../spleen_segmentation/{programs => scripts}/export.py | 0 .../spleen_segmentation/{programs => scripts}/inference.py | 0 5 files changed, 2 insertions(+), 2 deletions(-) rename modules/model_package/spleen_segmentation/{programs => scripts}/__init__.py (100%) rename modules/model_package/spleen_segmentation/{programs => scripts}/export.py (100%) rename modules/model_package/spleen_segmentation/{programs => scripts}/inference.py (100%) diff --git a/modules/model_package/spleen_segmentation/commands/export.sh b/modules/model_package/spleen_segmentation/commands/export.sh index e29559708e..1f70efddf7 100644 --- a/modules/model_package/spleen_segmentation/commands/export.sh +++ b/modules/model_package/spleen_segmentation/commands/export.sh @@ -1,4 +1,4 @@ -python ../programs/export.py +python ../scripts/export.py --weights ../models/model.pt --config ../configs/inference.json --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/commands/inference.sh b/modules/model_package/spleen_segmentation/commands/inference.sh index 12a5bf58a8..93c0590bbb 100644 --- a/modules/model_package/spleen_segmentation/commands/inference.sh +++ b/modules/model_package/spleen_segmentation/commands/inference.sh @@ -1,3 +1,3 @@ -python ../programs/inference.py +python ../scripts/inference.py --config ../configs/inference.json --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/programs/__init__.py b/modules/model_package/spleen_segmentation/scripts/__init__.py similarity index 100% rename from modules/model_package/spleen_segmentation/programs/__init__.py rename to modules/model_package/spleen_segmentation/scripts/__init__.py diff --git a/modules/model_package/spleen_segmentation/programs/export.py b/modules/model_package/spleen_segmentation/scripts/export.py similarity index 100% rename from modules/model_package/spleen_segmentation/programs/export.py rename to modules/model_package/spleen_segmentation/scripts/export.py diff --git a/modules/model_package/spleen_segmentation/programs/inference.py b/modules/model_package/spleen_segmentation/scripts/inference.py similarity index 100% rename from modules/model_package/spleen_segmentation/programs/inference.py rename to modules/model_package/spleen_segmentation/scripts/inference.py From 1b01dad368dff0c0b70cac01a93166ce93b8b972 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Mon, 17 Jan 2022 12:14:57 +0800 Subject: [PATCH 08/17] [DLMED] add more features Signed-off-by: Nic Ma --- .../commands/inference_v2.sh | 4 ++ .../spleen_segmentation/commands/trtinfer.sh | 3 + .../configs/inference.json | 2 +- .../configs/inference_v2.json | 23 +++++++ .../spleen_segmentation/configs/trtinfer.json | 19 ++++++ .../spleen_segmentation/scripts/export.py | 9 +-- .../spleen_segmentation/scripts/inference.py | 36 ++++++---- .../scripts/inference_v2.py | 67 +++++++++++++++++++ .../spleen_segmentation/scripts/trtinfer.py | 59 ++++++++++++++++ 9 files changed, 203 insertions(+), 19 deletions(-) create mode 100644 modules/model_package/spleen_segmentation/commands/inference_v2.sh create mode 100644 modules/model_package/spleen_segmentation/commands/trtinfer.sh create mode 100644 modules/model_package/spleen_segmentation/configs/inference_v2.json create mode 100644 modules/model_package/spleen_segmentation/configs/trtinfer.json create mode 100644 modules/model_package/spleen_segmentation/scripts/inference_v2.py create mode 100644 modules/model_package/spleen_segmentation/scripts/trtinfer.py diff --git a/modules/model_package/spleen_segmentation/commands/inference_v2.sh b/modules/model_package/spleen_segmentation/commands/inference_v2.sh new file mode 100644 index 0000000000..572b223dcf --- /dev/null +++ b/modules/model_package/spleen_segmentation/commands/inference_v2.sh @@ -0,0 +1,4 @@ +python ../scripts/inference.py + --base_config ../configs/inference.json + --config ../configs/inference_v2.json + --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/commands/trtinfer.sh b/modules/model_package/spleen_segmentation/commands/trtinfer.sh new file mode 100644 index 0000000000..1df47fbcc1 --- /dev/null +++ b/modules/model_package/spleen_segmentation/commands/trtinfer.sh @@ -0,0 +1,3 @@ +python ../scripts/inference.py + --config ../configs/trtinfer.json + --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/configs/inference.json b/modules/model_package/spleen_segmentation/configs/inference.json index f98d90b592..db831a3c85 100644 --- a/modules/model_package/spleen_segmentation/configs/inference.json +++ b/modules/model_package/spleen_segmentation/configs/inference.json @@ -1,7 +1,7 @@ { "multi_gpu": false, "amp": true, - "model": "monai.data.load_net_with_metadata('../models/model.ts')[0]", + "model": "#monai.data.load_net_with_metadata('../models/model.ts')[0]", "network": { "name": "UNet", "args": { diff --git a/modules/model_package/spleen_segmentation/configs/inference_v2.json b/modules/model_package/spleen_segmentation/configs/inference_v2.json new file mode 100644 index 0000000000..8f2ad18305 --- /dev/null +++ b/modules/model_package/spleen_segmentation/configs/inference_v2.json @@ -0,0 +1,23 @@ +{ + "amp": false, + "network": { + "name": "UNet", + "args": { + "spatial_dims": 3, + "in_channels": 1, + "out_channels": 2, + "channels": [32, 64, 128, 256, 512], + "strides": [2, 2, 2, 2], + "num_res_units": 2, + "norm": "group" + } + }, + "inferer": { + "name": "SlidingWindowInferer", + "args": { + "roi_size": [96, 96, 96], + "sw_batch_size": 4, + "overlap": 0.6 + } + } +} diff --git a/modules/model_package/spleen_segmentation/configs/trtinfer.json b/modules/model_package/spleen_segmentation/configs/trtinfer.json new file mode 100644 index 0000000000..435b742be2 --- /dev/null +++ b/modules/model_package/spleen_segmentation/configs/trtinfer.json @@ -0,0 +1,19 @@ +{ + "preprocessing": { + "ref": { + "path": "../inference.json/preprocessing" + } + }, + "dataset": { + "ref": { + "path": "../inference.json/dataset" + } + }, + "model": "#load_trt_model(...)", + "dataloader": { + "name": "DALIpipeline" + }, + "inferer": { + "name": "TensorRTInferer" + } +} diff --git a/modules/model_package/spleen_segmentation/scripts/export.py b/modules/model_package/spleen_segmentation/scripts/export.py index 5740f7fc3a..22f76f90b8 100644 --- a/modules/model_package/spleen_segmentation/scripts/export.py +++ b/modules/model_package/spleen_segmentation/scripts/export.py @@ -14,6 +14,7 @@ import json import torch +from monai.apps import ConfigParser from ignite.handlers import Checkpoint from monai.data import save_net_with_metadata from monai.networks import convert_to_torchscript @@ -28,15 +29,15 @@ def main(): # load config file with open(args.config, "r") as f: - cofnig_dict = json.load(f) + config_dict = json.load(f) # load meta data with open(args.meta, "r") as f: meta_dict = json.load(f) net: torch.nn.Module = None # TODO: parse network definiftion from config file and construct network instance - # config_parser = ConfigParser(config_dict, meta_dict) - # net = config_parser.get_component("network") + config_parser = ConfigParser(config_dict) + net = config_parser.get_instance("network") checkpoint = torch.load(args.weights) # here we use ignite Checkpoint to support nested weights and be compatible with MONAI CheckpointSaver @@ -51,7 +52,7 @@ def main(): include_config_vals=False, append_timestamp=False, meta_values=meta_dict, - more_extra_files={args.config: json.dumps(cofnig_dict).encode()}, + more_extra_files={args.config: json.dumps(config_dict).encode()}, ) diff --git a/modules/model_package/spleen_segmentation/scripts/inference.py b/modules/model_package/spleen_segmentation/scripts/inference.py index 7a91d1165a..9f667f9c4b 100644 --- a/modules/model_package/spleen_segmentation/scripts/inference.py +++ b/modules/model_package/spleen_segmentation/scripts/inference.py @@ -14,6 +14,7 @@ import json import torch +from monai.apps import ConfigParser from monai.data import decollate_batch from monai.inferers import Inferer from monai.transforms import Transform @@ -22,38 +23,45 @@ def main(): parser = argparse.ArgumentParser() - parser.add_argument('--config', '-c', type=str, help='file path of config file that defines network', required=True) + parser.add_argument('--config', '-c', type=str, help='config file that defines components', required=True) parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') args = parser.parse_args() device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + configs = {} - # load config file - with open(args.config, "r") as f: - cofnig_dict = json.load(f) # load meta data with open(args.meta, "r") as f: - meta_dict = json.load(f) + configs.update(json.load(f)) + # load config file, can override meta data in config + with open(args.config, "r") as f: + configs.update(json.load(f)) - net: torch.nn.Module = None + model: torch.nn.Module = None dataloader: torch.utils.data.DataLoader = None inferer: Inferer = None postprocessing: Transform = None # TODO: parse inference config file and construct instances - # config_parser = ConfigParser(config_dict, meta_dict) - # net = config_parser.get_component("model").to(device) - # dataloader = config_parser.get_component("dataloader") - # inferer = config_parser.get_component("inferer") - # postprocessing = config_parser.get_component("postprocessing") + config_parser = ConfigParser(configs) + + # change JSON config content in python code, lazy instantiation + model_conf = config_parser.get_config("model") + model_conf["disabled"] = False + model = config_parser.build(model_conf).to(device) + + # instantialize the components immediately + dataloader = config_parser.get_instance("dataloader") + inferer = config_parser.get_instance("inferer") + postprocessing = config_parser.get_instance("postprocessing") - net.eval() + model.eval() with torch.no_grad(): for d in dataloader: images = d[CommonKeys.IMAGE].to(device) # define sliding window size and batch size for windows inference - d[CommonKeys.PRED] = inferer(inputs=images, predictor=net) + d[CommonKeys.PRED] = inferer(inputs=images, predictor=model) # decollate the batch data into a list of dictionaries, then execute postprocessing transforms - d = [postprocessing(i) for i in decollate_batch(d)] + [postprocessing(i) for i in decollate_batch(d)] if __name__ == '__main__': diff --git a/modules/model_package/spleen_segmentation/scripts/inference_v2.py b/modules/model_package/spleen_segmentation/scripts/inference_v2.py new file mode 100644 index 0000000000..2f1b7ea0cd --- /dev/null +++ b/modules/model_package/spleen_segmentation/scripts/inference_v2.py @@ -0,0 +1,67 @@ + +# Copyright 2020 - 2021 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. + +import argparse +import json + +import torch +from monai.apps import ConfigParser +from monai.data import decollate_batch +from monai.inferers import Inferer +from monai.transforms import Transform +from monai.utils.enums import CommonKeys + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--base_config', '-c', type=str, help='file path of base config', required=False) + parser.add_argument('--config', '-c', type=str, help='config file to override base config', required=True) + parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') + args = parser.parse_args() + + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + configs = {} + + # load meta data + with open(args.meta, "r") as f: + configs.update(json.load(f)) + # load base config file, can override meta data in config + with open(args.base_config, "r") as f: + configs.update(json.load(f)) + # load config file, add or override the content of base config + with open(args.config, "r") as f: + configs.update(json.load(f)) + + model: torch.nn.Module = None + dataloader: torch.utils.data.DataLoader = None + inferer: Inferer = None + postprocessing: Transform = None + # TODO: parse inference config file and construct instances + config_parser = ConfigParser(configs) + # instantialize the components immediately + model = config_parser.get_instance("model").to(device) + dataloader = config_parser.get_instance("dataloader") + inferer = config_parser.get_instance("inferer") + postprocessing = config_parser.get_instance("postprocessing") + + model.eval() + with torch.no_grad(): + for d in dataloader: + images = d[CommonKeys.IMAGE].to(device) + # define sliding window size and batch size for windows inference + d[CommonKeys.PRED] = inferer(inputs=images, predictor=model) + # decollate the batch data into a list of dictionaries, then execute postprocessing transforms + [postprocessing(i) for i in decollate_batch(d)] + + +if __name__ == '__main__': + main() diff --git a/modules/model_package/spleen_segmentation/scripts/trtinfer.py b/modules/model_package/spleen_segmentation/scripts/trtinfer.py new file mode 100644 index 0000000000..1888e58916 --- /dev/null +++ b/modules/model_package/spleen_segmentation/scripts/trtinfer.py @@ -0,0 +1,59 @@ + +# Copyright 2020 - 2021 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. + +import argparse +import json + +import torch +from monai.apps import ConfigParser +from monai.data import decollate_batch +from monai.transforms import Transform + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--config', '-c', type=str, help='config file that defines components', required=True) + parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') + args = parser.parse_args() + + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + configs = {} + + # load meta data + with open(args.meta, "r") as f: + configs.update(json.load(f)) + # load config file, can override meta data in config + with open(args.config, "r") as f: + configs.update(json.load(f)) + + # fake code to simulate TensorRT and DALI logic + model: TRTModel = None + dataloader: DALIpipeline = None + inferer: TRTInfer = None + postprocessing: Transform = None + # TODO: parse inference config file and construct instances + config_parser = ConfigParser(configs) + + # instantialize the components immediately + model = config_parser.get_instance("model").to(device) + dataloader = config_parser.get_instance("dataloader") + inferer = config_parser.get_instance("inferer") + postprocessing = config_parser.get_instance("postprocessing") + + # simuluate TensorRT and DALI logic + for d in dataloader: + r = inferer(inputs=d, predictor=model) + [postprocessing(i) for i in decollate_batch(r)] + + +if __name__ == '__main__': + main() From fab729f01f24f70610bd235e838a9adba7e84370 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Tue, 18 Jan 2022 08:30:53 +0800 Subject: [PATCH 09/17] [DLMED] add more materials Signed-off-by: Nic Ma --- .../{docs => materials}/README.md | 0 .../{docs => materials}/license.txt | 0 .../spleen_segmentation/materials/mlflow.png | Bin 0 -> 56640 bytes .../materials/tensorboard.png | Bin 0 -> 124898 bytes 4 files changed, 0 insertions(+), 0 deletions(-) rename modules/model_package/spleen_segmentation/{docs => materials}/README.md (100%) rename modules/model_package/spleen_segmentation/{docs => materials}/license.txt (100%) create mode 100644 modules/model_package/spleen_segmentation/materials/mlflow.png create mode 100644 modules/model_package/spleen_segmentation/materials/tensorboard.png diff --git a/modules/model_package/spleen_segmentation/docs/README.md b/modules/model_package/spleen_segmentation/materials/README.md similarity index 100% rename from modules/model_package/spleen_segmentation/docs/README.md rename to modules/model_package/spleen_segmentation/materials/README.md diff --git a/modules/model_package/spleen_segmentation/docs/license.txt b/modules/model_package/spleen_segmentation/materials/license.txt similarity index 100% rename from modules/model_package/spleen_segmentation/docs/license.txt rename to modules/model_package/spleen_segmentation/materials/license.txt diff --git a/modules/model_package/spleen_segmentation/materials/mlflow.png b/modules/model_package/spleen_segmentation/materials/mlflow.png new file mode 100644 index 0000000000000000000000000000000000000000..34d0651e1daff3a5758a4fd5dd3b4cd36531b390 GIT binary patch literal 56640 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 literal 0 HcmV?d00001 diff --git a/modules/model_package/spleen_segmentation/materials/tensorboard.png b/modules/model_package/spleen_segmentation/materials/tensorboard.png new file mode 100644 index 0000000000000000000000000000000000000000..fa3d91e3d2a0f2c80ce405417662954705bf690f GIT binary patch literal 124898 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

V=5#xdw^H|fGg`U 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 Ygkf=8z_Wl}1hlFI?*kMPI zsXg!=|59jS-zAkhc4uE7fp=0V{a=;yEqFw|WSEA&U*6TcB(B%bLu>t^VgP2P!$HEs z&dC2$t6gX4?aQN$!UQV@uBK-ys9~q-9uoAs9Lm;DhL1yY1u9q*XPlm}?p^V05WEI1 zo6`UN>^0um)H!A}3STUqSb6#B{6YOk>$+o5pLR$6z9hc%stk?}ir#L^d1l+=$TAgN zJh8@c6NG2UeP+bnh5vs3yOz81Y;Fu*y3y&B@wmB6Wh*rF(^7-K!mvtE{J^9!Ny3|Y zx-K@_3PS2u)u%$vNzFC&apP8z-nu=ksS0j09jE`F{4rl{C`UoAg7y`YB8L zWRlero8ZN%#ih05q@jN*F1XOWz1%^M7#p0@pCyX&Db*KYkrg(($HQgb5vM+|1Wk)} zv$+U6lH9Pnl%7>YeZwx~G7IeZIq|dSp?v4nUPLmU@;{^rRzBlW@9h0$U$Am!&GA>P z+9G!B6BY9lr;UrW1H*;RNCE9(y8bfvjQU=e9jUIqJwD2D?}ICcmiHvt&=4Lq@o6NU z0>X?%1pinW!MRyiVl?QGlMt)7TM+R@n@X zw;ue?>*Ce!c)Ek1mtH`4#GBv`NVs5;KE33pyWaWxWSl`jJ_>jQ5gtix&0>Tb`pfJQ zXsr@^_e`(pGf&feaV!f*{%?Pc8ZxsbF`A_|DhT`|FQalN=eF^) F{{!l_np*$> literal 0 HcmV?d00001 From fa5dbf0ee9f7fd05ad896a0680fc29f4a70d6261 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Wed, 19 Jan 2022 10:38:04 +0800 Subject: [PATCH 10/17] [DLMED] update according to discussion Signed-off-by: Nic Ma --- .../configs/inference_v2.json | 15 +++++---------- .../{materials => docs}/README.md | 0 .../{materials => docs}/license.txt | 0 .../{materials => docs}/mlflow.png | Bin .../{materials => docs}/tensorboard.png | Bin .../spleen_segmentation/scripts/inference_v2.py | 6 +++++- 6 files changed, 10 insertions(+), 11 deletions(-) rename modules/model_package/spleen_segmentation/{materials => docs}/README.md (100%) rename modules/model_package/spleen_segmentation/{materials => docs}/license.txt (100%) rename modules/model_package/spleen_segmentation/{materials => docs}/mlflow.png (100%) rename modules/model_package/spleen_segmentation/{materials => docs}/tensorboard.png (100%) diff --git a/modules/model_package/spleen_segmentation/configs/inference_v2.json b/modules/model_package/spleen_segmentation/configs/inference_v2.json index 8f2ad18305..eed4e1048b 100644 --- a/modules/model_package/spleen_segmentation/configs/inference_v2.json +++ b/modules/model_package/spleen_segmentation/configs/inference_v2.json @@ -1,15 +1,10 @@ { - "amp": false, - "network": { - "name": "UNet", + "preprocessing": { + "name": "Spacingd", "args": { - "spatial_dims": 3, - "in_channels": 1, - "out_channels": 2, - "channels": [32, 64, 128, 256, 512], - "strides": [2, 2, 2, 2], - "num_res_units": 2, - "norm": "group" + "keys": "image", + "pixdim": [1.0, 1.0, 1.0], + "mode": "bilinear" } }, "inferer": { diff --git a/modules/model_package/spleen_segmentation/materials/README.md b/modules/model_package/spleen_segmentation/docs/README.md similarity index 100% rename from modules/model_package/spleen_segmentation/materials/README.md rename to modules/model_package/spleen_segmentation/docs/README.md diff --git a/modules/model_package/spleen_segmentation/materials/license.txt b/modules/model_package/spleen_segmentation/docs/license.txt similarity index 100% rename from modules/model_package/spleen_segmentation/materials/license.txt rename to modules/model_package/spleen_segmentation/docs/license.txt diff --git a/modules/model_package/spleen_segmentation/materials/mlflow.png b/modules/model_package/spleen_segmentation/docs/mlflow.png similarity index 100% rename from modules/model_package/spleen_segmentation/materials/mlflow.png rename to modules/model_package/spleen_segmentation/docs/mlflow.png diff --git a/modules/model_package/spleen_segmentation/materials/tensorboard.png b/modules/model_package/spleen_segmentation/docs/tensorboard.png similarity index 100% rename from modules/model_package/spleen_segmentation/materials/tensorboard.png rename to modules/model_package/spleen_segmentation/docs/tensorboard.png diff --git a/modules/model_package/spleen_segmentation/scripts/inference_v2.py b/modules/model_package/spleen_segmentation/scripts/inference_v2.py index 2f1b7ea0cd..f6d4533cc5 100644 --- a/modules/model_package/spleen_segmentation/scripts/inference_v2.py +++ b/modules/model_package/spleen_segmentation/scripts/inference_v2.py @@ -39,7 +39,11 @@ def main(): configs.update(json.load(f)) # load config file, add or override the content of base config with open(args.config, "r") as f: - configs.update(json.load(f)) + new_configs = json.load(f) + # override the inferer with other args + configs["inferer"] = new_configs["inferer"] + # override spacing transform with other pixdims + configs["preprocessing"][1] = new_configs["preprocessing"] model: torch.nn.Module = None dataloader: torch.utils.data.DataLoader = None From 918a4bde65cec8af4332c3a65515a88d681cb295 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Tue, 25 Jan 2022 18:25:42 +0800 Subject: [PATCH 11/17] [DLMED] update according to Eric's suggestion Signed-off-by: Nic Ma --- .../configs/inference.json | 10 ++--- .../spleen_segmentation/configs/metadata.json | 37 +++++++++++++++++-- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/modules/model_package/spleen_segmentation/configs/inference.json b/modules/model_package/spleen_segmentation/configs/inference.json index db831a3c85..23eaeb4dd1 100644 --- a/modules/model_package/spleen_segmentation/configs/inference.json +++ b/modules/model_package/spleen_segmentation/configs/inference.json @@ -1,13 +1,13 @@ { "multi_gpu": false, "amp": true, - "model": "#monai.data.load_net_with_metadata('../models/model.ts')[0]", + "model": "$monai.data.load_net_with_metadata('../models/model.ts')[0]", "network": { "name": "UNet", "args": { "spatial_dims": 3, - "in_channels": 1, - "out_channels": 2, + "in_channels": "@network_data_format#inputs#image#num_channels", + "out_channels": "@network_data_format#outputs#pred#num_channels", "channels": [16, 32, 64, 128, 256], "strides": [2, 2, 2, 2], "num_res_units": 2, @@ -70,7 +70,7 @@ "datalist": { "name": "DatasetFunc", "args": { - "data": "#@dataset_dir + '/dataset.json'", + "data": "$@dataset_dir + '/dataset.json'", "func": "monai.data.load_decathlon_datalist", "is_segmentation": true, "data_list_key": "test", @@ -96,7 +96,7 @@ "inferer": { "name": "SlidingWindowInferer", "args": { - "roi_size": [160, 160, 160], + "roi_size": "@network_data_format#inputs#image#spatial_shape", "sw_batch_size": 4, "overlap": 0.5 } diff --git a/modules/model_package/spleen_segmentation/configs/metadata.json b/modules/model_package/spleen_segmentation/configs/metadata.json index 108e07b395..082f60c480 100644 --- a/modules/model_package/spleen_segmentation/configs/metadata.json +++ b/modules/model_package/spleen_segmentation/configs/metadata.json @@ -11,14 +11,12 @@ "task": "Decathlon spleen segmentation", "description": "A pre-trained model for volumetric (3D) segmentation of the spleen from CT image", "authorship": "MONAI team", + "copyright": "Copyright (c) MONAI Consortium", "data_source": "Task09_Spleen.tar from http://medicaldecathlon.com/", "dataset_dir": "/workspace/data/Task09_Spleen", "image_classes": "single channel data, intensity scaled to [0, 1]", "label_classes": "single channel data, 1 is spleen, 0 is everything else", "pred_classes": "2 channels OneHot data, channel 1 is spleen, channel 0 is background", - "image_shape": [1, 160, 160, 160], - "label_shape": [1, 160, 160, 160], - "pred_shape": [2, 160, 160, 160], "eval_metrics": { "mean_dice": 0.96 }, @@ -26,5 +24,36 @@ "references": [ "Xia, Yingda, et al. '3D Semi-Supervised Learning with Uncertainty-Aware Multi-View Co-Training.' arXiv preprint arXiv:1811.12506 (2018). https://arxiv.org/abs/1811.12506.", "Kerfoot E., Clough J., Oksuz I., Lee J., King A.P., Schnabel J.A. (2019) Left-Ventricle Quantification Using Residual U-Net. In: Pop M. et al. (eds) Statistical Atlases and Computational Models of the Heart. Atrial Segmentation and LV Quantification Challenges. STACOM 2018. Lecture Notes in Computer Science, vol 11395. Springer, Cham. https://doi.org/10.1007/978-3-030-12029-0_40" - ] + ], + "network_data_format":{ + "inputs": { + "image": { + "type": "image", + "format": "magnitude", + "num_channels": 1, + "spatial_shape": [160, 160, 160], + "dtype": "float32", + "value_range": [0, 1] + }, + "label": { + "type": "label", + "format": "segmentation", + "num_channels": 1, + "spatial_shape": [160, 160, 160], + "dtype": "float32", + "value_range": [0, 1] + } + }, + "outputs":{ + "pred": { + "type": "image", + "format": "segmentation", + "num_channels": 2, + "spatial_shape": [160, 160, 160], + "dtype": "float32", + "value_range": [0, 1] + } + }, + "patch_inference": false + } } From c38560540cca23220fd4e3b4069afa66903983b7 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Tue, 25 Jan 2022 20:28:43 +0800 Subject: [PATCH 12/17] [DLMED] add config schema example Signed-off-by: Nic Ma --- .../commands/schema_check.sh | 1 + .../spleen_segmentation/schema/metadata.json | 71 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 modules/model_package/spleen_segmentation/commands/schema_check.sh create mode 100644 modules/model_package/spleen_segmentation/schema/metadata.json diff --git a/modules/model_package/spleen_segmentation/commands/schema_check.sh b/modules/model_package/spleen_segmentation/commands/schema_check.sh new file mode 100644 index 0000000000..1ed9703f3a --- /dev/null +++ b/modules/model_package/spleen_segmentation/commands/schema_check.sh @@ -0,0 +1 @@ +jsonschema --instance ../configs/metadata.json ../schema/metadata.json diff --git a/modules/model_package/spleen_segmentation/schema/metadata.json b/modules/model_package/spleen_segmentation/schema/metadata.json new file mode 100644 index 0000000000..babee8b30e --- /dev/null +++ b/modules/model_package/spleen_segmentation/schema/metadata.json @@ -0,0 +1,71 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://monai.io/mmar_metadata_schema.json", + "title": "metadata", + "description": "metadata that defines the context information for MMAR.", + "type": "object", + "properties": { + "version": { + "description": "version number of this MMAR.", + "type": "string" + }, + "monai_version": { + "description": "version number of MONAI used in this MMAR.", + "type": "string" + }, + "pytorch_version": { + "description": "version number of PyTorch used in this MMAR.", + "type": "string" + }, + "numpy_version": { + "description": "version number of MONAI used in this MMAR.", + "type": "string" + }, + "network_data_format": { + "description": "define the input and output data format for network.", + "type": "object", + "properties": { + "inputs": { + "type": "object", + "properties": { + "image": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "the data format for `image`." + }, + "format": { + "type": "string" + }, + "num_channels": { + "type": "integer", + "minimum": 1 + }, + "spatial_shape": { + "type": "array", + "items": { + "type": "integer", + "minumum": 1 + } + }, + "dtype": { + "type": "string" + }, + "value_range": { + "type": "array", + "items": { + "type": "number", + "unuqueItems": true + } + }, + "required": ["num_channels", "spatial_shape", "value_range"] + } + } + } + } + } + }, + "required": ["monai_version", "pytorch_version", "network_data_format"] + } +} From 826192e99d11ecd05274c029d0ba8d269d475a06 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Tue, 25 Jan 2022 20:48:45 +0800 Subject: [PATCH 13/17] [DLMED] network verification example Signed-off-by: Nic Ma --- .../commands/verify_network.sh | 3 + .../scripts/verify_network.py | 61 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 modules/model_package/spleen_segmentation/commands/verify_network.sh create mode 100644 modules/model_package/spleen_segmentation/scripts/verify_network.py diff --git a/modules/model_package/spleen_segmentation/commands/verify_network.sh b/modules/model_package/spleen_segmentation/commands/verify_network.sh new file mode 100644 index 0000000000..8d8cbb967d --- /dev/null +++ b/modules/model_package/spleen_segmentation/commands/verify_network.sh @@ -0,0 +1,3 @@ +python ../scripts/verify_network.py + --config ../configs/inference.json + --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/scripts/verify_network.py b/modules/model_package/spleen_segmentation/scripts/verify_network.py new file mode 100644 index 0000000000..1fe0b76b6c --- /dev/null +++ b/modules/model_package/spleen_segmentation/scripts/verify_network.py @@ -0,0 +1,61 @@ + +# Copyright 2020 - 2021 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. + +import argparse +import json + +import torch +from monai.apps import ConfigParser +from monai.utils.type_conversion import get_equivalent_dtype + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--config', '-c', type=str, help='config file that defines components', required=True) + parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') + args = parser.parse_args() + + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + configs = {} + + # load meta data + with open(args.meta, "r") as f: + configs.update(json.load(f)) + # load config file, can override meta data in config + with open(args.config, "r") as f: + configs.update(json.load(f)) + + model: torch.nn.Module = None + # TODO: parse inference config file and construct instances + config_parser = ConfigParser(configs) + + model = config_parser.get_instance("model") + input_channels = config_parser.get_config("network_data_format#inputs#image#num_channels") + input_spatial_shape = tuple(config_parser.get_config("network_data_format#inputs#image#spatial_shape")) + dtype = config_parser.get_config("network_data_format#inputs#image#dtype") + dtype = get_equivalent_dtype(dtype, data_type=torch.Tensor) + + output_channels = config_parser.get_config("network_data_format#outputs#pred#num_channels") + output_spatial_shape = tuple(config_parser.get_config("network_data_format#outputs#pred#spatial_shape")) + + model.eval() + with torch.no_grad(): + test_data = torch.rand(*(input_channels, *input_spatial_shape), dtype=dtype, device=device) + output = model(test_data) + if output.shape[0] != output_channels: + raise ValueError(f"channel number of output data doesn't match expection: {output_channels}.") + if output.shape[1:] != output_spatial_shape: + raise ValueError(f"spatial shape of output data doesn't match expection: {output_spatial_shape}.") + + +if __name__ == '__main__': + main() From 0890d38cc78f8e8c1d55e683cf0771cd0186d33f Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Tue, 25 Jan 2022 20:55:28 +0800 Subject: [PATCH 14/17] [DLMED] change the "override" example to a separate MMAR example Signed-off-by: Nic Ma --- .../spleen_segmentation/commands/inference_v2.sh | 4 ---- .../spleen_segmentation_v2/commands/inference.sh | 4 ++++ .../configs/inference.json} | 0 .../spleen_segmentation_v2/scripts/__init__.py | 11 +++++++++++ .../scripts/inference.py} | 0 5 files changed, 15 insertions(+), 4 deletions(-) delete mode 100644 modules/model_package/spleen_segmentation/commands/inference_v2.sh create mode 100644 modules/model_package/spleen_segmentation_v2/commands/inference.sh rename modules/model_package/{spleen_segmentation/configs/inference_v2.json => spleen_segmentation_v2/configs/inference.json} (100%) create mode 100644 modules/model_package/spleen_segmentation_v2/scripts/__init__.py rename modules/model_package/{spleen_segmentation/scripts/inference_v2.py => spleen_segmentation_v2/scripts/inference.py} (100%) diff --git a/modules/model_package/spleen_segmentation/commands/inference_v2.sh b/modules/model_package/spleen_segmentation/commands/inference_v2.sh deleted file mode 100644 index 572b223dcf..0000000000 --- a/modules/model_package/spleen_segmentation/commands/inference_v2.sh +++ /dev/null @@ -1,4 +0,0 @@ -python ../scripts/inference.py - --base_config ../configs/inference.json - --config ../configs/inference_v2.json - --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation_v2/commands/inference.sh b/modules/model_package/spleen_segmentation_v2/commands/inference.sh new file mode 100644 index 0000000000..087d951cbc --- /dev/null +++ b/modules/model_package/spleen_segmentation_v2/commands/inference.sh @@ -0,0 +1,4 @@ +python ../scripts/inference.py + --base_config ../../spleen_segmentation/configs/inference.json + --config ../configs/inference.json + --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/configs/inference_v2.json b/modules/model_package/spleen_segmentation_v2/configs/inference.json similarity index 100% rename from modules/model_package/spleen_segmentation/configs/inference_v2.json rename to modules/model_package/spleen_segmentation_v2/configs/inference.json diff --git a/modules/model_package/spleen_segmentation_v2/scripts/__init__.py b/modules/model_package/spleen_segmentation_v2/scripts/__init__.py new file mode 100644 index 0000000000..7e5ba0883c --- /dev/null +++ b/modules/model_package/spleen_segmentation_v2/scripts/__init__.py @@ -0,0 +1,11 @@ + +# Copyright 2020 - 2021 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. diff --git a/modules/model_package/spleen_segmentation/scripts/inference_v2.py b/modules/model_package/spleen_segmentation_v2/scripts/inference.py similarity index 100% rename from modules/model_package/spleen_segmentation/scripts/inference_v2.py rename to modules/model_package/spleen_segmentation_v2/scripts/inference.py From 1ccb783971ce7f2d81b5124bb132798f401871b5 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 27 Jan 2022 16:06:57 +0800 Subject: [PATCH 15/17] [DLMED] update according to comments Signed-off-by: Nic Ma --- .../spleen_segmentation/commands/export.sh | 2 +- .../spleen_segmentation/commands/inference.sh | 2 +- .../commands/schema_check.sh | 4 +- .../spleen_segmentation/commands/trtinfer.sh | 3 - .../commands/verify_network.sh | 2 +- .../configs/inference.json | 86 ++++++++++++------- .../spleen_segmentation/configs/trtinfer.json | 19 ---- .../spleen_segmentation/schema/metadata.json | 71 --------------- .../spleen_segmentation/scripts/__init__.py | 11 --- .../spleen_segmentation/scripts/export.py | 60 ------------- .../spleen_segmentation/scripts/inference.py | 68 --------------- .../spleen_segmentation/scripts/trtinfer.py | 59 ------------- .../scripts/verify_network.py | 61 ------------- .../commands/inference.sh | 6 +- .../configs/inference.json | 20 ++--- 15 files changed, 67 insertions(+), 407 deletions(-) delete mode 100644 modules/model_package/spleen_segmentation/commands/trtinfer.sh delete mode 100644 modules/model_package/spleen_segmentation/configs/trtinfer.json delete mode 100644 modules/model_package/spleen_segmentation/schema/metadata.json delete mode 100644 modules/model_package/spleen_segmentation/scripts/__init__.py delete mode 100644 modules/model_package/spleen_segmentation/scripts/export.py delete mode 100644 modules/model_package/spleen_segmentation/scripts/inference.py delete mode 100644 modules/model_package/spleen_segmentation/scripts/trtinfer.py delete mode 100644 modules/model_package/spleen_segmentation/scripts/verify_network.py diff --git a/modules/model_package/spleen_segmentation/commands/export.sh b/modules/model_package/spleen_segmentation/commands/export.sh index 1f70efddf7..f3ae1f3aa2 100644 --- a/modules/model_package/spleen_segmentation/commands/export.sh +++ b/modules/model_package/spleen_segmentation/commands/export.sh @@ -1,4 +1,4 @@ -python ../scripts/export.py +python -m monai.apps.mmar.export --weights ../models/model.pt --config ../configs/inference.json --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/commands/inference.sh b/modules/model_package/spleen_segmentation/commands/inference.sh index 93c0590bbb..e5c121470a 100644 --- a/modules/model_package/spleen_segmentation/commands/inference.sh +++ b/modules/model_package/spleen_segmentation/commands/inference.sh @@ -1,3 +1,3 @@ -python ../scripts/inference.py +python -m monai.apps.mmar.inference.py --config ../configs/inference.json --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/commands/schema_check.sh b/modules/model_package/spleen_segmentation/commands/schema_check.sh index 1ed9703f3a..3d947d3e64 100644 --- a/modules/model_package/spleen_segmentation/commands/schema_check.sh +++ b/modules/model_package/spleen_segmentation/commands/schema_check.sh @@ -1 +1,3 @@ -jsonschema --instance ../configs/metadata.json ../schema/metadata.json +python -m monai.apps.mmar.verify_json.py + --schema_id metadata + --config ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/commands/trtinfer.sh b/modules/model_package/spleen_segmentation/commands/trtinfer.sh deleted file mode 100644 index 1df47fbcc1..0000000000 --- a/modules/model_package/spleen_segmentation/commands/trtinfer.sh +++ /dev/null @@ -1,3 +0,0 @@ -python ../scripts/inference.py - --config ../configs/trtinfer.json - --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/commands/verify_network.sh b/modules/model_package/spleen_segmentation/commands/verify_network.sh index 8d8cbb967d..a138a47747 100644 --- a/modules/model_package/spleen_segmentation/commands/verify_network.sh +++ b/modules/model_package/spleen_segmentation/commands/verify_network.sh @@ -1,3 +1,3 @@ -python ../scripts/verify_network.py +python -m monai.apps.mmar.verify_network.py --config ../configs/inference.json --meta ../configs/metadata.json diff --git a/modules/model_package/spleen_segmentation/configs/inference.json b/modules/model_package/spleen_segmentation/configs/inference.json index 23eaeb4dd1..8a317f9c40 100644 --- a/modules/model_package/spleen_segmentation/configs/inference.json +++ b/modules/model_package/spleen_segmentation/configs/inference.json @@ -3,8 +3,8 @@ "amp": true, "model": "$monai.data.load_net_with_metadata('../models/model.ts')[0]", "network": { - "name": "UNet", - "args": { + "": "UNet", + "": { "spatial_dims": 3, "in_channels": "@network_data_format#inputs#image#num_channels", "out_channels": "@network_data_format#outputs#pred#num_channels", @@ -16,35 +16,35 @@ }, "preprocessing": [ { - "name": "LoadImaged", - "args": { + "": "LoadImaged", + "": { "keys": "image" } }, { - "name": "Spacingd", - "args": { + "": "Spacingd", + "": { "keys": "image", "pixdim": [1.5, 1.5, 2], "mode": "bilinear" } }, { - "name": "Orientationd", - "args": { + "": "Orientationd", + "": { "keys": "image", "axcodes": "RAS" } }, { - "name": "EnsureChannelFirstd", - "args": { + "": "EnsureChannelFirstd", + "": { "keys": "image" } }, { - "name": "ScaleIntensityRanged", - "args": { + "": "ScaleIntensityRanged", + "": { "keys": "image", "a_min": -57, "a_max": 164, @@ -54,22 +54,22 @@ } }, { - "name": "CropForegroundd", - "args": { + "": "CropForegroundd", + "": { "keys": "image", "source_key": "image" } }, { - "name": "ToTensord", - "args": { + "": "ToTensord", + "": { "keys": "image" } } ], "datalist": { - "name": "DatasetFunc", - "args": { + "": "DatasetFunc", + "": { "data": "$@dataset_dir + '/dataset.json'", "func": "monai.data.load_decathlon_datalist", "is_segmentation": true, @@ -78,15 +78,15 @@ } }, "dataset": { - "name": "Dataset", - "args": { + "": "Dataset", + "": { "data": "@datalist", "transform": "@preprocessing" } }, "dataloader": { - "name": "DataLoader", - "args": { + "": "DataLoader", + "": { "dataset": "@dataset", "batch_size": 1, "shuffle": false, @@ -94,8 +94,8 @@ } }, "inferer": { - "name": "SlidingWindowInferer", - "args": { + "": "SlidingWindowInferer", + "": { "roi_size": "@network_data_format#inputs#image#spatial_shape", "sw_batch_size": 4, "overlap": 0.5 @@ -103,15 +103,15 @@ }, "postprocessing": [ { - "name": "Activationsd", - "args": { + "": "Activationsd", + "": { "keys": "pred", "softmax": true } }, { - "name": "Invertd", - "args": { + "": "Invertd", + "": { "keys": "pred", "transform": "@preprocessing", "orig_keys": "image", @@ -122,15 +122,15 @@ } }, { - "name": "AsDiscreted", - "args": { + "": "AsDiscreted", + "": { "keys": "pred", "argmax": true } }, { - "name": "SaveImaged", - "args": { + "": "SaveImaged", + "": { "keys": "pred", "meta_keys": "pred_meta_dict", "output_dir": "{MMAR_EVAL_OUTPUT_PATH}", @@ -138,5 +138,25 @@ "squeeze_end_dims": true } } - ] + ], + "handlers": [ + { + "": "StatsHandler", + "": { + "output_transform": "lambda x: None" + } + } + ], + "evaluator": { + "": "SupervisedEvaluator", + "": { + "device": "cuda", + "val_data_loader": "@dataloader", + "network": "@model", + "inferer": "@inferer", + "postprocessing": "@postprocessing", + "val_handlers": "@handlers", + "amp": "@amp" + } + } } diff --git a/modules/model_package/spleen_segmentation/configs/trtinfer.json b/modules/model_package/spleen_segmentation/configs/trtinfer.json deleted file mode 100644 index 435b742be2..0000000000 --- a/modules/model_package/spleen_segmentation/configs/trtinfer.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "preprocessing": { - "ref": { - "path": "../inference.json/preprocessing" - } - }, - "dataset": { - "ref": { - "path": "../inference.json/dataset" - } - }, - "model": "#load_trt_model(...)", - "dataloader": { - "name": "DALIpipeline" - }, - "inferer": { - "name": "TensorRTInferer" - } -} diff --git a/modules/model_package/spleen_segmentation/schema/metadata.json b/modules/model_package/spleen_segmentation/schema/metadata.json deleted file mode 100644 index babee8b30e..0000000000 --- a/modules/model_package/spleen_segmentation/schema/metadata.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://monai.io/mmar_metadata_schema.json", - "title": "metadata", - "description": "metadata that defines the context information for MMAR.", - "type": "object", - "properties": { - "version": { - "description": "version number of this MMAR.", - "type": "string" - }, - "monai_version": { - "description": "version number of MONAI used in this MMAR.", - "type": "string" - }, - "pytorch_version": { - "description": "version number of PyTorch used in this MMAR.", - "type": "string" - }, - "numpy_version": { - "description": "version number of MONAI used in this MMAR.", - "type": "string" - }, - "network_data_format": { - "description": "define the input and output data format for network.", - "type": "object", - "properties": { - "inputs": { - "type": "object", - "properties": { - "image": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "the data format for `image`." - }, - "format": { - "type": "string" - }, - "num_channels": { - "type": "integer", - "minimum": 1 - }, - "spatial_shape": { - "type": "array", - "items": { - "type": "integer", - "minumum": 1 - } - }, - "dtype": { - "type": "string" - }, - "value_range": { - "type": "array", - "items": { - "type": "number", - "unuqueItems": true - } - }, - "required": ["num_channels", "spatial_shape", "value_range"] - } - } - } - } - } - }, - "required": ["monai_version", "pytorch_version", "network_data_format"] - } -} diff --git a/modules/model_package/spleen_segmentation/scripts/__init__.py b/modules/model_package/spleen_segmentation/scripts/__init__.py deleted file mode 100644 index 7e5ba0883c..0000000000 --- a/modules/model_package/spleen_segmentation/scripts/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ - -# Copyright 2020 - 2021 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. diff --git a/modules/model_package/spleen_segmentation/scripts/export.py b/modules/model_package/spleen_segmentation/scripts/export.py deleted file mode 100644 index 22f76f90b8..0000000000 --- a/modules/model_package/spleen_segmentation/scripts/export.py +++ /dev/null @@ -1,60 +0,0 @@ - -# Copyright 2020 - 2021 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. - -import argparse -import json - -import torch -from monai.apps import ConfigParser -from ignite.handlers import Checkpoint -from monai.data import save_net_with_metadata -from monai.networks import convert_to_torchscript - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--weights', '-w', type=str, help='file path of the trained model weights', required=True) - parser.add_argument('--config', '-c', type=str, help='file path of config file that defines network', required=True) - parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') - args = parser.parse_args() - - # load config file - with open(args.config, "r") as f: - config_dict = json.load(f) - # load meta data - with open(args.meta, "r") as f: - meta_dict = json.load(f) - - net: torch.nn.Module = None - # TODO: parse network definiftion from config file and construct network instance - config_parser = ConfigParser(config_dict) - net = config_parser.get_instance("network") - - checkpoint = torch.load(args.weights) - # here we use ignite Checkpoint to support nested weights and be compatible with MONAI CheckpointSaver - Checkpoint.load_objects(to_load={"model": net}, checkpoint=checkpoint) - - # convert to TorchScript model and save with meta data - net = convert_to_torchscript(model=net) - - save_net_with_metadata( - jit_obj=net, - filename_prefix_or_stream="model.ts", - include_config_vals=False, - append_timestamp=False, - meta_values=meta_dict, - more_extra_files={args.config: json.dumps(config_dict).encode()}, - ) - - -if __name__ == '__main__': - main() diff --git a/modules/model_package/spleen_segmentation/scripts/inference.py b/modules/model_package/spleen_segmentation/scripts/inference.py deleted file mode 100644 index 9f667f9c4b..0000000000 --- a/modules/model_package/spleen_segmentation/scripts/inference.py +++ /dev/null @@ -1,68 +0,0 @@ - -# Copyright 2020 - 2021 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. - -import argparse -import json - -import torch -from monai.apps import ConfigParser -from monai.data import decollate_batch -from monai.inferers import Inferer -from monai.transforms import Transform -from monai.utils.enums import CommonKeys - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--config', '-c', type=str, help='config file that defines components', required=True) - parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') - args = parser.parse_args() - - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - configs = {} - - # load meta data - with open(args.meta, "r") as f: - configs.update(json.load(f)) - # load config file, can override meta data in config - with open(args.config, "r") as f: - configs.update(json.load(f)) - - model: torch.nn.Module = None - dataloader: torch.utils.data.DataLoader = None - inferer: Inferer = None - postprocessing: Transform = None - # TODO: parse inference config file and construct instances - config_parser = ConfigParser(configs) - - # change JSON config content in python code, lazy instantiation - model_conf = config_parser.get_config("model") - model_conf["disabled"] = False - model = config_parser.build(model_conf).to(device) - - # instantialize the components immediately - dataloader = config_parser.get_instance("dataloader") - inferer = config_parser.get_instance("inferer") - postprocessing = config_parser.get_instance("postprocessing") - - model.eval() - with torch.no_grad(): - for d in dataloader: - images = d[CommonKeys.IMAGE].to(device) - # define sliding window size and batch size for windows inference - d[CommonKeys.PRED] = inferer(inputs=images, predictor=model) - # decollate the batch data into a list of dictionaries, then execute postprocessing transforms - [postprocessing(i) for i in decollate_batch(d)] - - -if __name__ == '__main__': - main() diff --git a/modules/model_package/spleen_segmentation/scripts/trtinfer.py b/modules/model_package/spleen_segmentation/scripts/trtinfer.py deleted file mode 100644 index 1888e58916..0000000000 --- a/modules/model_package/spleen_segmentation/scripts/trtinfer.py +++ /dev/null @@ -1,59 +0,0 @@ - -# Copyright 2020 - 2021 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. - -import argparse -import json - -import torch -from monai.apps import ConfigParser -from monai.data import decollate_batch -from monai.transforms import Transform - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--config', '-c', type=str, help='config file that defines components', required=True) - parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') - args = parser.parse_args() - - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - configs = {} - - # load meta data - with open(args.meta, "r") as f: - configs.update(json.load(f)) - # load config file, can override meta data in config - with open(args.config, "r") as f: - configs.update(json.load(f)) - - # fake code to simulate TensorRT and DALI logic - model: TRTModel = None - dataloader: DALIpipeline = None - inferer: TRTInfer = None - postprocessing: Transform = None - # TODO: parse inference config file and construct instances - config_parser = ConfigParser(configs) - - # instantialize the components immediately - model = config_parser.get_instance("model").to(device) - dataloader = config_parser.get_instance("dataloader") - inferer = config_parser.get_instance("inferer") - postprocessing = config_parser.get_instance("postprocessing") - - # simuluate TensorRT and DALI logic - for d in dataloader: - r = inferer(inputs=d, predictor=model) - [postprocessing(i) for i in decollate_batch(r)] - - -if __name__ == '__main__': - main() diff --git a/modules/model_package/spleen_segmentation/scripts/verify_network.py b/modules/model_package/spleen_segmentation/scripts/verify_network.py deleted file mode 100644 index 1fe0b76b6c..0000000000 --- a/modules/model_package/spleen_segmentation/scripts/verify_network.py +++ /dev/null @@ -1,61 +0,0 @@ - -# Copyright 2020 - 2021 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. - -import argparse -import json - -import torch -from monai.apps import ConfigParser -from monai.utils.type_conversion import get_equivalent_dtype - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--config', '-c', type=str, help='config file that defines components', required=True) - parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') - args = parser.parse_args() - - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - configs = {} - - # load meta data - with open(args.meta, "r") as f: - configs.update(json.load(f)) - # load config file, can override meta data in config - with open(args.config, "r") as f: - configs.update(json.load(f)) - - model: torch.nn.Module = None - # TODO: parse inference config file and construct instances - config_parser = ConfigParser(configs) - - model = config_parser.get_instance("model") - input_channels = config_parser.get_config("network_data_format#inputs#image#num_channels") - input_spatial_shape = tuple(config_parser.get_config("network_data_format#inputs#image#spatial_shape")) - dtype = config_parser.get_config("network_data_format#inputs#image#dtype") - dtype = get_equivalent_dtype(dtype, data_type=torch.Tensor) - - output_channels = config_parser.get_config("network_data_format#outputs#pred#num_channels") - output_spatial_shape = tuple(config_parser.get_config("network_data_format#outputs#pred#spatial_shape")) - - model.eval() - with torch.no_grad(): - test_data = torch.rand(*(input_channels, *input_spatial_shape), dtype=dtype, device=device) - output = model(test_data) - if output.shape[0] != output_channels: - raise ValueError(f"channel number of output data doesn't match expection: {output_channels}.") - if output.shape[1:] != output_spatial_shape: - raise ValueError(f"spatial shape of output data doesn't match expection: {output_spatial_shape}.") - - -if __name__ == '__main__': - main() diff --git a/modules/model_package/spleen_segmentation_v2/commands/inference.sh b/modules/model_package/spleen_segmentation_v2/commands/inference.sh index 087d951cbc..87ffe42350 100644 --- a/modules/model_package/spleen_segmentation_v2/commands/inference.sh +++ b/modules/model_package/spleen_segmentation_v2/commands/inference.sh @@ -1,4 +1,4 @@ -python ../scripts/inference.py - --base_config ../../spleen_segmentation/configs/inference.json - --config ../configs/inference.json +python -m monai.apps.mmar.inference.py + --config ../../spleen_segmentation/configs/inference.json --meta ../configs/metadata.json + --override ../configs/inference.json diff --git a/modules/model_package/spleen_segmentation_v2/configs/inference.json b/modules/model_package/spleen_segmentation_v2/configs/inference.json index eed4e1048b..94011f775c 100644 --- a/modules/model_package/spleen_segmentation_v2/configs/inference.json +++ b/modules/model_package/spleen_segmentation_v2/configs/inference.json @@ -1,18 +1,8 @@ { - "preprocessing": { - "name": "Spacingd", - "args": { - "keys": "image", - "pixdim": [1.0, 1.0, 1.0], - "mode": "bilinear" - } - }, - "inferer": { - "name": "SlidingWindowInferer", - "args": { - "roi_size": [96, 96, 96], - "sw_batch_size": 4, - "overlap": 0.6 - } + "preprocessing#1##pixdim": [1.0, 1.0, 1.0], + "inferer#": { + "roi_size": [96, 96, 96], + "sw_batch_size": 4, + "overlap": 0.6 } } From 0171768a36110e2f2abd5694821d4c39a068ef79 Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 27 Jan 2022 17:19:46 +0800 Subject: [PATCH 16/17] [DLMED] refine override example Signed-off-by: Nic Ma --- .../commands/inference.sh | 0 .../configs/inference.json | 11 +++ .../scripts/__init__.py | 0 .../scripts/custom_inferer.py | 19 +++++ .../configs/inference.json | 8 --- .../scripts/inference.py | 71 ------------------- 6 files changed, 30 insertions(+), 79 deletions(-) rename modules/model_package/{spleen_segmentation_v2 => spleen_segmentation_a100}/commands/inference.sh (100%) create mode 100644 modules/model_package/spleen_segmentation_a100/configs/inference.json rename modules/model_package/{spleen_segmentation_v2 => spleen_segmentation_a100}/scripts/__init__.py (100%) create mode 100644 modules/model_package/spleen_segmentation_a100/scripts/custom_inferer.py delete mode 100644 modules/model_package/spleen_segmentation_v2/configs/inference.json delete mode 100644 modules/model_package/spleen_segmentation_v2/scripts/inference.py diff --git a/modules/model_package/spleen_segmentation_v2/commands/inference.sh b/modules/model_package/spleen_segmentation_a100/commands/inference.sh similarity index 100% rename from modules/model_package/spleen_segmentation_v2/commands/inference.sh rename to modules/model_package/spleen_segmentation_a100/commands/inference.sh diff --git a/modules/model_package/spleen_segmentation_a100/configs/inference.json b/modules/model_package/spleen_segmentation_a100/configs/inference.json new file mode 100644 index 0000000000..4f6ebe81df --- /dev/null +++ b/modules/model_package/spleen_segmentation_a100/configs/inference.json @@ -0,0 +1,11 @@ +{ + "preprocessing#1##pixdim": [1.0, 1.0, 1.0], + "inferer": { + "": "custom_inferer.TensorRTInferer", + "": { + "roi_size": [200, 200, 200], + "sw_batch_size": 4, + "overlap": 0.6 + } + } +} diff --git a/modules/model_package/spleen_segmentation_v2/scripts/__init__.py b/modules/model_package/spleen_segmentation_a100/scripts/__init__.py similarity index 100% rename from modules/model_package/spleen_segmentation_v2/scripts/__init__.py rename to modules/model_package/spleen_segmentation_a100/scripts/__init__.py diff --git a/modules/model_package/spleen_segmentation_a100/scripts/custom_inferer.py b/modules/model_package/spleen_segmentation_a100/scripts/custom_inferer.py new file mode 100644 index 0000000000..c201dfb66c --- /dev/null +++ b/modules/model_package/spleen_segmentation_a100/scripts/custom_inferer.py @@ -0,0 +1,19 @@ + +# Copyright 2020 - 2021 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.inferers import SlidingWindowInferer + + +class TensorRTInferer(SlidingWindowInferer): + def __init__(self, **kwargs) -> None: + print("fake code to show the customize logic.") + super().__init__(**kwargs) diff --git a/modules/model_package/spleen_segmentation_v2/configs/inference.json b/modules/model_package/spleen_segmentation_v2/configs/inference.json deleted file mode 100644 index 94011f775c..0000000000 --- a/modules/model_package/spleen_segmentation_v2/configs/inference.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "preprocessing#1##pixdim": [1.0, 1.0, 1.0], - "inferer#": { - "roi_size": [96, 96, 96], - "sw_batch_size": 4, - "overlap": 0.6 - } -} diff --git a/modules/model_package/spleen_segmentation_v2/scripts/inference.py b/modules/model_package/spleen_segmentation_v2/scripts/inference.py deleted file mode 100644 index f6d4533cc5..0000000000 --- a/modules/model_package/spleen_segmentation_v2/scripts/inference.py +++ /dev/null @@ -1,71 +0,0 @@ - -# Copyright 2020 - 2021 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. - -import argparse -import json - -import torch -from monai.apps import ConfigParser -from monai.data import decollate_batch -from monai.inferers import Inferer -from monai.transforms import Transform -from monai.utils.enums import CommonKeys - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--base_config', '-c', type=str, help='file path of base config', required=False) - parser.add_argument('--config', '-c', type=str, help='config file to override base config', required=True) - parser.add_argument('--meta', '-e', type=str, help='file path of the meta data') - args = parser.parse_args() - - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - configs = {} - - # load meta data - with open(args.meta, "r") as f: - configs.update(json.load(f)) - # load base config file, can override meta data in config - with open(args.base_config, "r") as f: - configs.update(json.load(f)) - # load config file, add or override the content of base config - with open(args.config, "r") as f: - new_configs = json.load(f) - # override the inferer with other args - configs["inferer"] = new_configs["inferer"] - # override spacing transform with other pixdims - configs["preprocessing"][1] = new_configs["preprocessing"] - - model: torch.nn.Module = None - dataloader: torch.utils.data.DataLoader = None - inferer: Inferer = None - postprocessing: Transform = None - # TODO: parse inference config file and construct instances - config_parser = ConfigParser(configs) - # instantialize the components immediately - model = config_parser.get_instance("model").to(device) - dataloader = config_parser.get_instance("dataloader") - inferer = config_parser.get_instance("inferer") - postprocessing = config_parser.get_instance("postprocessing") - - model.eval() - with torch.no_grad(): - for d in dataloader: - images = d[CommonKeys.IMAGE].to(device) - # define sliding window size and batch size for windows inference - d[CommonKeys.PRED] = inferer(inputs=images, predictor=model) - # decollate the batch data into a list of dictionaries, then execute postprocessing transforms - [postprocessing(i) for i in decollate_batch(d)] - - -if __name__ == '__main__': - main() From c5dc8be0859ebe2763a4c896ae4ca78c72d6c77d Mon Sep 17 00:00:00 2001 From: Nic Ma Date: Thu, 27 Jan 2022 17:49:19 +0800 Subject: [PATCH 17/17] [DLMED] add image data type Signed-off-by: Nic Ma --- modules/model_package/spleen_segmentation/configs/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/model_package/spleen_segmentation/configs/metadata.json b/modules/model_package/spleen_segmentation/configs/metadata.json index 082f60c480..6e0e4c2ead 100644 --- a/modules/model_package/spleen_segmentation/configs/metadata.json +++ b/modules/model_package/spleen_segmentation/configs/metadata.json @@ -13,6 +13,7 @@ "authorship": "MONAI team", "copyright": "Copyright (c) MONAI Consortium", "data_source": "Task09_Spleen.tar from http://medicaldecathlon.com/", + "data_type": "dicom", "dataset_dir": "/workspace/data/Task09_Spleen", "image_classes": "single channel data, intensity scaled to [0, 1]", "label_classes": "single channel data, 1 is spleen, 0 is everything else",