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..7e7c7530 --- /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": [ + false, + 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..312ef5a1 --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/inference.json @@ -0,0 +1,161 @@ +{ + "imports": [ + "$import glob", + "$import os" + ], + "bundle_root": ".", + "output_dir": "$@bundle_root + '/eval'", + "dataset_dir": "../datasets/Task09_Spleen", + "datalist": "$list(sorted(glob.glob(@dataset_dir + '/imagesTs/*.nii.gz')))", + "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)", + "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": [ + 1.5, + 1.5, + 1.5 + ], + "mode": "bilinear" + }, + { + "_target_": "NormalizeIntensityd", + "keys": "image", + "nonzero": true + }, + { + "_target_": "GaussianSmoothd", + "keys": "image", + "sigma": 0.4 + }, + { + "_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": 1, + "overlap": 0.4, + "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_": "Invertd", + "keys": "pred", + "transform": "@preprocessing", + "orig_keys": "image", + "meta_key_postfix": "meta_dict", + "nearest_interp": false, + "to_tensor": true + }, + { + "_target_": "AsDiscreted", + "keys": "pred", + "argmax": true + }, + { + "_target_": "SaveImaged", + "keys": "pred", + "meta_keys": "pred_meta_dict", + "output_dir": "@output_dir" + } + ] + }, + "handlers": [ + { + "_target_": "CheckpointLoader", + "load_path": "$@bundle_root + '/models/model.pt'", + "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..3db9b7bf --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/metadata.json @@ -0,0 +1,181 @@ +{ + "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" + }, + "task": "Whole Body CT 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." + ], + "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 100755 index 00000000..ede6ff0d --- /dev/null +++ b/models/wholeBody_ct_segmentation/configs/train.json @@ -0,0 +1,309 @@ +{ + "imports": [ + "$import glob", + "$import os", + "$import ignite" + ], + "bundle_root": ".", + "ckpt_dir": "$@bundle_root + '/models'", + "output_dir": "$@bundle_root + '/eval'", + "dataset_dir": "../datasets/sampleTrain", + "images": "$list(sorted(glob.glob(@dataset_dir + '/imagesTr/*.nii.gz')))", + "labels": "$list(sorted(glob.glob(@dataset_dir + '/labelsTr/*.nii.gz')))", + "val_interval": 2, + "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": 0.0001, + "weight_decay": 0.00001 + }, + "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": [ + 1.5, + 1.5, + 1.5 + ], + "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_": "Dataset", + "data": "$[{'image': i, 'label': l} for i, l in zip(@images[:-1], @labels[:-1])]", + "transform": "@train#preprocessing" + }, + "dataloader": { + "_target_": "DataLoader", + "dataset": "@train#dataset", + "batch_size": 1, + "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": 5, + "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": "%train#deterministic_transforms" + }, + "dataset": { + "_target_": "Dataset", + "data": "$[{'image': i, 'label': l} for i, l in zip(@images[-1:], @labels[-1:])]", + "transform": "@validate#preprocessing" + }, + "dataloader": { + "_target_": "DataLoader", + "dataset": "@validate#dataset", + "batch_size": 1, + "shuffle": false, + "num_workers": 2 + }, + "inferer": { + "_target_": "SlidingWindowInferer", + "roi_size": [ + 96, + 96, + 96 + ], + "sw_batch_size": 1, + "overlap": 0.4, + "device": "$torch.device('cpu')" + }, + "postprocessing": "%train#postprocessing", + "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": "model.pt" + } + ], + "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..969c91be --- /dev/null +++ b/models/wholeBody_ct_segmentation/docs/README.md @@ -0,0 +1,113 @@ +# Model Overview +A pre-trained model for volumetric (3D) segmentation of 104 whole body segments. + +This model is trained using the SegResNet [1] 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]. + +## 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. + +- Target: 104 structures +- Modality: CT +- Source: TotalSegmentator +- Challenge: Large volumes of structures in CT images + +## Training configuration + +The segmentation of 104 tissues is formulated as the voxel-wise multi-label segmentation. The model is optimized with gradient descent method minimizing Dice + cross entropy loss between the predicted mask and ground truth segmentation. + +The training was performed with the following: + +- GPU: at least 24 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) +- TODO + +### Resource Requirements + +- TODO + +## Performance + +- TODO + + +#### Training Loss +![A graph showing the training loss over 1260 epochs (10080 iterations).](https://developer.download.nvidia.com/assets/Clara/Images/clara_pt_spleen_ct_segmentation_train_2.png) + +#### Validation Dice +![A graph showing the validation mean Dice over 1260 epochs.](https://developer.download.nvidia.com/assets/Clara/Images/clara_pt_spleen_ct_segmentation_val_2.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 +``` + +# References +[1] 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. + +[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. + +# 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/large_files.yml b/models/wholeBody_ct_segmentation/large_files.yml new file mode 100644 index 00000000..a781b1c1 --- /dev/null +++ b/models/wholeBody_ct_segmentation/large_files.yml @@ -0,0 +1,5 @@ +large_files: + - path: "models/model.pt" + url: "https://drive.google.com/file/d/1FOe-GL0uKe9SdPWvw8-0hRJsJwgmSy3m/view?usp=share_link" + hash_val: "b418a2dc8672ce2fd98dc255036e7a3d" + hash_type: "md5"