diff --git a/models/swin_unetr_btcv_segmentation/configs/metadata.json b/models/swin_unetr_btcv_segmentation/configs/metadata.json index 58a14933..1de4e9be 100644 --- a/models/swin_unetr_btcv_segmentation/configs/metadata.json +++ b/models/swin_unetr_btcv_segmentation/configs/metadata.json @@ -1,7 +1,8 @@ { "schema": "https://github.com/Project-MONAI/MONAI-extra-test-data/releases/download/0.8.1/meta_schema_20220324.json", - "version": "0.4.1", + "version": "0.4.2", "changelog": { + "0.4.2": "fix train params of use_checkpoint", "0.4.1": "update params to supprot torch.jit.trace torchscript conversion", "0.4.0": "add name tag", "0.3.9": "use ITKreader to avoid mass logs at image loading", diff --git a/models/swin_unetr_btcv_segmentation/configs/train.json b/models/swin_unetr_btcv_segmentation/configs/train.json index 5135eda1..e5694677 100644 --- a/models/swin_unetr_btcv_segmentation/configs/train.json +++ b/models/swin_unetr_btcv_segmentation/configs/train.json @@ -19,7 +19,7 @@ "in_channels": 1, "out_channels": 14, "feature_size": 48, - "use_checkpoint": false + "use_checkpoint": true }, "network": "$@network_def.to(@device)", "loss": { diff --git a/models/wholeBody_ct_segmentation/LICENSE b/models/wholeBody_ct_segmentation/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/models/wholeBody_ct_segmentation/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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/models/wholeBody_ct_segmentation/configs/evaluate.json b/models/wholeBody_ct_segmentation/configs/evaluate.json new file mode 100644 index 00000000..2860fc2a --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/evaluate.json @@ -0,0 +1,78 @@ +{ + "validate#postprocessing": { + "_target_": "Compose", + "transforms": [ + { + "_target_": "Activationsd", + "keys": "pred", + "softmax": true + }, + { + "_target_": "AsDiscreted", + "keys": [ + "pred", + "label" + ], + "argmax": [ + true, + false + ], + "to_onehot": 105 + }, + { + "_target_": "Invertd", + "keys": [ + "pred", + "label" + ], + "transform": "@validate#preprocessing", + "orig_keys": "image", + "meta_key_postfix": "meta_dict", + "nearest_interp": [ + true, + true + ], + "to_tensor": true + }, + { + "_target_": "SaveImaged", + "_disabled_": true, + "keys": "pred", + "meta_keys": "pred_meta_dict", + "output_dir": "@output_dir", + "resample": false, + "squeeze_end_dims": true + } + ] + }, + "validate#handlers": [ + { + "_target_": "CheckpointLoader", + "load_path": "$@ckpt_dir + '/model.pt'", + "load_dict": { + "model": "@network" + } + }, + { + "_target_": "StatsHandler", + "iteration_log": false + }, + { + "_target_": "MetricsSaver", + "save_dir": "@output_dir", + "metrics": [ + "val_mean_dice", + "val_acc" + ], + "metric_details": [ + "val_mean_dice" + ], + "batch_transform": "$monai.handlers.from_engine(['image_meta_dict'])", + "summary_ops": "*" + } + ], + "evaluating": [ + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$@validate#evaluator.run()" + ] +} diff --git a/models/wholeBody_ct_segmentation/configs/inference.json b/models/wholeBody_ct_segmentation/configs/inference.json new file mode 100644 index 00000000..b17f4ce8 --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/inference.json @@ -0,0 +1,159 @@ +{ + "displayable_configs": { + "highres": true, + "sw_overlap": 0.25, + "sw_batch_size": 1 + }, + "imports": [ + "$import glob", + "$import os" + ], + "bundle_root": ".", + "output_dir": "$@bundle_root + '/eval'", + "dataset_dir": "sampledata", + "datalist": "$list(sorted(glob.glob(@dataset_dir + '/imagesTs/*.nii.gz')))", + "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')", + "pixdim": "$[1.5, 1.5, 1.5] if @displayable_configs#highres else [3.0, 3.0, 3.0]", + "modelname": "$'model.pt' if @displayable_configs#highres else 'model_lowres.pt'", + "network_def": { + "_target_": "SegResNet", + "spatial_dims": 3, + "in_channels": 1, + "out_channels": 105, + "init_filters": 32, + "blocks_down": [ + 1, + 2, + 2, + 4 + ], + "blocks_up": [ + 1, + 1, + 1 + ], + "dropout_prob": 0.2 + }, + "network": "$@network_def.to(@device)", + "preprocessing": { + "_target_": "Compose", + "transforms": [ + { + "_target_": "LoadImaged", + "keys": "image" + }, + { + "_target_": "EnsureTyped", + "keys": "image" + }, + { + "_target_": "EnsureChannelFirstd", + "keys": "image" + }, + { + "_target_": "Orientationd", + "keys": "image", + "axcodes": "RAS" + }, + { + "_target_": "Spacingd", + "keys": "image", + "pixdim": "@pixdim", + "mode": "bilinear" + }, + { + "_target_": "NormalizeIntensityd", + "keys": "image", + "nonzero": true + }, + { + "_target_": "ScaleIntensityd", + "keys": "image", + "minv": -1.0, + "maxv": 1.0 + } + ] + }, + "dataset": { + "_target_": "Dataset", + "data": "$[{'image': i} for i in @datalist]", + "transform": "@preprocessing" + }, + "dataloader": { + "_target_": "DataLoader", + "dataset": "@dataset", + "batch_size": 1, + "shuffle": false, + "num_workers": 1 + }, + "inferer": { + "_target_": "SlidingWindowInferer", + "roi_size": [ + 96, + 96, + 96 + ], + "sw_batch_size": "@displayable_configs#sw_batch_size", + "overlap": "@displayable_configs#sw_overlap", + "padding_mode": "replicate", + "mode": "gaussian", + "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')" + }, + "postprocessing": { + "_target_": "Compose", + "transforms": [ + { + "_target_": "Activationsd", + "keys": "pred", + "softmax": true + }, + { + "_target_": "AsDiscreted", + "keys": "pred", + "argmax": true + }, + { + "_target_": "Invertd", + "keys": "pred", + "transform": "@preprocessing", + "orig_keys": "image", + "meta_key_postfix": "meta_dict", + "nearest_interp": true, + "to_tensor": true + }, + { + "_target_": "SaveImaged", + "keys": "pred", + "meta_keys": "pred_meta_dict", + "output_dir": "@output_dir" + } + ] + }, + "handlers": [ + { + "_target_": "CheckpointLoader", + "load_path": "$@bundle_root + '/models/' + @modelname", + "load_dict": { + "model": "@network" + } + }, + { + "_target_": "StatsHandler", + "iteration_log": false + } + ], + "evaluator": { + "_target_": "SupervisedEvaluator", + "device": "@device", + "val_data_loader": "@dataloader", + "network": "@network", + "inferer": "@inferer", + "postprocessing": "@postprocessing", + "val_handlers": "@handlers", + "amp": true + }, + "evaluating": [ + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$@evaluator.run()" + ] +} diff --git a/models/wholeBody_ct_segmentation/configs/logging.conf b/models/wholeBody_ct_segmentation/configs/logging.conf new file mode 100644 index 00000000..91c1a21c --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/logging.conf @@ -0,0 +1,21 @@ +[loggers] +keys=root + +[handlers] +keys=consoleHandler + +[formatters] +keys=fullFormatter + +[logger_root] +level=INFO +handlers=consoleHandler + +[handler_consoleHandler] +class=StreamHandler +level=INFO +formatter=fullFormatter +args=(sys.stdout,) + +[formatter_fullFormatter] +format=%(asctime)s - %(name)s - %(levelname)s - %(message)s diff --git a/models/wholeBody_ct_segmentation/configs/metadata.json b/models/wholeBody_ct_segmentation/configs/metadata.json new file mode 100644 index 00000000..f5513a70 --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/metadata.json @@ -0,0 +1,183 @@ +{ + "schema": "https://github.com/Project-MONAI/MONAI-extra-test-data/releases/download/0.8.1/meta_schema_20220324.json", + "version": "0.1.0", + "changelog": { + "0.1.0": "complete the model package", + "0.0.1": "initialize the model package structure" + }, + "monai_version": "1.1.0", + "pytorch_version": "1.13.0", + "numpy_version": "1.21.2", + "optional_packages_version": { + "nibabel": "4.0.1", + "pytorch-ignite": "0.4.9" + }, + "name": "Whole body CT segmentation", + "task": "TotalSegmentator Segmentation", + "description": "A pre-trained SegResNet model for volumetric (3D) segmentation of the 104 whole body segments", + "authors": "MONAI team", + "copyright": "Copyright (c) MONAI Consortium", + "data_source": "TotalSegmentator", + "data_type": "nibabel", + "image_classes": "104 foreground channels, 0 channel for the background, intensity scaled to [0, 1]", + "label_classes": "0 is the background, others are whole body segments", + "pred_classes": "0 is the background, 104 other chanels are whole body segments", + "eval_metrics": { + "mean_dice": 0.5 + }, + "intended_use": "This is an example, not to be used for diagnostic purposes", + "references": [ + "Wasserthal, J., Meyer, M., Breit, H.C., Cyriac, J., Yang, S. and Segeroth, M., 2022. TotalSegmentator: robust segmentation of 104 anatomical structures in CT images. arXiv preprint arXiv:2208.05868.", + "Myronenko, A., Siddiquee, M.M.R., Yang, D., He, Y. and Xu, D., 2022. Automated head and neck tumor segmentation from 3D PET/CT. arXiv preprint arXiv:2209.10809.", + "Tang, Y., Gao, R., Lee, H.H., Han, S., Chen, Y., Gao, D., Nath, V., Bermudez, C., Savona, M.R., Abramson, R.G. and Bao, S., 2021. High-resolution 3D abdominal segmentation with random patch network fusion. Medical image analysis, 69, p.101894." + ], + "network_data_format": { + "inputs": { + "image": { + "type": "image", + "format": "hounsfield", + "modality": "CT", + "num_channels": 1, + "spatial_shape": [ + 96, + 96, + 96 + ], + "dtype": "float32", + "value_range": [ + 0, + 1 + ], + "is_patch_data": true, + "channel_def": { + "0": "image" + } + } + }, + "outputs": { + "pred": { + "type": "image", + "format": "segmentation", + "num_channels": 105, + "spatial_shape": [ + 96, + 96, + 96 + ], + "dtype": "float32", + "value_range": [ + 0, + 104 + ], + "is_patch_data": true, + "channel_def": { + "0": "background", + "1": "spleen", + "2": "kidney_right", + "3": "kidney_left", + "4": "gallbladder", + "5": "liver", + "6": "stomach", + "7": "aorta", + "8": "inferior_vena_cava", + "9": "portal_vein_and_splenic_vein", + "10": "pancreas", + "11": "adrenal_gland_right", + "12": "adrenal_gland_left", + "13": "lung_upper_lobe_left", + "14": "lung_lower_lobe_left", + "15": "lung_upper_lobe_right", + "16": "lung_middle_lobe_right", + "17": "lung_lower_lobe_right", + "18": "vertebrae_L5", + "19": "vertebrae_L4", + "20": "vertebrae_L3", + "21": "vertebrae_L2", + "22": "vertebrae_L1", + "23": "vertebrae_T12", + "24": "vertebrae_T11", + "25": "vertebrae_T10", + "26": "vertebrae_T9", + "27": "vertebrae_T8", + "28": "vertebrae_T7", + "29": "vertebrae_T6", + "30": "vertebrae_T5", + "31": "vertebrae_T4", + "32": "vertebrae_T3", + "33": "vertebrae_T2", + "34": "vertebrae_T1", + "35": "vertebrae_C7", + "36": "vertebrae_C6", + "37": "vertebrae_C5", + "38": "vertebrae_C4", + "39": "vertebrae_C3", + "40": "vertebrae_C2", + "41": "vertebrae_C1", + "42": "esophagus", + "43": "trachea", + "44": "heart_myocardium", + "45": "heart_atrium_left", + "46": "heart_ventricle_left", + "47": "heart_atrium_right", + "48": "heart_ventricle_right", + "49": "pulmonary_artery", + "50": "brain", + "51": "iliac_artery_left", + "52": "iliac_artery_right", + "53": "iliac_vena_left", + "54": "iliac_vena_right", + "55": "small_bowel", + "56": "duodenum", + "57": "colon", + "58": "rib_left_1", + "59": "rib_left_2", + "60": "rib_left_3", + "61": "rib_left_4", + "62": "rib_left_5", + "63": "rib_left_6", + "64": "rib_left_7", + "65": "rib_left_8", + "66": "rib_left_9", + "67": "rib_left_10", + "68": "rib_left_11", + "69": "rib_left_12", + "70": "rib_right_1", + "71": "rib_right_2", + "72": "rib_right_3", + "73": "rib_right_4", + "74": "rib_right_5", + "75": "rib_right_6", + "76": "rib_right_7", + "77": "rib_right_8", + "78": "rib_right_9", + "79": "rib_right_10", + "80": "rib_right_11", + "81": "rib_right_12", + "82": "humerus_left", + "83": "humerus_right", + "84": "scapula_left", + "85": "scapula_right", + "86": "clavicula_left", + "87": "clavicula_right", + "88": "femur_left", + "89": "femur_right", + "90": "hip_left", + "91": "hip_right", + "92": "sacrum", + "93": "face", + "94": "gluteus_maximus_left", + "95": "gluteus_maximus_right", + "96": "gluteus_medius_left", + "97": "gluteus_medius_right", + "98": "gluteus_minimus_left", + "99": "gluteus_minimus_right", + "100": "autochthon_left", + "101": "autochthon_right", + "102": "iliopsoas_left", + "103": "iliopsoas_right", + "104": "urinary_bladder" + } + } + } + } +} diff --git a/models/wholeBody_ct_segmentation/configs/multi_gpu_evaluate.json b/models/wholeBody_ct_segmentation/configs/multi_gpu_evaluate.json new file mode 100644 index 00000000..f6b6c6dc --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/multi_gpu_evaluate.json @@ -0,0 +1,28 @@ +{ + "device": "$torch.device(f'cuda:{dist.get_rank()}')", + "network": { + "_target_": "torch.nn.parallel.DistributedDataParallel", + "module": "$@network_def.to(@device)", + "device_ids": [ + "@device" + ] + }, + "validate#sampler": { + "_target_": "DistributedSampler", + "dataset": "@validate#dataset", + "even_divisible": false, + "shuffle": false + }, + "validate#dataloader#sampler": "@validate#sampler", + "validate#handlers#1#_disabled_": "$dist.get_rank() > 0", + "evaluating": [ + "$import torch.distributed as dist", + "$dist.init_process_group(backend='nccl')", + "$torch.cuda.set_device(@device)", + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$import logging", + "$@validate#evaluator.logger.setLevel(logging.WARNING if dist.get_rank() > 0 else logging.INFO)", + "$@validate#evaluator.run()", + "$dist.destroy_process_group()" + ] +} diff --git a/models/wholeBody_ct_segmentation/configs/multi_gpu_train.json b/models/wholeBody_ct_segmentation/configs/multi_gpu_train.json new file mode 100644 index 00000000..4161e527 --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/multi_gpu_train.json @@ -0,0 +1,39 @@ +{ + "device": "$torch.device(f'cuda:{dist.get_rank()}')", + "network": { + "_target_": "torch.nn.parallel.DistributedDataParallel", + "module": "$@network_def.to(@device)", + "device_ids": [ + "@device" + ] + }, + "train#sampler": { + "_target_": "DistributedSampler", + "dataset": "@train#dataset", + "even_divisible": true, + "shuffle": true + }, + "train#dataloader#sampler": "@train#sampler", + "train#dataloader#shuffle": false, + "train#trainer#train_handlers": "$@train#handlers[: -2 if dist.get_rank() > 0 else None]", + "validate#sampler": { + "_target_": "DistributedSampler", + "dataset": "@validate#dataset", + "even_divisible": false, + "shuffle": false + }, + "validate#dataloader#sampler": "@validate#sampler", + "validate#evaluator#val_handlers": "$None if dist.get_rank() > 0 else @validate#handlers", + "training": [ + "$import torch.distributed as dist", + "$dist.init_process_group(backend='nccl')", + "$torch.cuda.set_device(@device)", + "$monai.utils.set_determinism(seed=123)", + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$import logging", + "$@train#trainer.logger.setLevel(logging.WARNING if dist.get_rank() > 0 else logging.INFO)", + "$@validate#evaluator.logger.setLevel(logging.WARNING if dist.get_rank() > 0 else logging.INFO)", + "$@train#trainer.run()", + "$dist.destroy_process_group()" + ] +} diff --git a/models/wholeBody_ct_segmentation/configs/train.json b/models/wholeBody_ct_segmentation/configs/train.json new file mode 100644 index 00000000..9e79afd6 --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/train.json @@ -0,0 +1,422 @@ +{ + "displayable_configs": { + "highres": true, + "init_LR": 0.0001 + }, + "imports": [ + "$import glob", + "$import os", + "$import ignite" + ], + "bundle_root": ".", + "ckpt_dir": "$@bundle_root + '/models'", + "output_dir": "$@bundle_root + '/eval'", + "dataset_dir": "sampledata", + "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", + "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", + "highres": true, + "val_interval": 20, + "init_LR": 0.0001, + "batch_size": 4, + "pixdim": "$[1.5, 1.5, 1.5] if @displayable_configs#highres else [3.0, 3.0, 3.0]", + "modelname": "$'model.pt' if @displayable_configs#highres else 'model_lowres.pt'", + "device": "$torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')", + "network_def": { + "_target_": "SegResNet", + "spatial_dims": 3, + "in_channels": 1, + "out_channels": 105, + "init_filters": 32, + "blocks_down": [ + 1, + 2, + 2, + 4 + ], + "blocks_up": [ + 1, + 1, + 1 + ], + "dropout_prob": 0.2 + }, + "network": "$@network_def.to(@device)", + "loss": { + "_target_": "DiceCELoss", + "to_onehot_y": true, + "softmax": true + }, + "optimizer": { + "_target_": "torch.optim.AdamW", + "params": "$@network.parameters()", + "lr": "@displayable_configs#init_LR", + "weight_decay": 1e-05 + }, + "train": { + "deterministic_transforms": [ + { + "_target_": "LoadImaged", + "keys": [ + "image", + "label" + ] + }, + { + "_target_": "EnsureChannelFirstd", + "keys": [ + "image", + "label" + ] + }, + { + "_target_": "EnsureTyped", + "keys": [ + "image", + "label" + ] + }, + { + "_target_": "Orientationd", + "keys": [ + "image", + "label" + ], + "axcodes": "RAS" + }, + { + "_target_": "Spacingd", + "keys": [ + "image", + "label" + ], + "pixdim": "@pixdim", + "mode": [ + "bilinear", + "nearest" + ] + }, + { + "_target_": "NormalizeIntensityd", + "keys": "image", + "nonzero": true + }, + { + "_target_": "CropForegroundd", + "keys": [ + "image", + "label" + ], + "source_key": "image", + "margin": 10, + "k_divisible": [ + 96, + 96, + 96 + ] + }, + { + "_target_": "GaussianSmoothd", + "keys": [ + "image" + ], + "sigma": 0.4 + }, + { + "_target_": "ScaleIntensityd", + "keys": "image", + "minv": -1.0, + "maxv": 1.0 + }, + { + "_target_": "EnsureTyped", + "keys": [ + "image", + "label" + ] + } + ], + "random_transforms": [ + { + "_target_": "RandSpatialCropd", + "keys": [ + "image", + "label" + ], + "roi_size": [ + 96, + 96, + 96 + ], + "random_size": false + } + ], + "preprocessing": { + "_target_": "Compose", + "transforms": "$@train#deterministic_transforms + @train#random_transforms" + }, + "dataset": { + "_target_": "CacheDataset", + "data": "$[{'image': i, 'label': l} for i, l in zip(@images[:-10], @labels[:-10])]", + "transform": "@train#preprocessing", + "cache_rate": 0.4, + "num_workers": 4 + }, + "dataloader": { + "_target_": "DataLoader", + "dataset": "@train#dataset", + "batch_size": "@batch_size", + "shuffle": true, + "num_workers": 4 + }, + "inferer": { + "_target_": "SimpleInferer" + }, + "postprocessing": { + "_target_": "Compose", + "transforms": [ + { + "_target_": "Activationsd", + "keys": "pred", + "softmax": true + }, + { + "_target_": "AsDiscreted", + "keys": [ + "pred", + "label" + ], + "argmax": [ + true, + false + ], + "to_onehot": 105 + } + ] + }, + "handlers": [ + { + "_target_": "ValidationHandler", + "validator": "@validate#evaluator", + "epoch_level": true, + "interval": "@val_interval" + }, + { + "_target_": "StatsHandler", + "tag_name": "train_loss", + "output_transform": "$monai.handlers.from_engine(['loss'], first=True)" + }, + { + "_target_": "TensorBoardStatsHandler", + "log_dir": "@output_dir", + "tag_name": "train_loss", + "output_transform": "$monai.handlers.from_engine(['loss'], first=True)" + } + ], + "key_metric": { + "train_accuracy": { + "_target_": "ignite.metrics.Accuracy", + "output_transform": "$monai.handlers.from_engine(['pred', 'label'])" + } + }, + "trainer": { + "_target_": "SupervisedTrainer", + "max_epochs": 4000, + "device": "@device", + "train_data_loader": "@train#dataloader", + "network": "@network", + "loss_function": "@loss", + "optimizer": "@optimizer", + "inferer": "@train#inferer", + "postprocessing": "@train#postprocessing", + "key_train_metric": "@train#key_metric", + "train_handlers": "@train#handlers", + "amp": true + } + }, + "validate": { + "preprocessing": { + "_target_": "Compose", + "transforms": [ + { + "_target_": "LoadImaged", + "keys": [ + "image", + "label" + ] + }, + { + "_target_": "EnsureChannelFirstd", + "keys": [ + "image", + "label" + ] + }, + { + "_target_": "EnsureTyped", + "keys": [ + "image", + "label" + ] + }, + { + "_target_": "Orientationd", + "keys": [ + "image", + "label" + ], + "axcodes": "RAS" + }, + { + "_target_": "Spacingd", + "keys": [ + "image", + "label" + ], + "pixdim": "@pixdim", + "mode": [ + "bilinear", + "nearest" + ] + }, + { + "_target_": "NormalizeIntensityd", + "keys": "image", + "nonzero": true + }, + { + "_target_": "CropForegroundd", + "keys": [ + "image", + "label" + ], + "source_key": "image", + "margin": 10, + "k_divisible": [ + 96, + 96, + 96 + ] + }, + { + "_target_": "GaussianSmoothd", + "keys": [ + "image" + ], + "sigma": 0.4 + }, + { + "_target_": "ScaleIntensityd", + "keys": "image", + "minv": -1.0, + "maxv": 1.0 + }, + { + "_target_": "CenterSpatialCropd", + "keys": [ + "image", + "label" + ], + "roi_size": [ + 160, + 160, + 160 + ] + } + ] + }, + "postprocessing": { + "_target_": "Compose", + "transforms": [ + { + "_target_": "Activationsd", + "keys": "pred", + "softmax": true + }, + { + "_target_": "AsDiscreted", + "keys": [ + "pred", + "label" + ], + "argmax": [ + true, + false + ], + "to_onehot": 105 + } + ] + }, + "dataset": { + "_target_": "Dataset", + "data": "$[{'image': i, 'label': l} for i, l in zip(@images[-10:], @labels[-10:])]", + "transform": "@validate#preprocessing" + }, + "dataloader": { + "_target_": "DataLoader", + "dataset": "@validate#dataset", + "batch_size": 1, + "shuffle": false, + "num_workers": 4 + }, + "inferer": { + "_target_": "SlidingWindowInferer", + "roi_size": [ + 96, + 96, + 96 + ], + "sw_batch_size": 1, + "overlap": 0.25 + }, + "handlers": [ + { + "_target_": "StatsHandler", + "iteration_log": false + }, + { + "_target_": "TensorBoardStatsHandler", + "log_dir": "@output_dir", + "iteration_log": false + }, + { + "_target_": "CheckpointSaver", + "save_dir": "@ckpt_dir", + "save_dict": { + "model": "@network" + }, + "save_key_metric": true, + "key_metric_filename": "@modelname" + } + ], + "key_metric": { + "val_mean_dice": { + "_target_": "MeanDice", + "include_background": false, + "output_transform": "$monai.handlers.from_engine(['pred', 'label'])" + } + }, + "additional_metrics": { + "val_accuracy": { + "_target_": "ignite.metrics.Accuracy", + "output_transform": "$monai.handlers.from_engine(['pred', 'label'])" + } + }, + "evaluator": { + "_target_": "SupervisedEvaluator", + "device": "@device", + "val_data_loader": "@validate#dataloader", + "network": "@network", + "inferer": "@validate#inferer", + "postprocessing": "@validate#postprocessing", + "key_val_metric": "@validate#key_metric", + "additional_metrics": "@validate#additional_metrics", + "val_handlers": "@validate#handlers", + "amp": true + } + }, + "training": [ + "$monai.utils.set_determinism(seed=123)", + "$setattr(torch.backends.cudnn, 'benchmark', True)", + "$@train#trainer.run()" + ] +} diff --git a/models/wholeBody_ct_segmentation/docs/README.md b/models/wholeBody_ct_segmentation/docs/README.md new file mode 100644 index 00000000..9a2b7fad --- /dev/null +++ b/models/wholeBody_ct_segmentation/docs/README.md @@ -0,0 +1,172 @@ +# Model Overview + +Body CT segmentation models are evolving. Starting from abdominal multi-organ segmentation model [1]. Now the community is developing hundreds of target anatomies. In this bundle, we provide re-trained models for (3D) segmentation of 104 whole-body segments. + +This model is trained using the SegResNet [3] network. The model is trained using TotalSegmentator datasets [2]. + +![structures](https://github.com/wasserth/TotalSegmentator/blob/master/resources/imgs/overview_classes.png) + +Figure source from the TotalSegmentator [2]. + +## MONAI Label Showcase + +- We highlight the use of this bundle to use and visualize in MONAI Label + 3D Slicer integration. + +![](./imgs/totalsegmentator_monailabel.png)
+ +## Data + +The training set is the 104 whole-body structures from the TotalSegmentator released datasets. Users can find more details on the datasets at https://github.com/wasserth/TotalSegmentator. All rights and licenses are reserved to the original authors. + +- Target: 104 structures +- Modality: CT +- Source: TotalSegmentator +- Challenge: Large volumes of structures in CT images + +### Preprocessing + +To use the bundle, users need to download the data and merge all annotated labels into one NIFTI file. Each file contains 0-104 values, each value represents one anatomy class. A sample set is provided with this [link](https://drive.google.com/file/d/1DtDmERVMjks1HooUhggOKAuDm0YIEunG/view?usp=share_link). + +## Training Configuration + +The segmentation of 104 tissues is formulated as voxel-wise multi-label segmentation. The model is optimized with the gradient descent method minimizing Dice + cross-entropy loss between the predicted mask and ground truth segmentation. + +The training was performed with the following: + +- GPU: 32 GB of GPU memory +- Actual Model Input: 96 x 96 x 96 +- AMP: True +- Optimizer: AdamW +- Learning Rate: 1e-4 +- Loss: DiceCELoss + +### Input + +One channel +- CT image + +### Output + +105 channels +- Label 0: Background (everything else) +- label 1-105: Foreground classes (104) + +### High-Resolution and Low-Resolution Models + +We retrained two versions of the totalSegmentator models, following the original paper and implementation. +To meet multiple demands according to computation resources and performance, we provide a 1.5 mm model and a 3.0 mm model, both models are trained with 104 foreground output channels. + +In this bundle, we configured a parameter called `highres`, users can set it to `true` when using 1.5 mm model, and set it to `false` to use the 3.0 mm model. The high-resolution model is named `model.pt` by default, the low-resolution model is named `model_lowres.pt`. + +In MONAI Label use case, users can set the parameter in 3D Slicer plugin to control which model to infer and train. + +- Pretrained Checkpoints + - 1.5 mm model: [Download link](https://drive.google.com/file/d/1PHpFWboimEXmMSe2vBra6T8SaCMC2SHT/view?usp=share_link) + - 3.0 mm model: [Download link](https://drive.google.com/file/d/1c3osYscnr6710ObqZZS8GkZJQlWlc7rt/view?usp=share_link) + +### Resource Requirements and Latency Benchmarks + +Latencies and memory performance of using the bundle with MONAI Label: + +Tested Image Dimension: **(512, 512, 397)**, the slice thickness is **1.5mm** in this case. After resample to **1.5** isotropic resolution, the dimension is **(287, 287, 397)** + +## 1.5 mm (highres) model (Single Model with 104 foreground classes) + +Benchmarking on GPU: Memory: **28.73G** + +- `++ Latencies => Total: 6.0277; Pre: 1.6228; Inferer: 4.1153; Invert: 0.0000; Post: 0.0897; Write: 0.1995` + +Benchmarking on CPU: Memory: **26G** + +- `++ Latencies => Total: 38.3108; Pre: 1.6643; Inferer: 30.3018; Invert: 0.0000; Post: 6.1656; Write: 0.1786` + +## 3.0 mm (lowres) model (single model with 104 foreground classes) + +GPU: Memory: **5.89G** + + - `++ Latencies => Total: 1.9993; Pre: 1.2363; Inferer: 0.5207; Invert: 0.0000; Post: 0.0358; Write: 0.2060` + +CPU: Memory: **2.3G** + + - `++ Latencies => Total: 6.6138; Pre: 1.3192; Inferer: 3.6746; Invert: 0.0000; Post: 1.4431; Write: 0.1760` + +## Performance + +- 1.5 mm Model Training + + - Training Accuracy + +![](./imgs/totalsegmentator_train_accuracy.png)
+ + - Validation Dice + +![](./imgs/totalsegmentator_15mm_validation.png)
+ +## MONAI Bundle Commands +In addition to the Pythonic APIs, a few command line interfaces (CLI) are provided to interact with the bundle. The CLI supports flexible use cases, such as overriding configs at runtime and predefining arguments in a file. + +For more details usage instructions, visit the [MONAI Bundle Configuration Page](https://docs.monai.io/en/latest/config_syntax.html). + +#### Execute training + +``` +python -m monai.bundle run training --meta_file configs/metadata.json --config_file configs/train.json --logging_file configs/logging.conf +``` + +#### Override the `train` config to execute multi-GPU training + +``` +torchrun --standalone --nnodes=1 --nproc_per_node=2 -m monai.bundle run training --meta_file configs/metadata.json --config_file "['configs/train.json','configs/multi_gpu_train.json']" --logging_file configs/logging.conf +``` + +Please note that the distributed training-related options depend on the actual running environment; thus, users may need to remove `--standalone`, modify `--nnodes`, or do some other necessary changes according to the machine used. For more details, please refer to [pytorch's official tutorial](https://pytorch.org/tutorials/intermediate/ddp_tutorial.html). + +#### Override the `train` config to execute evaluation with the trained model + +``` +python -m monai.bundle run evaluating --meta_file configs/metadata.json --config_file "['configs/train.json','configs/evaluate.json']" --logging_file configs/logging.conf +``` + +#### Override the `train` config and `evaluate` config to execute multi-GPU evaluation + +``` +torchrun --standalone --nnodes=1 --nproc_per_node=2 -m monai.bundle run evaluating --meta_file configs/metadata.json --config_file "['configs/train.json','configs/evaluate.json','configs/multi_gpu_evaluate.json']" --logging_file configs/logging.conf +``` + +#### Execute inference + +``` +python -m monai.bundle run evaluating --meta_file configs/metadata.json --config_file configs/inference.json --logging_file configs/logging.conf +``` +#### Execute inference with Data Samples + +``` +python -m monai.bundle run evaluating --meta_file configs/metadata.json --config_file configs/inference.json --logging_file configs/logging.conf --datalist "['sampledata/imagesTr/s0037.nii.gz','sampledata/imagesTr/s0038.nii.gz']" +``` + + +# References + +[1] Tang, Y., Gao, R., Lee, H.H., Han, S., Chen, Y., Gao, D., Nath, V., Bermudez, C., Savona, M.R., Abramson, R.G. and Bao, S., 2021. High-resolution 3D abdominal segmentation with random patch network fusion. Medical image analysis, 69, p.101894. + +[2] Wasserthal, J., Meyer, M., Breit, H.C., Cyriac, J., Yang, S. and Segeroth, M., 2022. TotalSegmentator: robust segmentation of 104 anatomical structures in CT images. arXiv preprint arXiv:2208.05868. + +[3] Myronenko, A., Siddiquee, M.M.R., Yang, D., He, Y. and Xu, D., 2022. Automated head and neck tumor segmentation from 3D PET/CT. arXiv preprint arXiv:2209.10809. + + + +# License + +Copyright (c) MONAI Consortium + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/models/wholeBody_ct_segmentation/docs/data_license.txt b/models/wholeBody_ct_segmentation/docs/data_license.txt new file mode 100644 index 00000000..0f702f0b --- /dev/null +++ b/models/wholeBody_ct_segmentation/docs/data_license.txt @@ -0,0 +1,6 @@ +Third Party Licenses +----------------------------------------------------------------------- + +/*********************************************************************/ +i. TotalSegmentator + https://zenodo.org/record/6802614#.Y9iTydLMJ6I diff --git a/models/wholeBody_ct_segmentation/docs/imgs/totalsegmentator_15mm_validation.png b/models/wholeBody_ct_segmentation/docs/imgs/totalsegmentator_15mm_validation.png new file mode 100644 index 00000000..c97f9a57 Binary files /dev/null and b/models/wholeBody_ct_segmentation/docs/imgs/totalsegmentator_15mm_validation.png differ diff --git a/models/wholeBody_ct_segmentation/docs/imgs/totalsegmentator_monailabel.png b/models/wholeBody_ct_segmentation/docs/imgs/totalsegmentator_monailabel.png new file mode 100644 index 00000000..ec28eafd Binary files /dev/null and b/models/wholeBody_ct_segmentation/docs/imgs/totalsegmentator_monailabel.png differ diff --git a/models/wholeBody_ct_segmentation/docs/imgs/totalsegmentator_train_accuracy.png b/models/wholeBody_ct_segmentation/docs/imgs/totalsegmentator_train_accuracy.png new file mode 100644 index 00000000..3af606c3 Binary files /dev/null and b/models/wholeBody_ct_segmentation/docs/imgs/totalsegmentator_train_accuracy.png differ diff --git a/models/wholeBody_ct_segmentation/large_files.yml b/models/wholeBody_ct_segmentation/large_files.yml new file mode 100644 index 00000000..3420abf2 --- /dev/null +++ b/models/wholeBody_ct_segmentation/large_files.yml @@ -0,0 +1,9 @@ +large_files: + - path: "models/model.pt" + url: "https://drive.google.com/file/d/1PHpFWboimEXmMSe2vBra6T8SaCMC2SHT/view?usp=share_link" + hash_val: "" + hash_type: "" + - path: "models/model_lowres.pt" + url: "https://drive.google.com/file/d/1c3osYscnr6710ObqZZS8GkZJQlWlc7rt/view?usp=share_link" + hash_val: "" + hash_type: ""