From bddcbbaf1bde1d1a0c5f3aa72dcda465877b0317 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Tue, 25 Jun 2024 17:34:40 +0000 Subject: [PATCH 01/34] added first files, duplicated from the totalsegmentator implementation --- models/mrsegmentator/.temp_image.nii.gz | 0 models/mrsegmentator/README.md | 3 + models/mrsegmentator/__init__.py | 1 + models/mrsegmentator/config/REMOVE_slicer.yml | 29 +++ models/mrsegmentator/config/default.yml | 32 +++ models/mrsegmentator/dockerfiles/Dockerfile | 30 +++ models/mrsegmentator/meta.json | 216 ++++++++++++++++++ models/mrsegmentator/scripts/run.py | 48 ++++ .../utils/MRSegmentatorMLRunner.py | 153 +++++++++++++ .../utils/TotalSegmentatorRunner.py | 73 ++++++ models/mrsegmentator/utils/__init__.py | 1 + 11 files changed, 586 insertions(+) create mode 100644 models/mrsegmentator/.temp_image.nii.gz create mode 100644 models/mrsegmentator/README.md create mode 100644 models/mrsegmentator/__init__.py create mode 100644 models/mrsegmentator/config/REMOVE_slicer.yml create mode 100644 models/mrsegmentator/config/default.yml create mode 100644 models/mrsegmentator/dockerfiles/Dockerfile create mode 100644 models/mrsegmentator/meta.json create mode 100644 models/mrsegmentator/scripts/run.py create mode 100644 models/mrsegmentator/utils/MRSegmentatorMLRunner.py create mode 100644 models/mrsegmentator/utils/TotalSegmentatorRunner.py create mode 100644 models/mrsegmentator/utils/__init__.py diff --git a/models/mrsegmentator/.temp_image.nii.gz b/models/mrsegmentator/.temp_image.nii.gz new file mode 100644 index 00000000..e69de29b diff --git a/models/mrsegmentator/README.md b/models/mrsegmentator/README.md new file mode 100644 index 00000000..714846a6 --- /dev/null +++ b/models/mrsegmentator/README.md @@ -0,0 +1,3 @@ +# TotalSegmentator @ MHub.ai + +For details on the model or how to run the end-to-end pipeline on your data in a single command, visit [mhub.ai/models/totalsegmentator](https://mhub.ai/models/totalsegmentator) diff --git a/models/mrsegmentator/__init__.py b/models/mrsegmentator/__init__.py new file mode 100644 index 00000000..90f60fdd --- /dev/null +++ b/models/mrsegmentator/__init__.py @@ -0,0 +1 @@ +from .utils import * \ No newline at end of file diff --git a/models/mrsegmentator/config/REMOVE_slicer.yml b/models/mrsegmentator/config/REMOVE_slicer.yml new file mode 100644 index 00000000..ded7d4ee --- /dev/null +++ b/models/mrsegmentator/config/REMOVE_slicer.yml @@ -0,0 +1,29 @@ +general: + data_base_dir: /app/data + version: 1.0.0 + description: TotalSegmentator workflow for 3D Slicer (nrrd to nrrd) + +execute: +- NrrdImporter +- NiftiConverter +- TotalSegmentatorMLRunner +- JsonSegExporter +- DataOrganizer + +modules: + NrrdImporter: + input_dir: input_data + input_file_name: image.nrrd + + TotalSegmentatorMLRunner: + use_fast_mode: true + + JsonSegExporter: + segment_id_meta_key: roi + targets: + - nifti:mod=seg-->[basename] + + DataOrganizer: + targets: + - nifti:mod=seg-->[basename] + - json:mod=seg-->segdef.json \ No newline at end of file diff --git a/models/mrsegmentator/config/default.yml b/models/mrsegmentator/config/default.yml new file mode 100644 index 00000000..f72fd292 --- /dev/null +++ b/models/mrsegmentator/config/default.yml @@ -0,0 +1,32 @@ +general: + data_base_dir: /app/data + version: 1.0.0 + description: TotalSegmentator default config (dicom to dicom) + +execute: +- DicomImporter +- NiftiConverter +- TotalSegmentatorMLRunner +- DsegConverter +- DataOrganizer + +modules: + DicomImporter: + source_dir: input_data + import_dir: sorted_data + sort_data: true + meta: + mod: '%Modality' + + TotalSegmentatorMLRunner: + use_fast_mode: true + + DsegConverter: + model_name: TotalSegmentator + body_part_examined: WHOLEBODY + source_segs: nifti:mod=seg + skip_empty_slices: True + + DataOrganizer: + targets: + - dicomseg:mod=seg-->[i:sid]/TotalSegmentator.seg.dcm diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile new file mode 100644 index 00000000..6bf85807 --- /dev/null +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -0,0 +1,30 @@ +FROM mhubai/base:latest + +# FIXME: set this environment variable as a shortcut to avoid nnunet crashing the build +# by pulling sklearn instead of scikit-learn +# N.B. this is a known issue: +# https://github.com/MIC-DKFZ/nnUNet/issues/1281 +# https://github.com/MIC-DKFZ/nnUNet/pull/1209 +#ENV SKLEARN_ALLOW_DEPRECATED_SKLEARN_PACKAGE_INSTALL=True +RUN apt-get update && apt-get install -y \ + python3.9 \ + python3-pip + +# Install TotalSegmentator +RUN python3 --version +#RUN python3.9 -m pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 --extra-index-url https://download.pytorch.org/whl/cu116 +RUN python3.9 -m pip install --no-cache-dir mrsegmentator + +# Execute mrsegmentator once to download the weights, this will fail to run but download regardless +RUN touch .temp_image.nii.gz +RUN mrsegmentator -i .temp_image.nii.gz; exit 0 + +# Import the MHub model definiton +#ARG MHUB_MODELS_REPO +#RUN buildutils/import_mhub_model.sh totalsegmentator ${MHUB_MODELS_REPO} + +# Default run script +#ENTRYPOINT ["python3", "-m", "mhubio.run"] +#CMD ["--config", "/app/models/totalsegmentator/config/default.yml"] + +CMD ["/bin/bash"] diff --git a/models/mrsegmentator/meta.json b/models/mrsegmentator/meta.json new file mode 100644 index 00000000..9975518d --- /dev/null +++ b/models/mrsegmentator/meta.json @@ -0,0 +1,216 @@ +{ + "id": "1a7ff9ac-dea4-45c3-9ec3-502decca3e0c", + "name": "totalsegmentator", + "title": "TotalSegmentator", + "summary": { + "description": "TotalSegmentator is an AI-based pipeline for the segmentation of 104 anatomical structures in CT images (with and without contrast).", + "inputs": [ + { + "label": "Input Image", + "description": "The CT scan of a patient (any part of the body).", + "format": "DICOM", + "modality": "CT", + "bodypartexamined": "WHOLEBODY", + "slicethickness": "1.5 mm", + "non-contrast": true, + "contrast": true + } + ], + "outputs": [ + { + "type": "Segmentation", + "classes": [ + "SPLEEN", + "RIGHT_KIDNEY", + "LEFT_KIDNEY", + "GALLBLADDER", + "LIVER", + "STOMACH", + "AORTA", + "INFERIOR_VENA_CAVA", + "PORTAL_AND_SPLENIC_VEIN", + "PANCREAS", + "RIGHT_ADRENAL_GLAND", + "LEFT_ADRENAL_GLAND", + "LEFT_UPPER_LUNG_LOBE", + "LEFT_LOWER_LUNG_LOBE", + "RIGHT_UPPER_LUNG_LOBE", + "RIGHT_MIDDLE_LUNG_LOBE", + "RIGHT_LOWER_LUNG_LOBE", + "VERTEBRAE_L5", + "VERTEBRAE_L4", + "VERTEBRAE_L3", + "VERTEBRAE_L2", + "VERTEBRAE_L1", + "VERTEBRAE_T12", + "VERTEBRAE_T11", + "VERTEBRAE_T10", + "VERTEBRAE_T9", + "VERTEBRAE_T8", + "VERTEBRAE_T7", + "VERTEBRAE_T6", + "VERTEBRAE_T5", + "VERTEBRAE_T4", + "VERTEBRAE_T3", + "VERTEBRAE_T2", + "VERTEBRAE_T1", + "VERTEBRAE_C7", + "VERTEBRAE_C6", + "VERTEBRAE_C5", + "VERTEBRAE_C4", + "VERTEBRAE_C3", + "VERTEBRAE_C2", + "VERTEBRAE_C1", + "ESOPHAGUS", + "TRACHEA", + "MYOCARDIUM", + "LEFT_ATRIUM", + "LEFT_VENTRICLE", + "RIGHT_ATRIUM", + "RIGHT_VENTRICLE", + "PULMONARY_ARTERY", + "BRAIN", + "LEFT_ILIAC_ARTERY", + "RIGHT_ILIAC_ARTERY", + "LEFT_ILIAC_VEIN", + "RIGHT_ILIAC_VEIN", + "SMALL_INTESTINE", + "DUODENUM", + "COLON", + "LEFT_RIB_1", + "LEFT_RIB_2", + "LEFT_RIB_3", + "LEFT_RIB_4", + "LEFT_RIB_5", + "LEFT_RIB_6", + "LEFT_RIB_7", + "LEFT_RIB_8", + "LEFT_RIB_9", + "LEFT_RIB_10", + "LEFT_RIB_11", + "LEFT_RIB_12", + "RIGHT_RIB_1", + "RIGHT_RIB_2", + "RIGHT_RIB_3", + "RIGHT_RIB_4", + "RIGHT_RIB_5", + "RIGHT_RIB_6", + "RIGHT_RIB_7", + "RIGHT_RIB_8", + "RIGHT_RIB_9", + "RIGHT_RIB_10", + "RIGHT_RIB_11", + "RIGHT_RIB_12", + "LEFT_HUMERUS", + "RIGHT_HUMERUS", + "LEFT_SCAPULA", + "RIGHT_SCAPULA", + "LEFT_CLAVICLE", + "RIGHT_CLAVICLE", + "LEFT_FEMUR", + "RIGHT_FEMUR", + "LEFT_HIP", + "RIGHT_HIP", + "SACRUM", + "FACE", + "LEFT_GLUTEUS_MAXIMUS", + "RIGHT_GLUTEUS_MAXIMUS", + "LEFT_GLUTEUS_MEDIUS", + "RIGHT_GLUTEUS_MEDIUS", + "LEFT_GLUTEUS_MINIMUS", + "RIGHT_GLUTEUS_MINIMUS", + "LEFT_AUTOCHTHONOUS_BACK_MUSCLE", + "RIGHT_AUTOCHTHONOUS_BACK_MUSCLE", + "LEFT_ILIOPSOAS", + "RIGHT_ILIOPSOAS", + "URINARY_BLADDER" + ] + } + ], + "model": { + "architecture": "U-net", + "training": "supervised", + "cmpapproach": "ensemble" + }, + "data": { + "training": { + "vol_samples": 1082 + }, + "evaluation": { + "vol_samples": 65 + }, + "public": true, + "external": false + } + }, + "details": { + "name": "TotalSegmentator", + "version": "1.0.0", + "devteam": "Department of Research and Analysis at University Hospital Basel", + "type": "nnU-Net (U-Net structure, optimized by data-driven heuristics)", + "date": { + "weights": "06/07/22", + "code": "n/a", + "pub": "2023" + }, + "cite": "Jakob Wasserthal, Hanns-Christian Breit, Manfred T. Meyer, Maurice Pradella, Daniel Hinck, Alexander W. Sauter, Tobias Heye, Daniel T. Boll, Joshy Cyriac, Shan Yang, Michael Bach, and Martin Segeroth (2023). TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images. Radiology Artificial Intelligence, 5:5", + "license": { + "code": "Apache 2.0", + "weights": "CC BY-NC 4.0" + }, + "publications": [ + { + "title": "TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images", + "uri": "https://pubs.rsna.org/doi/10.1148/ryai.230024" + } + ], + "github": "https://github.com/wasserth/TotalSegmentator", + "zenodo": "https://zenodo.org/record/6802342", + "colab": "https://colab.research.google.com/github/MHubAI/models/blob/colab/models/totalsegmentator/notebooks/totalsegmentator_mwe.ipynb", + "slicer": true + }, + "info": { + "use": { + "title": "Intended Use", + "text": "This model is intended to perform segmentations of 104 anatomic structures (27 organs, 59 bones, 10 muscles, 8 vessels) that are relevant for use cases such as organ volumetry, disease characterization, and surgical or radiation therapy planning. The CT images were randomly sampled from routine clinical studies, such that the dataset contains scans of patients with different ages, pathologies, of different body parts, acquired with different scanners, and sequences. The slice thickness should not exceed 1.5mm for best results." + }, + "analyses": { + "title": "Quantitative Analyses", + "text": "The model's performance was assessed using the Dice Coefficient on a held-out portion of the in-house dataset (public). For more information, please refer to the model's publication [1].", + "references": [ + { + "label": "TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images", + "uri": "https://pubs.rsna.org/doi/10.1148/ryai.230024" + } + ] + }, + "evaluation": { + "title": "Evaluation Data", + "text": "The evaluation dataset consists of 65 CT scans of patients with different ages, presenting various pathologies, and acquired with various imaging protocols. The Nora Imaging Platform was used for manual segmentation or further refinement of generated segmentations, starting from data uniformely resampled to 1.5mm isotropic. Segmentation was supervised by two physicians with three and six years of experience in body imaging. If an existing model for a given structure was publicly available, that model was used to create a first segmentation, which was then validated and refined manually. Furthermore, the authors used an iterative learning approach to speed up the segmentation process [1][2]. The evaluation process was conducted on images resampled to 1.5mm isotropic.", + "references": [ + { + "label": "TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images", + "uri": "https://pubs.rsna.org/doi/10.1148/ryai.230024" + }, + { + "label": "TotalSegmentator dataset", + "uri": "https://doi.org/10.5281/zenodo.6802613" + } + ] + }, + "training": { + "title": "Training Data", + "text": "The training dataset consists of 1082 CT scans of patients with different ages, presenting various pathologies, and acquired with various imaging protocols [1][2]. All of the CT images were resampled to a common resolution of 1.5mm isotropic before training. For details regarding the labels the model was trained with, see the section above.", + "references": [ + { + "label": "TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images", + "uri": "https://pubs.rsna.org/doi/10.1148/ryai.230024" + }, + { + "label": "TotalSegmentator dataset", + "uri": "https://doi.org/10.5281/zenodo.6802613" + } + ] + } + } +} \ No newline at end of file diff --git a/models/mrsegmentator/scripts/run.py b/models/mrsegmentator/scripts/run.py new file mode 100644 index 00000000..f1e42463 --- /dev/null +++ b/models/mrsegmentator/scripts/run.py @@ -0,0 +1,48 @@ +""" +------------------------------------------------- +MHub - run the TS pipeline locally +------------------------------------------------- + +------------------------------------------------- +Author: Leonard Nürnberg +Email: leonard.nuernberg@maastrichtuniversity.nl +------------------------------------------------- +""" + +import sys, os +sys.path.append('.') + +from mhubio.core import Config, DataType, FileType, CT, SEG +from mhubio.modules.importer.DicomImporter import DicomImporter +from mhubio.modules.convert.NiftiConverter import NiftiConverter +from mhubio.modules.convert.DsegConverter import DsegConverter +from mhubio.modules.organizer.DataOrganizer import DataOrganizer +from models.totalsegmentator.utils.TotalSegmentatorRunner import TotalSegmentatorRunner + +# clean +import shutil +shutil.rmtree("/app/data/sorted_data", ignore_errors=True) +shutil.rmtree("/app/tmp", ignore_errors=True) +shutil.rmtree("/app/data/output_data", ignore_errors=True) + +# config +config = Config('/app/models/totalsegmentator/config/config.yml') +config.verbose = True # TODO: define levels of verbosity and integrate consistently. + +# import +DicomImporter(config).execute() + +# convert (ct:dicom -> ct:nifti) +NiftiConverter(config).execute() + +# execute model (ct:nifti -> seg:nifti) +TotalSegmentatorRunner(config).execute() + +# convert (seg:nifti -> seg:dicomseg) +DsegConverter(config).execute() + +# organize data into output folder +organizer = DataOrganizer(config, set_file_permissions=sys.platform.startswith('linux')) +organizer.setTarget(DataType(FileType.NIFTI, CT), "/app/data/output_data/[i:sid]/[path]") +organizer.setTarget(DataType(FileType.DICOMSEG, SEG), "/app/data/output_data/[i:sid]/TotalSegmentator.seg.dcm") +organizer.execute() \ No newline at end of file diff --git a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py new file mode 100644 index 00000000..3ba5ac82 --- /dev/null +++ b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py @@ -0,0 +1,153 @@ +""" +------------------------------------------------- +MHub - Run Module for TotalSegmentator. +------------------------------------------------- + +------------------------------------------------- +Author: Leonard Nürnberg +Email: leonard.nuernberg@maastrichtuniversity.nl +------------------------------------------------- +""" + +from mhubio.core import Module, Instance, InstanceData, DataType, FileType, CT, SEG, IO, DataTypeQuery +import os, subprocess + +mapping = { + 'spleen': 'SPLEEN', + 'right_kidney': 'RIGHT_KIDNEY', + 'left_kidney': 'LEFT_KIDNEY', + 'gallbladder': 'GALLBLADDER', + 'liver': 'LIVER', + 'stomach': 'STOMACH', + 'aorta': 'AORTA', + 'inferior_vena_cava': 'INFERIOR_VENA_CAVA', + 'portal_vein_and_splenic_vein': 'PORTAL_AND_SPLENIC_VEIN', + 'pancreas': 'PANCREAS', + 'right_adrenal_gland': 'RIGHT_ADRENAL_GLAND', + 'left_adrenal_gland': 'LEFT_ADRENAL_GLAND', + 'left_lung': 'LEFT_LUNG', + 'right_lung': 'RIGHT_LUNG', + 'vertebrae_L5': 'VERTEBRAE_L5', + 'vertebrae_L4': 'VERTEBRAE_L4', + 'vertebrae_L3': 'VERTEBRAE_L3', + 'vertebrae_L2': 'VERTEBRAE_L2', + 'vertebrae_L1': 'VERTEBRAE_L1', + 'vertebrae_T12': 'VERTEBRAE_T12', + 'vertebrae_T11': 'VERTEBRAE_T11', + 'vertebrae_T10': 'VERTEBRAE_T10', + 'vertebrae_T9': 'VERTEBRAE_T9', + 'vertebrae_T8': 'VERTEBRAE_T8', + 'vertebrae_T7': 'VERTEBRAE_T7', + 'vertebrae_T6': 'VERTEBRAE_T6', + 'vertebrae_T5': 'VERTEBRAE_T5', + 'vertebrae_T4': 'VERTEBRAE_T4', + 'vertebrae_T3': 'VERTEBRAE_T3', + 'vertebrae_T2': 'VERTEBRAE_T2', + 'vertebrae_T1': 'VERTEBRAE_T1', + 'vertebrae_C7': 'VERTEBRAE_C7', + 'vertebrae_C6': 'VERTEBRAE_C6', + 'vertebrae_C5': 'VERTEBRAE_C5', + 'vertebrae_C4': 'VERTEBRAE_C4', + 'vertebrae_C3': 'VERTEBRAE_C3', + 'vertebrae_C2': 'VERTEBRAE_C2', + 'vertebrae_C1': 'VERTEBRAE_C1', + 'esophagus': 'ESOPHAGUS', + 'trachea': 'TRACHEA', + 'heart_myocardium': 'MYOCARDIUM', + 'heart_atrium_left': 'LEFT_ATRIUM', + 'heart_ventricle_left': 'LEFT_VENTRICLE', + 'heart_atrium_right': 'RIGHT_ATRIUM', + 'heart_ventricle_right': 'RIGHT_VENTRICLE', + 'pulmonary_artery': 'PULMONARY_ARTERY', + 'brain': 'BRAIN', + 'iliac_artery_left': 'LEFT_ILIAC_ARTERY', + 'iliac_artery_right': 'RIGHT_ILIAC_ARTERY', + 'iliac_vena_left': 'LEFT_ILIAC_VEIN', + 'iliac_vena_right': 'RIGHT_ILIAC_VEIN', + 'small_bowel': 'SMALL_INTESTINE', + 'duodenum': 'DUODENUM', + 'colon': 'COLON', + 'rib_left_1': 'LEFT_RIB_1', + 'rib_left_2': 'LEFT_RIB_2', + 'rib_left_3': 'LEFT_RIB_3', + 'rib_left_4': 'LEFT_RIB_4', + 'rib_left_5': 'LEFT_RIB_5', + 'rib_left_6': 'LEFT_RIB_6', + 'rib_left_7': 'LEFT_RIB_7', + 'rib_left_8': 'LEFT_RIB_8', + 'rib_left_9': 'LEFT_RIB_9', + 'rib_left_10': 'LEFT_RIB_10', + 'rib_left_11': 'LEFT_RIB_11', + 'rib_left_12': 'LEFT_RIB_12', + 'rib_right_1': 'RIGHT_RIB_1', + 'rib_right_2': 'RIGHT_RIB_2', + 'rib_right_3': 'RIGHT_RIB_3', + 'rib_right_4': 'RIGHT_RIB_4', + 'rib_right_5': 'RIGHT_RIB_5', + 'rib_right_6': 'RIGHT_RIB_6', + 'rib_right_7': 'RIGHT_RIB_7', + 'rib_right_8': 'RIGHT_RIB_8', + 'rib_right_9': 'RIGHT_RIB_9', + 'rib_right_10': 'RIGHT_RIB_10', + 'rib_right_11': 'RIGHT_RIB_11', + 'rib_right_12': 'RIGHT_RIB_12', + 'humerus_left': 'LEFT_HUMERUS', + 'humerus_right': 'RIGHT_HUMERUS', + 'scapula_left': 'LEFT_SCAPULA', + 'scapula_right': 'RIGHT_SCAPULA', + 'clavicula_left': 'LEFT_CLAVICLE', + 'clavicula_right': 'RIGHT_CLAVICLE', + 'femur_left': 'LEFT_FEMUR', + 'femur_right': 'RIGHT_FEMUR', + 'hip_left': 'LEFT_HIP', + 'hip_right': 'RIGHT_HIP', + 'sacrum': 'SACRUM', + 'face': 'FACE', + 'gluteus_maximus_left': 'LEFT_GLUTEUS_MAXIMUS', + 'gluteus_maximus_right': 'RIGHT_GLUTEUS_MAXIMUS', + 'gluteus_medius_left': 'LEFT_GLUTEUS_MEDIUS', + 'gluteus_medius_right': 'RIGHT_GLUTEUS_MEDIUS', + 'gluteus_minimus_left': 'LEFT_GLUTEUS_MINIMUS', + 'gluteus_minimus_right': 'RIGHT_GLUTEUS_MINIMUS', + 'autochthon_left': 'LEFT_AUTOCHTHONOUS_BACK_MUSCLE', + 'autochthon_right': 'RIGHT_AUTOCHTHONOUS_BACK_MUSCLE', + 'iliopsoas_left': 'LEFT_ILIOPSOAS', + 'iliopsoas_right': 'RIGHT_ILIOPSOAS', + 'urinary_bladder': 'URINARY_BLADDER' +} + +# from totalsegmentator.map_to_binary import class_map +# ROI = ','.join(mapping[class_map['total'][ci]] for ci in range(1, 105)) +#ROI = 'SPLEEN,RIGHT_KIDNEY,LEFT_KIDNEY,GALLBLADDER,LIVER,STOMACH,AORTA,INFERIOR_VENA_CAVA,PORTAL_AND_SPLENIC_VEIN,PANCREAS,RIGHT_ADRENAL_GLAND,LEFT_ADRENAL_GLAND,LEFT_UPPER_LUNG_LOBE,LEFT_LOWER_LUNG_LOBE,RIGHT_UPPER_LUNG_LOBE,RIGHT_MIDDLE_LUNG_LOBE,RIGHT_LOWER_LUNG_LOBE,VERTEBRAE_L5,VERTEBRAE_L4,VERTEBRAE_L3,VERTEBRAE_L2,VERTEBRAE_L1,VERTEBRAE_T12,VERTEBRAE_T11,VERTEBRAE_T10,VERTEBRAE_T9,VERTEBRAE_T8,VERTEBRAE_T7,VERTEBRAE_T6,VERTEBRAE_T5,VERTEBRAE_T4,VERTEBRAE_T3,VERTEBRAE_T2,VERTEBRAE_T1,VERTEBRAE_C7,VERTEBRAE_C6,VERTEBRAE_C5,VERTEBRAE_C4,VERTEBRAE_C3,VERTEBRAE_C2,VERTEBRAE_C1,ESOPHAGUS,TRACHEA,MYOCARDIUM,LEFT_ATRIUM,LEFT_VENTRICLE,RIGHT_ATRIUM,RIGHT_VENTRICLE,PULMONARY_ARTERY,BRAIN,LEFT_ILIAC_ARTERY,RIGHT_ILIAC_ARTERY,LEFT_ILIAC_VEIN,RIGHT_ILIAC_VEIN,SMALL_INTESTINE,DUODENUM,COLON,LEFT_RIB_1,LEFT_RIB_2,LEFT_RIB_3,LEFT_RIB_4,LEFT_RIB_5,LEFT_RIB_6,LEFT_RIB_7,LEFT_RIB_8,LEFT_RIB_9,LEFT_RIB_10,LEFT_RIB_11,LEFT_RIB_12,RIGHT_RIB_1,RIGHT_RIB_2,RIGHT_RIB_3,RIGHT_RIB_4,RIGHT_RIB_5,RIGHT_RIB_6,RIGHT_RIB_7,RIGHT_RIB_8,RIGHT_RIB_9,RIGHT_RIB_10,RIGHT_RIB_11,RIGHT_RIB_12,LEFT_HUMERUS,RIGHT_HUMERUS,LEFT_SCAPULA,RIGHT_SCAPULA,LEFT_CLAVICLE,RIGHT_CLAVICLE,LEFT_FEMUR,RIGHT_FEMUR,LEFT_HIP,RIGHT_HIP,SACRUM,FACE,LEFT_GLUTEUS_MAXIMUS,RIGHT_GLUTEUS_MAXIMUS,LEFT_GLUTEUS_MEDIUS,RIGHT_GLUTEUS_MEDIUS,LEFT_GLUTEUS_MINIMUS,RIGHT_GLUTEUS_MINIMUS,LEFT_AUTOCHTHONOUS_BACK_MUSCLE,RIGHT_AUTOCHTHONOUS_BACK_MUSCLE,LEFT_ILIOPSOAS,RIGHT_ILIOPSOAS,URINARY_BLADDER' +ROI = 'BACKGROUND, SPLEEN, RIGHT_KIDNEY, LEFT_KIDNEY, GALLBLADDER, LIVER, STOMACH, PANCREAS, RIGHT_ADRENAL_GLAND, LEFT_ADRENAL_GLAND, LEFT_LUNG, RIGHT_LUNG, HEART, AORTA, INFERIOR_VENA_CAVA, PORTAL_AND_SPLENIC_VEIN, LEFT_ILIAC_ARTERY, RIGHT_ILIAC_ARTERY, ESOPHAGUS, SMALL_INTESTINE, DUODENUM, COLON, URINARY_BLADDER, SPINE, SACRUM, LEFT_HIP, RIGHT_HIP, LEFT_FEMUR, RIGHT_FEMUR, LEFT_AUTOCHTHONOUS_BACK_MUSCLE, RIGHT_AUTOCHTHONOUS_BACK_MUSCLE, LEFT_ILIOPSOAS, RIGHT_ILIOPSOAS, LEFT_GLUTEUS_MAXIMUS, RIGHT_GLUTEUS_MAXIMUS, LEFT_GLUTEUS_MEDIUS, RIGHT_GLUTEUS_MEDIUS, LEFT_GLUTEUS_MINIMUS, RIGHT_GLUTEUS_MINIMUS' + +#NOte: Background, SPINE still needs to be implemented + +#@IO.Config('use_fast_mode', bool, True, the="flag to set to run TotalSegmentator in fast mode") +class MRSegmentatorMLRunner(Module): + + #use_fast_mode: bool + + @IO.Instance() + @IO.Input('in_data', 'nifti:mod=ct', the="input whole body ct scan") + @IO.Output('out_data', 'segmentations.nii.gz', 'nifti:mod=seg:model=MRSegmentator:roi=BACKGROUND,SPLEEN,RIGHT_KIDNEY,LEFT_KIDNEY,GALLBLADDER,LIVER,STOMACH,PANCREAS,RIGHT_ADRENAL_GLAND,LEFT_ADRENAL_GLAND,LEFT_LUNG,RIGHT_LUNG,HEART,AORTA,INFERIOR_VENA_CAVA,PORTAL_AND_SPLENIC_VEIN,LEFT_ILIAC_ARTERY,RIGHT_ILIAC_ARTERY,ESOPHAGUS,SMALL_INTESTINE,DUODENUM,COLON,URINARY_BLADDER,SPINE,SACRUM,LEFT_HIP,RIGHT_HIP,LEFT_FEMUR,RIGHT_FEMUR,LEFT_AUTOCHTHONOUS_BACK_MUSCLE,RIGHT_AUTOCHTHONOUS_BACK_MUSCLE,LEFT_ILIOPSOAS,RIGHT_ILIOPSOAS,LEFT_GLUTEUS_MAXIMUS,RIGHT_GLUTEUS_MAXIMUS,LEFT_GLUTEUS_MEDIUS,RIGHT_GLUTEUS_MEDIUS,LEFT_GLUTEUS_MINIMUS,RIGHT_GLUTEUS_MINIMUS', data='in_data', the="output segmentation mask containing all labels") + def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData) -> None: + + # build command + bash_command = ["mrsegmentator"] + bash_command += ["-i", in_data.abspath] + + bash_command += ["-outdir", out_data.abspath] + + # fast mode + if self.use_fast_mode: + self.v("Running TotalSegmentator in fast mode ('--fast', 3mm)") + bash_command += ["--fast"] + else: + self.v("Running TotalSegmentator in default mode (1.5mm)") + + # TODO: remove + self.v(">> run: ", " ".join(bash_command)) + + # run the model + self.subprocess(bash_command, text=True) \ No newline at end of file diff --git a/models/mrsegmentator/utils/TotalSegmentatorRunner.py b/models/mrsegmentator/utils/TotalSegmentatorRunner.py new file mode 100644 index 00000000..420b6faf --- /dev/null +++ b/models/mrsegmentator/utils/TotalSegmentatorRunner.py @@ -0,0 +1,73 @@ +""" +------------------------------------------------- +MHub - Run Module for MRSegmentator. +------------------------------------------------- + +------------------------------------------------- +Author: Felix Dorfner +Email: felix.dorfner@charite.de +------------------------------------------------- +""" + +from mhubio.modules.runner.ModelRunner import ModelRunner +from mhubio.core import Instance, InstanceData, DataType, FileType, CT, SEG + +import os, subprocess + +class TotalSegmentatorRunner(ModelRunner): + def runModel(self, instance: Instance) -> None: + + # configuration + use_fast_mode = "use_fast_mode" in self.c and self.c["use_fast_mode"] + use_multi_label_output = "use_multi_label_output" in self.c and self.c["use_multi_label_output"] + + # data + inp_data = instance.data.filter(DataType(FileType.NIFTI, CT)).first() + + # define model output (instance data bundle) + output = instance.getDataBundle("ts-model-out") + + # build command + bash_command = ["TotalSegmentator"] + bash_command += ["-i", inp_data.abspath] + + # multi-label output (one nifti file containing all labels instead of one nifti file per label) + if use_multi_label_output: + self.v("Generating multi-label output ('--ml')") + bash_command += ["-o", os.path.join(output.abspath, 'segmentations.nii.gz')] + bash_command += ["--ml"] + else: + self.v("Generating single-label output (default)") + bash_command += ["-o", output.abspath] + + # fast mode + if use_fast_mode: + self.v("Running TotalSegmentator in fast mode ('--fast', 3mm)") + bash_command += ["--fast"] + else: + self.v("Running TotalSegmentator in default mode (1.5mm)") + + # TODO: remove + self.v(">> run: ", " ".join(bash_command)) + + # run the model + self.subprocess(bash_command, text=True) + + # add output data + for out_file in os.listdir(output.abspath): + + # ignore non nifti files + if out_file[-7:] != ".nii.gz": + self.v(f"IGNORE OUTPUT FILE {out_file}") + continue + + # meta + meta = { + "model": "TotalSegmentator", + "roi": out_file[:-7] # TODO: standardize (as with the whole DataType usecase & filtering!) + } + + # create output data + seg_data_type = DataType(FileType.NIFTI, SEG + meta) + seg_data = InstanceData(out_file, type=seg_data_type, bundle=output) + seg_data.confirm() \ No newline at end of file diff --git a/models/mrsegmentator/utils/__init__.py b/models/mrsegmentator/utils/__init__.py new file mode 100644 index 00000000..73a657ea --- /dev/null +++ b/models/mrsegmentator/utils/__init__.py @@ -0,0 +1 @@ +from .TotalSegmentatorRunner import * \ No newline at end of file From 910d72761917cc5643ff9a487c3c119e2b0d5ff7 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 26 Jun 2024 16:03:49 +0000 Subject: [PATCH 02/34] Added different Configurations and finalized scripts --- models/mrsegmentator/config/REMOVE_slicer.yml | 29 ---- models/mrsegmentator/config/default.yml | 13 +- models/mrsegmentator/config/low_memory.yml | 33 ++++ models/mrsegmentator/dockerfiles/Dockerfile | 21 +-- models/mrsegmentator/meta.json | 114 +++---------- models/mrsegmentator/scripts/run.py | 48 ------ .../utils/MRSegmentatorMLRunner.py | 157 ++++-------------- .../utils/TotalSegmentatorRunner.py | 73 -------- models/mrsegmentator/utils/__init__.py | 1 - 9 files changed, 100 insertions(+), 389 deletions(-) delete mode 100644 models/mrsegmentator/config/REMOVE_slicer.yml create mode 100644 models/mrsegmentator/config/low_memory.yml delete mode 100644 models/mrsegmentator/scripts/run.py delete mode 100644 models/mrsegmentator/utils/TotalSegmentatorRunner.py diff --git a/models/mrsegmentator/config/REMOVE_slicer.yml b/models/mrsegmentator/config/REMOVE_slicer.yml deleted file mode 100644 index ded7d4ee..00000000 --- a/models/mrsegmentator/config/REMOVE_slicer.yml +++ /dev/null @@ -1,29 +0,0 @@ -general: - data_base_dir: /app/data - version: 1.0.0 - description: TotalSegmentator workflow for 3D Slicer (nrrd to nrrd) - -execute: -- NrrdImporter -- NiftiConverter -- TotalSegmentatorMLRunner -- JsonSegExporter -- DataOrganizer - -modules: - NrrdImporter: - input_dir: input_data - input_file_name: image.nrrd - - TotalSegmentatorMLRunner: - use_fast_mode: true - - JsonSegExporter: - segment_id_meta_key: roi - targets: - - nifti:mod=seg-->[basename] - - DataOrganizer: - targets: - - nifti:mod=seg-->[basename] - - json:mod=seg-->segdef.json \ No newline at end of file diff --git a/models/mrsegmentator/config/default.yml b/models/mrsegmentator/config/default.yml index f72fd292..e2f55ac4 100644 --- a/models/mrsegmentator/config/default.yml +++ b/models/mrsegmentator/config/default.yml @@ -1,12 +1,12 @@ general: data_base_dir: /app/data version: 1.0.0 - description: TotalSegmentator default config (dicom to dicom) + description: MRSegmentator default config (dicom to dicom) execute: - DicomImporter - NiftiConverter -- TotalSegmentatorMLRunner +- MRSegmentatorMLRunner - DsegConverter - DataOrganizer @@ -18,15 +18,16 @@ modules: meta: mod: '%Modality' - TotalSegmentatorMLRunner: - use_fast_mode: true + MRSegmentatorMLRunner: + use_fast_mode: false DsegConverter: - model_name: TotalSegmentator + model_name: MRSegmentator body_part_examined: WHOLEBODY source_segs: nifti:mod=seg skip_empty_slices: True DataOrganizer: targets: - - dicomseg:mod=seg-->[i:sid]/TotalSegmentator.seg.dcm + - dicomseg:mod=seg-->[i:sid]//MRSegmentator.seg.dcm + - log-->[i:sid]/logs/[d:module]/[filename] diff --git a/models/mrsegmentator/config/low_memory.yml b/models/mrsegmentator/config/low_memory.yml new file mode 100644 index 00000000..59fa7802 --- /dev/null +++ b/models/mrsegmentator/config/low_memory.yml @@ -0,0 +1,33 @@ +general: + data_base_dir: /app/data + version: 1.0.0 + description: MRSegmentator default lower memory footprint config (dicom to dicom) + +execute: +- DicomImporter +- NiftiConverter +- MRSegmentatorMLRunner +- DsegConverter +- DataOrganizer + +modules: + DicomImporter: + source_dir: input_data + import_dir: sorted_data + sort_data: true + meta: + mod: '%Modality' + + MRSegmentatorMLRunner: + use_fast_mode: true + + DsegConverter: + model_name: MRSegmentator + body_part_examined: WHOLEBODY + source_segs: nifti:mod=seg + skip_empty_slices: True + + DataOrganizer: + targets: + - dicomseg:mod=seg-->[i:sid]//MRSegmentator.seg.dcm + - log-->[i:sid]/logs/[d:module]/[filename] diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 6bf85807..642d1011 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -1,30 +1,17 @@ FROM mhubai/base:latest -# FIXME: set this environment variable as a shortcut to avoid nnunet crashing the build -# by pulling sklearn instead of scikit-learn -# N.B. this is a known issue: -# https://github.com/MIC-DKFZ/nnUNet/issues/1281 -# https://github.com/MIC-DKFZ/nnUNet/pull/1209 -#ENV SKLEARN_ALLOW_DEPRECATED_SKLEARN_PACKAGE_INSTALL=True +# Update Python, nnUNet needs Python 3.9 RUN apt-get update && apt-get install -y \ python3.9 \ python3-pip -# Install TotalSegmentator -RUN python3 --version -#RUN python3.9 -m pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 --extra-index-url https://download.pytorch.org/whl/cu116 +# Install MRSegmentator RUN python3.9 -m pip install --no-cache-dir mrsegmentator # Execute mrsegmentator once to download the weights, this will fail to run but download regardless RUN touch .temp_image.nii.gz RUN mrsegmentator -i .temp_image.nii.gz; exit 0 -# Import the MHub model definiton -#ARG MHUB_MODELS_REPO -#RUN buildutils/import_mhub_model.sh totalsegmentator ${MHUB_MODELS_REPO} - # Default run script -#ENTRYPOINT ["python3", "-m", "mhubio.run"] -#CMD ["--config", "/app/models/totalsegmentator/config/default.yml"] - -CMD ["/bin/bash"] +ENTRYPOINT ["python3", "-m", "mhubio.run"] +CMD ["--config", "/app/models/mrsegmentator/config/default.yml"] \ No newline at end of file diff --git a/models/mrsegmentator/meta.json b/models/mrsegmentator/meta.json index 9975518d..0722ee00 100644 --- a/models/mrsegmentator/meta.json +++ b/models/mrsegmentator/meta.json @@ -1,15 +1,15 @@ { - "id": "1a7ff9ac-dea4-45c3-9ec3-502decca3e0c", - "name": "totalsegmentator", - "title": "TotalSegmentator", + "id": "1a7ff9ac-dea4-45c3-9ec3-502decca3e0c", + "name": "mrsegmentator", + "title": "MRSegmentator", "summary": { - "description": "TotalSegmentator is an AI-based pipeline for the segmentation of 104 anatomical structures in CT images (with and without contrast).", + "description": "MRSegmentator is an AI-based pipeline for the segmentation of 40 anatomical structures in MR images (with and without contrast).", "inputs": [ { "label": "Input Image", - "description": "The CT scan of a patient (any part of the body).", + "description": "The MR scan of a patient (Thorax, Abdomen and Pelvis).", "format": "DICOM", - "modality": "CT", + "modality": "MRI", "bodypartexamined": "WHOLEBODY", "slicethickness": "1.5 mm", "non-contrast": true, @@ -26,104 +26,38 @@ "GALLBLADDER", "LIVER", "STOMACH", - "AORTA", - "INFERIOR_VENA_CAVA", - "PORTAL_AND_SPLENIC_VEIN", "PANCREAS", "RIGHT_ADRENAL_GLAND", "LEFT_ADRENAL_GLAND", - "LEFT_UPPER_LUNG_LOBE", - "LEFT_LOWER_LUNG_LOBE", - "RIGHT_UPPER_LUNG_LOBE", - "RIGHT_MIDDLE_LUNG_LOBE", - "RIGHT_LOWER_LUNG_LOBE", - "VERTEBRAE_L5", - "VERTEBRAE_L4", - "VERTEBRAE_L3", - "VERTEBRAE_L2", - "VERTEBRAE_L1", - "VERTEBRAE_T12", - "VERTEBRAE_T11", - "VERTEBRAE_T10", - "VERTEBRAE_T9", - "VERTEBRAE_T8", - "VERTEBRAE_T7", - "VERTEBRAE_T6", - "VERTEBRAE_T5", - "VERTEBRAE_T4", - "VERTEBRAE_T3", - "VERTEBRAE_T2", - "VERTEBRAE_T1", - "VERTEBRAE_C7", - "VERTEBRAE_C6", - "VERTEBRAE_C5", - "VERTEBRAE_C4", - "VERTEBRAE_C3", - "VERTEBRAE_C2", - "VERTEBRAE_C1", - "ESOPHAGUS", - "TRACHEA", - "MYOCARDIUM", - "LEFT_ATRIUM", - "LEFT_VENTRICLE", - "RIGHT_ATRIUM", - "RIGHT_VENTRICLE", - "PULMONARY_ARTERY", - "BRAIN", + "LEFT_LUNG", + "RIGHT_LUNG", + "HEART", + "AORTA", + "INFERIOR_VENA_CAVA", + "PORTAL_AND_SPLENIC_VEIN", "LEFT_ILIAC_ARTERY", "RIGHT_ILIAC_ARTERY", - "LEFT_ILIAC_VEIN", - "RIGHT_ILIAC_VEIN", + "ESOPHAGUS", "SMALL_INTESTINE", "DUODENUM", "COLON", - "LEFT_RIB_1", - "LEFT_RIB_2", - "LEFT_RIB_3", - "LEFT_RIB_4", - "LEFT_RIB_5", - "LEFT_RIB_6", - "LEFT_RIB_7", - "LEFT_RIB_8", - "LEFT_RIB_9", - "LEFT_RIB_10", - "LEFT_RIB_11", - "LEFT_RIB_12", - "RIGHT_RIB_1", - "RIGHT_RIB_2", - "RIGHT_RIB_3", - "RIGHT_RIB_4", - "RIGHT_RIB_5", - "RIGHT_RIB_6", - "RIGHT_RIB_7", - "RIGHT_RIB_8", - "RIGHT_RIB_9", - "RIGHT_RIB_10", - "RIGHT_RIB_11", - "RIGHT_RIB_12", - "LEFT_HUMERUS", - "RIGHT_HUMERUS", - "LEFT_SCAPULA", - "RIGHT_SCAPULA", - "LEFT_CLAVICLE", - "RIGHT_CLAVICLE", - "LEFT_FEMUR", - "RIGHT_FEMUR", + "URINARY_BLADDER", + "SPINE", + "SACRUM", "LEFT_HIP", "RIGHT_HIP", - "SACRUM", - "FACE", + "LEFT_FEMUR", + "RIGHT_FEMUR", + "LEFT_AUTOCHTHONOUS_BACK_MUSCLE", + "RIGHT_AUTOCHTHONOUS_BACK_MUSCLE", + "LEFT_ILIOPSOAS", + "RIGHT_ILIOPSOAS", "LEFT_GLUTEUS_MAXIMUS", "RIGHT_GLUTEUS_MAXIMUS", "LEFT_GLUTEUS_MEDIUS", "RIGHT_GLUTEUS_MEDIUS", "LEFT_GLUTEUS_MINIMUS", - "RIGHT_GLUTEUS_MINIMUS", - "LEFT_AUTOCHTHONOUS_BACK_MUSCLE", - "RIGHT_AUTOCHTHONOUS_BACK_MUSCLE", - "LEFT_ILIOPSOAS", - "RIGHT_ILIOPSOAS", - "URINARY_BLADDER" + "RIGHT_GLUTEUS_MINIMUS" ] } ], @@ -144,7 +78,7 @@ } }, "details": { - "name": "TotalSegmentator", + "name": "MRSegmentator", "version": "1.0.0", "devteam": "Department of Research and Analysis at University Hospital Basel", "type": "nnU-Net (U-Net structure, optimized by data-driven heuristics)", diff --git a/models/mrsegmentator/scripts/run.py b/models/mrsegmentator/scripts/run.py deleted file mode 100644 index f1e42463..00000000 --- a/models/mrsegmentator/scripts/run.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -------------------------------------------------- -MHub - run the TS pipeline locally -------------------------------------------------- - -------------------------------------------------- -Author: Leonard Nürnberg -Email: leonard.nuernberg@maastrichtuniversity.nl -------------------------------------------------- -""" - -import sys, os -sys.path.append('.') - -from mhubio.core import Config, DataType, FileType, CT, SEG -from mhubio.modules.importer.DicomImporter import DicomImporter -from mhubio.modules.convert.NiftiConverter import NiftiConverter -from mhubio.modules.convert.DsegConverter import DsegConverter -from mhubio.modules.organizer.DataOrganizer import DataOrganizer -from models.totalsegmentator.utils.TotalSegmentatorRunner import TotalSegmentatorRunner - -# clean -import shutil -shutil.rmtree("/app/data/sorted_data", ignore_errors=True) -shutil.rmtree("/app/tmp", ignore_errors=True) -shutil.rmtree("/app/data/output_data", ignore_errors=True) - -# config -config = Config('/app/models/totalsegmentator/config/config.yml') -config.verbose = True # TODO: define levels of verbosity and integrate consistently. - -# import -DicomImporter(config).execute() - -# convert (ct:dicom -> ct:nifti) -NiftiConverter(config).execute() - -# execute model (ct:nifti -> seg:nifti) -TotalSegmentatorRunner(config).execute() - -# convert (seg:nifti -> seg:dicomseg) -DsegConverter(config).execute() - -# organize data into output folder -organizer = DataOrganizer(config, set_file_permissions=sys.platform.startswith('linux')) -organizer.setTarget(DataType(FileType.NIFTI, CT), "/app/data/output_data/[i:sid]/[path]") -organizer.setTarget(DataType(FileType.DICOMSEG, SEG), "/app/data/output_data/[i:sid]/TotalSegmentator.seg.dcm") -organizer.execute() \ No newline at end of file diff --git a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py index 3ba5ac82..d58c060b 100644 --- a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py +++ b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py @@ -1,153 +1,60 @@ """ ------------------------------------------------- -MHub - Run Module for TotalSegmentator. +MHub - Run Module for MRSegmentator. ------------------------------------------------- ------------------------------------------------- -Author: Leonard Nürnberg -Email: leonard.nuernberg@maastrichtuniversity.nl +Author: Felix Dorfner +Email: felix.dorfner@charite.de ------------------------------------------------- """ from mhubio.core import Module, Instance, InstanceData, DataType, FileType, CT, SEG, IO, DataTypeQuery import os, subprocess +from segdb.classes.Segment import Segment +import shutil -mapping = { - 'spleen': 'SPLEEN', - 'right_kidney': 'RIGHT_KIDNEY', - 'left_kidney': 'LEFT_KIDNEY', - 'gallbladder': 'GALLBLADDER', - 'liver': 'LIVER', - 'stomach': 'STOMACH', - 'aorta': 'AORTA', - 'inferior_vena_cava': 'INFERIOR_VENA_CAVA', - 'portal_vein_and_splenic_vein': 'PORTAL_AND_SPLENIC_VEIN', - 'pancreas': 'PANCREAS', - 'right_adrenal_gland': 'RIGHT_ADRENAL_GLAND', - 'left_adrenal_gland': 'LEFT_ADRENAL_GLAND', - 'left_lung': 'LEFT_LUNG', - 'right_lung': 'RIGHT_LUNG', - 'vertebrae_L5': 'VERTEBRAE_L5', - 'vertebrae_L4': 'VERTEBRAE_L4', - 'vertebrae_L3': 'VERTEBRAE_L3', - 'vertebrae_L2': 'VERTEBRAE_L2', - 'vertebrae_L1': 'VERTEBRAE_L1', - 'vertebrae_T12': 'VERTEBRAE_T12', - 'vertebrae_T11': 'VERTEBRAE_T11', - 'vertebrae_T10': 'VERTEBRAE_T10', - 'vertebrae_T9': 'VERTEBRAE_T9', - 'vertebrae_T8': 'VERTEBRAE_T8', - 'vertebrae_T7': 'VERTEBRAE_T7', - 'vertebrae_T6': 'VERTEBRAE_T6', - 'vertebrae_T5': 'VERTEBRAE_T5', - 'vertebrae_T4': 'VERTEBRAE_T4', - 'vertebrae_T3': 'VERTEBRAE_T3', - 'vertebrae_T2': 'VERTEBRAE_T2', - 'vertebrae_T1': 'VERTEBRAE_T1', - 'vertebrae_C7': 'VERTEBRAE_C7', - 'vertebrae_C6': 'VERTEBRAE_C6', - 'vertebrae_C5': 'VERTEBRAE_C5', - 'vertebrae_C4': 'VERTEBRAE_C4', - 'vertebrae_C3': 'VERTEBRAE_C3', - 'vertebrae_C2': 'VERTEBRAE_C2', - 'vertebrae_C1': 'VERTEBRAE_C1', - 'esophagus': 'ESOPHAGUS', - 'trachea': 'TRACHEA', - 'heart_myocardium': 'MYOCARDIUM', - 'heart_atrium_left': 'LEFT_ATRIUM', - 'heart_ventricle_left': 'LEFT_VENTRICLE', - 'heart_atrium_right': 'RIGHT_ATRIUM', - 'heart_ventricle_right': 'RIGHT_VENTRICLE', - 'pulmonary_artery': 'PULMONARY_ARTERY', - 'brain': 'BRAIN', - 'iliac_artery_left': 'LEFT_ILIAC_ARTERY', - 'iliac_artery_right': 'RIGHT_ILIAC_ARTERY', - 'iliac_vena_left': 'LEFT_ILIAC_VEIN', - 'iliac_vena_right': 'RIGHT_ILIAC_VEIN', - 'small_bowel': 'SMALL_INTESTINE', - 'duodenum': 'DUODENUM', - 'colon': 'COLON', - 'rib_left_1': 'LEFT_RIB_1', - 'rib_left_2': 'LEFT_RIB_2', - 'rib_left_3': 'LEFT_RIB_3', - 'rib_left_4': 'LEFT_RIB_4', - 'rib_left_5': 'LEFT_RIB_5', - 'rib_left_6': 'LEFT_RIB_6', - 'rib_left_7': 'LEFT_RIB_7', - 'rib_left_8': 'LEFT_RIB_8', - 'rib_left_9': 'LEFT_RIB_9', - 'rib_left_10': 'LEFT_RIB_10', - 'rib_left_11': 'LEFT_RIB_11', - 'rib_left_12': 'LEFT_RIB_12', - 'rib_right_1': 'RIGHT_RIB_1', - 'rib_right_2': 'RIGHT_RIB_2', - 'rib_right_3': 'RIGHT_RIB_3', - 'rib_right_4': 'RIGHT_RIB_4', - 'rib_right_5': 'RIGHT_RIB_5', - 'rib_right_6': 'RIGHT_RIB_6', - 'rib_right_7': 'RIGHT_RIB_7', - 'rib_right_8': 'RIGHT_RIB_8', - 'rib_right_9': 'RIGHT_RIB_9', - 'rib_right_10': 'RIGHT_RIB_10', - 'rib_right_11': 'RIGHT_RIB_11', - 'rib_right_12': 'RIGHT_RIB_12', - 'humerus_left': 'LEFT_HUMERUS', - 'humerus_right': 'RIGHT_HUMERUS', - 'scapula_left': 'LEFT_SCAPULA', - 'scapula_right': 'RIGHT_SCAPULA', - 'clavicula_left': 'LEFT_CLAVICLE', - 'clavicula_right': 'RIGHT_CLAVICLE', - 'femur_left': 'LEFT_FEMUR', - 'femur_right': 'RIGHT_FEMUR', - 'hip_left': 'LEFT_HIP', - 'hip_right': 'RIGHT_HIP', - 'sacrum': 'SACRUM', - 'face': 'FACE', - 'gluteus_maximus_left': 'LEFT_GLUTEUS_MAXIMUS', - 'gluteus_maximus_right': 'RIGHT_GLUTEUS_MAXIMUS', - 'gluteus_medius_left': 'LEFT_GLUTEUS_MEDIUS', - 'gluteus_medius_right': 'RIGHT_GLUTEUS_MEDIUS', - 'gluteus_minimus_left': 'LEFT_GLUTEUS_MINIMUS', - 'gluteus_minimus_right': 'RIGHT_GLUTEUS_MINIMUS', - 'autochthon_left': 'LEFT_AUTOCHTHONOUS_BACK_MUSCLE', - 'autochthon_right': 'RIGHT_AUTOCHTHONOUS_BACK_MUSCLE', - 'iliopsoas_left': 'LEFT_ILIOPSOAS', - 'iliopsoas_right': 'RIGHT_ILIOPSOAS', - 'urinary_bladder': 'URINARY_BLADDER' -} - -# from totalsegmentator.map_to_binary import class_map -# ROI = ','.join(mapping[class_map['total'][ci]] for ci in range(1, 105)) -#ROI = 'SPLEEN,RIGHT_KIDNEY,LEFT_KIDNEY,GALLBLADDER,LIVER,STOMACH,AORTA,INFERIOR_VENA_CAVA,PORTAL_AND_SPLENIC_VEIN,PANCREAS,RIGHT_ADRENAL_GLAND,LEFT_ADRENAL_GLAND,LEFT_UPPER_LUNG_LOBE,LEFT_LOWER_LUNG_LOBE,RIGHT_UPPER_LUNG_LOBE,RIGHT_MIDDLE_LUNG_LOBE,RIGHT_LOWER_LUNG_LOBE,VERTEBRAE_L5,VERTEBRAE_L4,VERTEBRAE_L3,VERTEBRAE_L2,VERTEBRAE_L1,VERTEBRAE_T12,VERTEBRAE_T11,VERTEBRAE_T10,VERTEBRAE_T9,VERTEBRAE_T8,VERTEBRAE_T7,VERTEBRAE_T6,VERTEBRAE_T5,VERTEBRAE_T4,VERTEBRAE_T3,VERTEBRAE_T2,VERTEBRAE_T1,VERTEBRAE_C7,VERTEBRAE_C6,VERTEBRAE_C5,VERTEBRAE_C4,VERTEBRAE_C3,VERTEBRAE_C2,VERTEBRAE_C1,ESOPHAGUS,TRACHEA,MYOCARDIUM,LEFT_ATRIUM,LEFT_VENTRICLE,RIGHT_ATRIUM,RIGHT_VENTRICLE,PULMONARY_ARTERY,BRAIN,LEFT_ILIAC_ARTERY,RIGHT_ILIAC_ARTERY,LEFT_ILIAC_VEIN,RIGHT_ILIAC_VEIN,SMALL_INTESTINE,DUODENUM,COLON,LEFT_RIB_1,LEFT_RIB_2,LEFT_RIB_3,LEFT_RIB_4,LEFT_RIB_5,LEFT_RIB_6,LEFT_RIB_7,LEFT_RIB_8,LEFT_RIB_9,LEFT_RIB_10,LEFT_RIB_11,LEFT_RIB_12,RIGHT_RIB_1,RIGHT_RIB_2,RIGHT_RIB_3,RIGHT_RIB_4,RIGHT_RIB_5,RIGHT_RIB_6,RIGHT_RIB_7,RIGHT_RIB_8,RIGHT_RIB_9,RIGHT_RIB_10,RIGHT_RIB_11,RIGHT_RIB_12,LEFT_HUMERUS,RIGHT_HUMERUS,LEFT_SCAPULA,RIGHT_SCAPULA,LEFT_CLAVICLE,RIGHT_CLAVICLE,LEFT_FEMUR,RIGHT_FEMUR,LEFT_HIP,RIGHT_HIP,SACRUM,FACE,LEFT_GLUTEUS_MAXIMUS,RIGHT_GLUTEUS_MAXIMUS,LEFT_GLUTEUS_MEDIUS,RIGHT_GLUTEUS_MEDIUS,LEFT_GLUTEUS_MINIMUS,RIGHT_GLUTEUS_MINIMUS,LEFT_AUTOCHTHONOUS_BACK_MUSCLE,RIGHT_AUTOCHTHONOUS_BACK_MUSCLE,LEFT_ILIOPSOAS,RIGHT_ILIOPSOAS,URINARY_BLADDER' -ROI = 'BACKGROUND, SPLEEN, RIGHT_KIDNEY, LEFT_KIDNEY, GALLBLADDER, LIVER, STOMACH, PANCREAS, RIGHT_ADRENAL_GLAND, LEFT_ADRENAL_GLAND, LEFT_LUNG, RIGHT_LUNG, HEART, AORTA, INFERIOR_VENA_CAVA, PORTAL_AND_SPLENIC_VEIN, LEFT_ILIAC_ARTERY, RIGHT_ILIAC_ARTERY, ESOPHAGUS, SMALL_INTESTINE, DUODENUM, COLON, URINARY_BLADDER, SPINE, SACRUM, LEFT_HIP, RIGHT_HIP, LEFT_FEMUR, RIGHT_FEMUR, LEFT_AUTOCHTHONOUS_BACK_MUSCLE, RIGHT_AUTOCHTHONOUS_BACK_MUSCLE, LEFT_ILIOPSOAS, RIGHT_ILIOPSOAS, LEFT_GLUTEUS_MAXIMUS, RIGHT_GLUTEUS_MAXIMUS, LEFT_GLUTEUS_MEDIUS, RIGHT_GLUTEUS_MEDIUS, LEFT_GLUTEUS_MINIMUS, RIGHT_GLUTEUS_MINIMUS' - -#NOte: Background, SPINE still needs to be implemented - -#@IO.Config('use_fast_mode', bool, True, the="flag to set to run TotalSegmentator in fast mode") + + +# register custom segmentation before class definition +Segment.register("SPINE", name="Spine") + +@IO.Config('use_fast_mode', bool, False, the="flag to set to run MRSegmentator in a faster mode") class MRSegmentatorMLRunner(Module): - #use_fast_mode: bool + use_fast_mode: bool @IO.Instance() @IO.Input('in_data', 'nifti:mod=ct', the="input whole body ct scan") - @IO.Output('out_data', 'segmentations.nii.gz', 'nifti:mod=seg:model=MRSegmentator:roi=BACKGROUND,SPLEEN,RIGHT_KIDNEY,LEFT_KIDNEY,GALLBLADDER,LIVER,STOMACH,PANCREAS,RIGHT_ADRENAL_GLAND,LEFT_ADRENAL_GLAND,LEFT_LUNG,RIGHT_LUNG,HEART,AORTA,INFERIOR_VENA_CAVA,PORTAL_AND_SPLENIC_VEIN,LEFT_ILIAC_ARTERY,RIGHT_ILIAC_ARTERY,ESOPHAGUS,SMALL_INTESTINE,DUODENUM,COLON,URINARY_BLADDER,SPINE,SACRUM,LEFT_HIP,RIGHT_HIP,LEFT_FEMUR,RIGHT_FEMUR,LEFT_AUTOCHTHONOUS_BACK_MUSCLE,RIGHT_AUTOCHTHONOUS_BACK_MUSCLE,LEFT_ILIOPSOAS,RIGHT_ILIOPSOAS,LEFT_GLUTEUS_MAXIMUS,RIGHT_GLUTEUS_MAXIMUS,LEFT_GLUTEUS_MEDIUS,RIGHT_GLUTEUS_MEDIUS,LEFT_GLUTEUS_MINIMUS,RIGHT_GLUTEUS_MINIMUS', data='in_data', the="output segmentation mask containing all labels") + @IO.Output('out_data', 'segmentations.nii.gz', 'nifti:mod=seg:model=MRSegmentator:roi=SPLEEN,RIGHT_KIDNEY,LEFT_KIDNEY,GALLBLADDER,LIVER,STOMACH,PANCREAS,RIGHT_ADRENAL_GLAND,LEFT_ADRENAL_GLAND,LEFT_LUNG,RIGHT_LUNG,HEART,AORTA,INFERIOR_VENA_CAVA,PORTAL_AND_SPLENIC_VEIN,LEFT_ILIAC_ARTERY,RIGHT_ILIAC_ARTERY,ESOPHAGUS,SMALL_INTESTINE,DUODENUM,COLON,URINARY_BLADDER,SPINE,SACRUM,LEFT_HIP,RIGHT_HIP,LEFT_FEMUR,RIGHT_FEMUR,LEFT_AUTOCHTHONOUS_BACK_MUSCLE,RIGHT_AUTOCHTHONOUS_BACK_MUSCLE,LEFT_ILIOPSOAS,RIGHT_ILIOPSOAS,LEFT_GLUTEUS_MAXIMUS,RIGHT_GLUTEUS_MAXIMUS,LEFT_GLUTEUS_MEDIUS,RIGHT_GLUTEUS_MEDIUS,LEFT_GLUTEUS_MINIMUS,RIGHT_GLUTEUS_MINIMUS', data='in_data', the="output segmentation mask containing all labels") def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData) -> None: - # build command + tmp_dir = self.config.data.requestTempDir("mr_segmentator") + + raw_filename = os.path.basename(in_data.abspath) + name_part = raw_filename.split('.nii')[0] + extension = '.nii.gz' + + new_filename = f"{name_part}_seg{extension}" + bash_command = ["mrsegmentator"] bash_command += ["-i", in_data.abspath] - bash_command += ["-outdir", out_data.abspath] + bash_command += ["--outdir", tmp_dir] + - # fast mode if self.use_fast_mode: - self.v("Running TotalSegmentator in fast mode ('--fast', 3mm)") - bash_command += ["--fast"] + self.v("Running MRSegmentator in lower memory footprint mode ('--split_level', 1)") + self.v("Note: This increases runtime and possibly reduces segmentation performance.") + bash_command += ["--split_level", "1"] else: - self.v("Running TotalSegmentator in default mode (1.5mm)") + self.v("Running MRSegmentator in default mode.") + - # TODO: remove self.v(">> run: ", " ".join(bash_command)) # run the model - self.subprocess(bash_command, text=True) \ No newline at end of file + self.subprocess(bash_command, text=True) + + # copy data + shutil.copy(os.path.join(tmp_dir, new_filename), out_data.abspath) \ No newline at end of file diff --git a/models/mrsegmentator/utils/TotalSegmentatorRunner.py b/models/mrsegmentator/utils/TotalSegmentatorRunner.py deleted file mode 100644 index 420b6faf..00000000 --- a/models/mrsegmentator/utils/TotalSegmentatorRunner.py +++ /dev/null @@ -1,73 +0,0 @@ -""" -------------------------------------------------- -MHub - Run Module for MRSegmentator. -------------------------------------------------- - -------------------------------------------------- -Author: Felix Dorfner -Email: felix.dorfner@charite.de -------------------------------------------------- -""" - -from mhubio.modules.runner.ModelRunner import ModelRunner -from mhubio.core import Instance, InstanceData, DataType, FileType, CT, SEG - -import os, subprocess - -class TotalSegmentatorRunner(ModelRunner): - def runModel(self, instance: Instance) -> None: - - # configuration - use_fast_mode = "use_fast_mode" in self.c and self.c["use_fast_mode"] - use_multi_label_output = "use_multi_label_output" in self.c and self.c["use_multi_label_output"] - - # data - inp_data = instance.data.filter(DataType(FileType.NIFTI, CT)).first() - - # define model output (instance data bundle) - output = instance.getDataBundle("ts-model-out") - - # build command - bash_command = ["TotalSegmentator"] - bash_command += ["-i", inp_data.abspath] - - # multi-label output (one nifti file containing all labels instead of one nifti file per label) - if use_multi_label_output: - self.v("Generating multi-label output ('--ml')") - bash_command += ["-o", os.path.join(output.abspath, 'segmentations.nii.gz')] - bash_command += ["--ml"] - else: - self.v("Generating single-label output (default)") - bash_command += ["-o", output.abspath] - - # fast mode - if use_fast_mode: - self.v("Running TotalSegmentator in fast mode ('--fast', 3mm)") - bash_command += ["--fast"] - else: - self.v("Running TotalSegmentator in default mode (1.5mm)") - - # TODO: remove - self.v(">> run: ", " ".join(bash_command)) - - # run the model - self.subprocess(bash_command, text=True) - - # add output data - for out_file in os.listdir(output.abspath): - - # ignore non nifti files - if out_file[-7:] != ".nii.gz": - self.v(f"IGNORE OUTPUT FILE {out_file}") - continue - - # meta - meta = { - "model": "TotalSegmentator", - "roi": out_file[:-7] # TODO: standardize (as with the whole DataType usecase & filtering!) - } - - # create output data - seg_data_type = DataType(FileType.NIFTI, SEG + meta) - seg_data = InstanceData(out_file, type=seg_data_type, bundle=output) - seg_data.confirm() \ No newline at end of file diff --git a/models/mrsegmentator/utils/__init__.py b/models/mrsegmentator/utils/__init__.py index 73a657ea..e69de29b 100644 --- a/models/mrsegmentator/utils/__init__.py +++ b/models/mrsegmentator/utils/__init__.py @@ -1 +0,0 @@ -from .TotalSegmentatorRunner import * \ No newline at end of file From 85fb1864e017c4574d56fbc806b2dfe22f13a2b5 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 26 Jun 2024 17:51:34 +0000 Subject: [PATCH 03/34] Removed empty tmp image --- models/mrsegmentator/.temp_image.nii.gz | 0 models/mrsegmentator/dockerfiles/Dockerfile | 1 + 2 files changed, 1 insertion(+) delete mode 100644 models/mrsegmentator/.temp_image.nii.gz diff --git a/models/mrsegmentator/.temp_image.nii.gz b/models/mrsegmentator/.temp_image.nii.gz deleted file mode 100644 index e69de29b..00000000 diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 642d1011..9ca5c6c4 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -11,6 +11,7 @@ RUN python3.9 -m pip install --no-cache-dir mrsegmentator # Execute mrsegmentator once to download the weights, this will fail to run but download regardless RUN touch .temp_image.nii.gz RUN mrsegmentator -i .temp_image.nii.gz; exit 0 +RUN rm .temp_image.nii.gz # Default run script ENTRYPOINT ["python3", "-m", "mhubio.run"] From b7944e88720ad5abfcca5bd8c1c37c8bfc044313 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 26 Jun 2024 17:52:56 +0000 Subject: [PATCH 04/34] Updated Readme --- models/mrsegmentator/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/mrsegmentator/README.md b/models/mrsegmentator/README.md index 714846a6..92b9f624 100644 --- a/models/mrsegmentator/README.md +++ b/models/mrsegmentator/README.md @@ -1,3 +1,3 @@ -# TotalSegmentator @ MHub.ai +# MRSegmentator @ MHub.ai -For details on the model or how to run the end-to-end pipeline on your data in a single command, visit [mhub.ai/models/totalsegmentator](https://mhub.ai/models/totalsegmentator) +For details on the model or how to run the end-to-end pipeline on your data in a single command, visit [mhub.ai/models/mrsegmentator](https://mhub.ai/models/mrsegmentator) From 9f65218fd317a2a3fc27dd27709ea24bb818f195 Mon Sep 17 00:00:00 2001 From: FJDorfner <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 27 Jun 2024 14:54:24 -0400 Subject: [PATCH 05/34] Update meta.json --- models/mrsegmentator/meta.json | 270 ++++++++++++++++----------------- 1 file changed, 130 insertions(+), 140 deletions(-) diff --git a/models/mrsegmentator/meta.json b/models/mrsegmentator/meta.json index 0722ee00..a6118636 100644 --- a/models/mrsegmentator/meta.json +++ b/models/mrsegmentator/meta.json @@ -1,150 +1,140 @@ { - "id": "1a7ff9ac-dea4-45c3-9ec3-502decca3e0c", - "name": "mrsegmentator", - "title": "MRSegmentator", - "summary": { - "description": "MRSegmentator is an AI-based pipeline for the segmentation of 40 anatomical structures in MR images (with and without contrast).", - "inputs": [ - { - "label": "Input Image", - "description": "The MR scan of a patient (Thorax, Abdomen and Pelvis).", - "format": "DICOM", - "modality": "MRI", - "bodypartexamined": "WHOLEBODY", - "slicethickness": "1.5 mm", - "non-contrast": true, - "contrast": true - } - ], - "outputs": [ - { - "type": "Segmentation", - "classes": [ - "SPLEEN", - "RIGHT_KIDNEY", - "LEFT_KIDNEY", - "GALLBLADDER", - "LIVER", - "STOMACH", - "PANCREAS", - "RIGHT_ADRENAL_GLAND", - "LEFT_ADRENAL_GLAND", - "LEFT_LUNG", - "RIGHT_LUNG", - "HEART", - "AORTA", - "INFERIOR_VENA_CAVA", - "PORTAL_AND_SPLENIC_VEIN", - "LEFT_ILIAC_ARTERY", - "RIGHT_ILIAC_ARTERY", - "ESOPHAGUS", - "SMALL_INTESTINE", - "DUODENUM", - "COLON", - "URINARY_BLADDER", - "SPINE", - "SACRUM", - "LEFT_HIP", - "RIGHT_HIP", - "LEFT_FEMUR", - "RIGHT_FEMUR", - "LEFT_AUTOCHTHONOUS_BACK_MUSCLE", - "RIGHT_AUTOCHTHONOUS_BACK_MUSCLE", - "LEFT_ILIOPSOAS", - "RIGHT_ILIOPSOAS", - "LEFT_GLUTEUS_MAXIMUS", - "RIGHT_GLUTEUS_MAXIMUS", - "LEFT_GLUTEUS_MEDIUS", - "RIGHT_GLUTEUS_MEDIUS", - "LEFT_GLUTEUS_MINIMUS", - "RIGHT_GLUTEUS_MINIMUS" - ] - } - ], - "model": { - "architecture": "U-net", - "training": "supervised", - "cmpapproach": "ensemble" - }, - "data": { - "training": { - "vol_samples": 1082 - }, - "evaluation": { - "vol_samples": 65 - }, - "public": true, - "external": false - } - }, - "details": { - "name": "MRSegmentator", - "version": "1.0.0", - "devteam": "Department of Research and Analysis at University Hospital Basel", - "type": "nnU-Net (U-Net structure, optimized by data-driven heuristics)", - "date": { - "weights": "06/07/22", - "code": "n/a", - "pub": "2023" - }, - "cite": "Jakob Wasserthal, Hanns-Christian Breit, Manfred T. Meyer, Maurice Pradella, Daniel Hinck, Alexander W. Sauter, Tobias Heye, Daniel T. Boll, Joshy Cyriac, Shan Yang, Michael Bach, and Martin Segeroth (2023). TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images. Radiology Artificial Intelligence, 5:5", - "license": { - "code": "Apache 2.0", - "weights": "CC BY-NC 4.0" - }, - "publications": [ - { - "title": "TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images", - "uri": "https://pubs.rsna.org/doi/10.1148/ryai.230024" - } - ], - "github": "https://github.com/wasserth/TotalSegmentator", - "zenodo": "https://zenodo.org/record/6802342", - "colab": "https://colab.research.google.com/github/MHubAI/models/blob/colab/models/totalsegmentator/notebooks/totalsegmentator_mwe.ipynb", - "slicer": true - }, - "info": { - "use": { - "title": "Intended Use", - "text": "This model is intended to perform segmentations of 104 anatomic structures (27 organs, 59 bones, 10 muscles, 8 vessels) that are relevant for use cases such as organ volumetry, disease characterization, and surgical or radiation therapy planning. The CT images were randomly sampled from routine clinical studies, such that the dataset contains scans of patients with different ages, pathologies, of different body parts, acquired with different scanners, and sequences. The slice thickness should not exceed 1.5mm for best results." - }, - "analyses": { - "title": "Quantitative Analyses", - "text": "The model's performance was assessed using the Dice Coefficient on a held-out portion of the in-house dataset (public). For more information, please refer to the model's publication [1].", - "references": [ + "id": "3b8e2f1d-4c5a-4b2a-8f3e-6a7d9e2c1b0d", + "name": "mrsegmentator", + "title": "MRSegmentator", + "summary": { + "description": "MRSegmentator is an AI-based pipeline for the segmentation of 40 anatomical structures in MR images (with and without contrast).", + "inputs": [ { - "label": "TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images", - "uri": "https://pubs.rsna.org/doi/10.1148/ryai.230024" + "label": "Input Image", + "description": "The MR or CT scan of a patient (Thorax, Abdomen and Pelvis).", + "format": "DICOM", + "modality": "MRI|CT", + "bodypartexamined": "WHOLEBODY", + "slicethickness": "1.5 mm", + "non-contrast": true, + "contrast": true } - ] - }, - "evaluation": { - "title": "Evaluation Data", - "text": "The evaluation dataset consists of 65 CT scans of patients with different ages, presenting various pathologies, and acquired with various imaging protocols. The Nora Imaging Platform was used for manual segmentation or further refinement of generated segmentations, starting from data uniformely resampled to 1.5mm isotropic. Segmentation was supervised by two physicians with three and six years of experience in body imaging. If an existing model for a given structure was publicly available, that model was used to create a first segmentation, which was then validated and refined manually. Furthermore, the authors used an iterative learning approach to speed up the segmentation process [1][2]. The evaluation process was conducted on images resampled to 1.5mm isotropic.", - "references": [ - { - "label": "TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images", - "uri": "https://pubs.rsna.org/doi/10.1148/ryai.230024" - }, + ], + "outputs": [ { - "label": "TotalSegmentator dataset", - "uri": "https://doi.org/10.5281/zenodo.6802613" + "type": "Segmentation", + "classes": [ + "SPLEEN", + "RIGHT_KIDNEY", + "LEFT_KIDNEY", + "GALLBLADDER", + "LIVER", + "STOMACH", + "PANCREAS", + "RIGHT_ADRENAL_GLAND", + "LEFT_ADRENAL_GLAND", + "LEFT_LUNG", + "RIGHT_LUNG", + "HEART", + "AORTA", + "INFERIOR_VENA_CAVA", + "PORTAL_AND_SPLENIC_VEIN", + "LEFT_ILIAC_ARTERY", + "RIGHT_ILIAC_ARTERY", + "ESOPHAGUS", + "SMALL_INTESTINE", + "DUODENUM", + "COLON", + "URINARY_BLADDER", + "SPINE", + "SACRUM", + "LEFT_HIP", + "RIGHT_HIP", + "LEFT_FEMUR", + "RIGHT_FEMUR", + "LEFT_AUTOCHTHONOUS_BACK_MUSCLE", + "RIGHT_AUTOCHTHONOUS_BACK_MUSCLE", + "LEFT_ILIOPSOAS", + "RIGHT_ILIOPSOAS", + "LEFT_GLUTEUS_MAXIMUS", + "RIGHT_GLUTEUS_MAXIMUS", + "LEFT_GLUTEUS_MEDIUS", + "RIGHT_GLUTEUS_MEDIUS", + "LEFT_GLUTEUS_MINIMUS", + "RIGHT_GLUTEUS_MINIMUS" + ] } - ] - }, - "training": { - "title": "Training Data", - "text": "The training dataset consists of 1082 CT scans of patients with different ages, presenting various pathologies, and acquired with various imaging protocols [1][2]. All of the CT images were resampled to a common resolution of 1.5mm isotropic before training. For details regarding the labels the model was trained with, see the section above.", - "references": [ - { - "label": "TotalSegmentator: Robust Segmentation of 104 Anatomic Structures in CT Images", - "uri": "https://pubs.rsna.org/doi/10.1148/ryai.230024" + ], + "model": { + "architecture": "U-net", + "training": "supervised", + "cmpapproach": "ensemble" + }, + "data": { + "training": { + "vol_samples": 2649 + }, + "evaluation": { + "vol_samples": 960 }, + "public": true, + "external": true + } + }, + "details": { + "name": "MRSegmentator", + "version": "1.1.0", + "devteam": "AI-Assisted Healthcare Lab at Technical University Munich", + "type": "nnU-Net (U-Net structure, optimized by data-driven heuristics)", + "date": { + "weights": "05/18/24", + "code": "n/a", + "pub": "2024" + }, + "cite": "Hartmut Häntze, Lina Xu, Felix J. Dorfner, Leonhard Donle, Daniel Truhn, Hugo Aerts, Mathias Prokop, Bram van Ginneken, Alessa Hering, Lisa C. Adams, and Keno K. Bressem. MRSegmentator: Robust multi-modality segmentation of 40 classes in MRI and CT sequences. arXiv, 2024.", + "license": { + "code": "Apache 2.0", + "weights": "Apache 2.0" + }, + "publications": [ { - "label": "TotalSegmentator dataset", - "uri": "https://doi.org/10.5281/zenodo.6802613" + "title": "MRSegmentator: Robust multi-modality segmentation of 40 classes in MRI and CT sequences", + "uri": "https://arxiv.org/pdf/2405.06463" } - ] + ], + "github": "https://github.com/hhaentze/MRSegmentator", + "slicer": false + }, + "info": { + "use": { + "title": "Intended Use", + "text": "Contrary to CT scans, where tools for automatic multi-structure segmentation are quite mature, segmentation tasks in MRI scans are often either focused on the brain region or on a subset of few organs in other body regions. MRSegmentator aims to extend this and accurately segment 40 organs and structures in human MRI scans of the abdominal, pelvic and thorax regions. The segmentation works well on different sequence types, including T1- and T2-weighted, Dixon sequences and even CT images." + }, + "analyses": { + "title": "Quantitative Analyses", + "text": "The model's performance was assessed using the Dice Coefficient on three different external datasets. For more information, please refer to the model's publication [1].", + "references": [ + { + "label": "MRSegmentator: Robust multi-modality segmentation of 40 classes in MRI and CT sequences", + "uri": "https://arxiv.org/pdf/2405.06463" + } + ] + }, + "evaluation": { + "title": "Evaluation Data", + "text": "MISSING, fill this out!!!! and acquired with various imaging protocols. The Nora Imaging Platform was used for manual segmentation or further refinement of generated segmentations, starting from data uniformely resampled to 1.5mm isotropic. Segmentation was supervised by two physicians with three and six years of experience in body imaging. If an existing model for a given structure was publicly available, that model was used to create a first segmentation, which was then validated and refined manually. Furthermore, the authors used an iterative learning approach to speed up the segmentation process [1][2]. The evaluation process was conducted on images resampled to 1.5mm isotropic.", + "references": [ + { + "label": "MRSegmentator: Robust multi-modality segmentation of 40 classes in MRI and CT sequences", + "uri": "https://arxiv.org/pdf/2405.06463" + } + ] + }, + "training": { + "title": "Training Data", + "text": "Three different datasets were used for training. The in-house dataset included 221 MRI scans with T1, T2 and T1fs post contrast sequences. The UK Biobank dataset used consisted of 1200 MRI examinations acquired using IN, OPP, W, F sequences. Furthermore 1228 CT examinations from the TotalSegmentator dataset were used. For details regarding the labels the model was trained with, see the section above.", + "references": [ + { + "label": "MRSegmentator: Robust multi-modality segmentation of 40 classes in MRI and CT sequences", + "uri": "https://arxiv.org/pdf/2405.06463" + } + ] + } } } -} \ No newline at end of file From 4ac1ac447ddad84e933bfb25e04032589c57691d Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Fri, 28 Jun 2024 03:25:21 +0000 Subject: [PATCH 06/34] BUGFIX: MR data was not included in the filtering --- models/mrsegmentator/config/default.yml | 1 + models/mrsegmentator/config/low_memory.yml | 1 + models/mrsegmentator/utils/MRSegmentatorMLRunner.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/models/mrsegmentator/config/default.yml b/models/mrsegmentator/config/default.yml index e2f55ac4..6468a409 100644 --- a/models/mrsegmentator/config/default.yml +++ b/models/mrsegmentator/config/default.yml @@ -26,6 +26,7 @@ modules: body_part_examined: WHOLEBODY source_segs: nifti:mod=seg skip_empty_slices: True + target_dicom: dicom:mod=ct|mr DataOrganizer: targets: diff --git a/models/mrsegmentator/config/low_memory.yml b/models/mrsegmentator/config/low_memory.yml index 59fa7802..b0aeb72e 100644 --- a/models/mrsegmentator/config/low_memory.yml +++ b/models/mrsegmentator/config/low_memory.yml @@ -26,6 +26,7 @@ modules: body_part_examined: WHOLEBODY source_segs: nifti:mod=seg skip_empty_slices: True + target_dicom: dicom:mod=ct|mr DataOrganizer: targets: diff --git a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py index d58c060b..4b594bd1 100644 --- a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py +++ b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py @@ -25,7 +25,7 @@ class MRSegmentatorMLRunner(Module): use_fast_mode: bool @IO.Instance() - @IO.Input('in_data', 'nifti:mod=ct', the="input whole body ct scan") + @IO.Input('in_data', 'nifti:mod=ct|mr', the="input whole body mr/ct scan") @IO.Output('out_data', 'segmentations.nii.gz', 'nifti:mod=seg:model=MRSegmentator:roi=SPLEEN,RIGHT_KIDNEY,LEFT_KIDNEY,GALLBLADDER,LIVER,STOMACH,PANCREAS,RIGHT_ADRENAL_GLAND,LEFT_ADRENAL_GLAND,LEFT_LUNG,RIGHT_LUNG,HEART,AORTA,INFERIOR_VENA_CAVA,PORTAL_AND_SPLENIC_VEIN,LEFT_ILIAC_ARTERY,RIGHT_ILIAC_ARTERY,ESOPHAGUS,SMALL_INTESTINE,DUODENUM,COLON,URINARY_BLADDER,SPINE,SACRUM,LEFT_HIP,RIGHT_HIP,LEFT_FEMUR,RIGHT_FEMUR,LEFT_AUTOCHTHONOUS_BACK_MUSCLE,RIGHT_AUTOCHTHONOUS_BACK_MUSCLE,LEFT_ILIOPSOAS,RIGHT_ILIOPSOAS,LEFT_GLUTEUS_MAXIMUS,RIGHT_GLUTEUS_MAXIMUS,LEFT_GLUTEUS_MEDIUS,RIGHT_GLUTEUS_MEDIUS,LEFT_GLUTEUS_MINIMUS,RIGHT_GLUTEUS_MINIMUS', data='in_data', the="output segmentation mask containing all labels") def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData) -> None: From 0fd58f049d332d33b7660ae906c93bb07064cfb5 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Thu, 4 Jul 2024 22:09:24 +0000 Subject: [PATCH 07/34] Updated to the Metadata file --- models/mrsegmentator/meta.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/models/mrsegmentator/meta.json b/models/mrsegmentator/meta.json index a6118636..94b987c3 100644 --- a/models/mrsegmentator/meta.json +++ b/models/mrsegmentator/meta.json @@ -11,7 +11,6 @@ "format": "DICOM", "modality": "MRI|CT", "bodypartexamined": "WHOLEBODY", - "slicethickness": "1.5 mm", "non-contrast": true, "contrast": true } @@ -80,7 +79,7 @@ "details": { "name": "MRSegmentator", "version": "1.1.0", - "devteam": "AI-Assisted Healthcare Lab at Technical University Munich", + "devteam": "AI-Assisted Healthcare Lab at Technical University Munich and Charité Universitätsmedizin Berlin", "type": "nnU-Net (U-Net structure, optimized by data-driven heuristics)", "date": { "weights": "05/18/24", @@ -118,7 +117,7 @@ }, "evaluation": { "title": "Evaluation Data", - "text": "MISSING, fill this out!!!! and acquired with various imaging protocols. The Nora Imaging Platform was used for manual segmentation or further refinement of generated segmentations, starting from data uniformely resampled to 1.5mm isotropic. Segmentation was supervised by two physicians with three and six years of experience in body imaging. If an existing model for a given structure was publicly available, that model was used to create a first segmentation, which was then validated and refined manually. Furthermore, the authors used an iterative learning approach to speed up the segmentation process [1][2]. The evaluation process was conducted on images resampled to 1.5mm isotropic.", + "text": "The model was evaluated on test data from three different dataset. The NAKO dataset included 600 MRI examinationsm, the AMOS MRI dataset included 60 MRI examinations and the AMOS CT dataset which included a total of 300 CT examinations.", "references": [ { "label": "MRSegmentator: Robust multi-modality segmentation of 40 classes in MRI and CT sequences", @@ -128,7 +127,7 @@ }, "training": { "title": "Training Data", - "text": "Three different datasets were used for training. The in-house dataset included 221 MRI scans with T1, T2 and T1fs post contrast sequences. The UK Biobank dataset used consisted of 1200 MRI examinations acquired using IN, OPP, W, F sequences. Furthermore 1228 CT examinations from the TotalSegmentator dataset were used. For details regarding the labels the model was trained with, see the section above.", + "text": "Three different datasets were used for training. The in-house dataset included 221 MRI scans with T1, T2 and T1fs post contrast sequences. The UK Biobank dataset used consisted of 1200 MRI examinations acquired using IN, OPP, W, F sequences. Furthermore 1228 CT examinations from the TotalSegmentator dataset were used. All segmentations were performed by a radiologist, using a human-in-the-loop annotation approach to efficiently create high-quality segmentations for the training data.", "references": [ { "label": "MRSegmentator: Robust multi-modality segmentation of 40 classes in MRI and CT sequences", From 0e0b8d88a1074c2919498433b55dcefcde52a20a Mon Sep 17 00:00:00 2001 From: FJDorfner <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 4 Jul 2024 19:26:12 -0400 Subject: [PATCH 08/34] Update meta.json --- models/mrsegmentator/meta.json | 1 + 1 file changed, 1 insertion(+) diff --git a/models/mrsegmentator/meta.json b/models/mrsegmentator/meta.json index 94b987c3..52f22c47 100644 --- a/models/mrsegmentator/meta.json +++ b/models/mrsegmentator/meta.json @@ -11,6 +11,7 @@ "format": "DICOM", "modality": "MRI|CT", "bodypartexamined": "WHOLEBODY", + "slicethickness": "n/a", "non-contrast": true, "contrast": true } From f0f577492f22de72d43b5901d8b9c2ecb54f519c Mon Sep 17 00:00:00 2001 From: FJDorfner <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 4 Jul 2024 19:30:46 -0400 Subject: [PATCH 09/34] Update Dockerfile --- models/mrsegmentator/dockerfiles/Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 9ca5c6c4..e2ecd221 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -4,6 +4,10 @@ FROM mhubai/base:latest RUN apt-get update && apt-get install -y \ python3.9 \ python3-pip + +# clone mhub implementation +ARG MHUB_MODELS_REPO +RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} # Install MRSegmentator RUN python3.9 -m pip install --no-cache-dir mrsegmentator @@ -15,4 +19,4 @@ RUN rm .temp_image.nii.gz # Default run script ENTRYPOINT ["python3", "-m", "mhubio.run"] -CMD ["--config", "/app/models/mrsegmentator/config/default.yml"] \ No newline at end of file +CMD ["--config", "/app/models/mrsegmentator/config/default.yml"] From 28ef8275475f989fb9479ccbca8490cde189a54b Mon Sep 17 00:00:00 2001 From: FJDorfner <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 18 Jul 2024 18:52:47 -0400 Subject: [PATCH 10/34] Removed logging from default.yml --- models/mrsegmentator/config/default.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/models/mrsegmentator/config/default.yml b/models/mrsegmentator/config/default.yml index 6468a409..7a014d56 100644 --- a/models/mrsegmentator/config/default.yml +++ b/models/mrsegmentator/config/default.yml @@ -31,4 +31,3 @@ modules: DataOrganizer: targets: - dicomseg:mod=seg-->[i:sid]//MRSegmentator.seg.dcm - - log-->[i:sid]/logs/[d:module]/[filename] From 7b257b808e5ad477218b5bd050659cefd85c4d0a Mon Sep 17 00:00:00 2001 From: FJDorfner <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 18 Jul 2024 18:53:38 -0400 Subject: [PATCH 11/34] Remove Logging and rename low_memory.yml to fast.yml --- models/mrsegmentator/config/{low_memory.yml => fast.yml} | 1 - 1 file changed, 1 deletion(-) rename models/mrsegmentator/config/{low_memory.yml => fast.yml} (93%) diff --git a/models/mrsegmentator/config/low_memory.yml b/models/mrsegmentator/config/fast.yml similarity index 93% rename from models/mrsegmentator/config/low_memory.yml rename to models/mrsegmentator/config/fast.yml index b0aeb72e..c6643b81 100644 --- a/models/mrsegmentator/config/low_memory.yml +++ b/models/mrsegmentator/config/fast.yml @@ -31,4 +31,3 @@ modules: DataOrganizer: targets: - dicomseg:mod=seg-->[i:sid]//MRSegmentator.seg.dcm - - log-->[i:sid]/logs/[d:module]/[filename] From 0081d97cde7b5da33794f13dd5d7d2a8d55f5942 Mon Sep 17 00:00:00 2001 From: FJDorfner <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 18 Jul 2024 18:54:16 -0400 Subject: [PATCH 12/34] Update Code Date meta.json --- models/mrsegmentator/meta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/meta.json b/models/mrsegmentator/meta.json index 52f22c47..85ba808a 100644 --- a/models/mrsegmentator/meta.json +++ b/models/mrsegmentator/meta.json @@ -84,7 +84,7 @@ "type": "nnU-Net (U-Net structure, optimized by data-driven heuristics)", "date": { "weights": "05/18/24", - "code": "n/a", + "code": "05/18/24", "pub": "2024" }, "cite": "Hartmut Häntze, Lina Xu, Felix J. Dorfner, Leonhard Donle, Daniel Truhn, Hugo Aerts, Mathias Prokop, Bram van Ginneken, Alessa Hering, Lisa C. Adams, and Keno K. Bressem. MRSegmentator: Robust multi-modality segmentation of 40 classes in MRI and CT sequences. arXiv, 2024.", From 6141cf7559d6199dadaee934a2c393b633af8b20 Mon Sep 17 00:00:00 2001 From: FJDorfner <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 18 Jul 2024 18:57:43 -0400 Subject: [PATCH 13/34] Update default.yml to remove / from DataOrganizer --- models/mrsegmentator/config/default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/config/default.yml b/models/mrsegmentator/config/default.yml index 7a014d56..90b8dd70 100644 --- a/models/mrsegmentator/config/default.yml +++ b/models/mrsegmentator/config/default.yml @@ -30,4 +30,4 @@ modules: DataOrganizer: targets: - - dicomseg:mod=seg-->[i:sid]//MRSegmentator.seg.dcm + - dicomseg:mod=seg-->[i:sid]/MRSegmentator.seg.dcm From 46c911ab01b7a16de505167e2cf44ce1ce13f3ca Mon Sep 17 00:00:00 2001 From: FJDorfner <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 18 Jul 2024 18:57:57 -0400 Subject: [PATCH 14/34] Update fast.yml to remove / from DataOrganizer --- models/mrsegmentator/config/fast.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/config/fast.yml b/models/mrsegmentator/config/fast.yml index c6643b81..9b1c94c9 100644 --- a/models/mrsegmentator/config/fast.yml +++ b/models/mrsegmentator/config/fast.yml @@ -30,4 +30,4 @@ modules: DataOrganizer: targets: - - dicomseg:mod=seg-->[i:sid]//MRSegmentator.seg.dcm + - dicomseg:mod=seg-->[i:sid]/MRSegmentator.seg.dcm From dd9a8e0faf1613b2d7ccc0f454363c2f8c8408c5 Mon Sep 17 00:00:00 2001 From: FJDorfner <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 18 Jul 2024 19:15:01 -0400 Subject: [PATCH 15/34] Implement robuster way for findings the output segmentation file in the temp dir --- .../utils/MRSegmentatorMLRunner.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py index 4b594bd1..62662e36 100644 --- a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py +++ b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py @@ -30,19 +30,11 @@ class MRSegmentatorMLRunner(Module): def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData) -> None: tmp_dir = self.config.data.requestTempDir("mr_segmentator") - - raw_filename = os.path.basename(in_data.abspath) - name_part = raw_filename.split('.nii')[0] - extension = '.nii.gz' - - new_filename = f"{name_part}_seg{extension}" - + bash_command = ["mrsegmentator"] bash_command += ["-i", in_data.abspath] - bash_command += ["--outdir", tmp_dir] - if self.use_fast_mode: self.v("Running MRSegmentator in lower memory footprint mode ('--split_level', 1)") self.v("Note: This increases runtime and possibly reduces segmentation performance.") @@ -50,11 +42,20 @@ def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData else: self.v("Running MRSegmentator in default mode.") - self.v(">> run: ", " ".join(bash_command)) # run the model self.subprocess(bash_command, text=True) + # Find the output file in the temporary directory + output_file = None + for filename in os.listdir(tmp_dir): + if filename.endswith('.nii.gz'): + output_file = filename + break + + if output_file is None: + raise FileNotFoundError("No output segmentation files found in the temporary directory.") + # copy data - shutil.copy(os.path.join(tmp_dir, new_filename), out_data.abspath) \ No newline at end of file + shutil.copy(os.path.join(tmp_dir, output_file), out_data.abspath) From 5600ff3dbe6e0f2c426448719852b90bc7ad030c Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Sun, 25 Aug 2024 21:33:22 +0000 Subject: [PATCH 16/34] updated mrsegmentator version to 1.2 --- models/mrsegmentator/dockerfiles/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index e2ecd221..74f1221b 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -10,7 +10,7 @@ ARG MHUB_MODELS_REPO RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} # Install MRSegmentator -RUN python3.9 -m pip install --no-cache-dir mrsegmentator +RUN python3.9 -m pip install --no-cache-dir mrsegmentator==1.2 # Execute mrsegmentator once to download the weights, this will fail to run but download regardless RUN touch .temp_image.nii.gz From 6ba6f927d14992af1b2e5b3251159cc658e151f5 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 10:50:05 +0000 Subject: [PATCH 17/34] updated dockerfile to include new entrypoint --- models/mrsegmentator/dockerfiles/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 74f1221b..71946238 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -19,4 +19,4 @@ RUN rm .temp_image.nii.gz # Default run script ENTRYPOINT ["python3", "-m", "mhubio.run"] -CMD ["--config", "/app/models/mrsegmentator/config/default.yml"] +CMD ["--workflow", "default"] \ No newline at end of file From 6de808004121514030ac635cc63e0935b19ea095 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 10:55:17 +0000 Subject: [PATCH 18/34] update dockerfile for newest mrsegmentator version --- models/mrsegmentator/dockerfiles/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 71946238..9399a9bd 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -1,8 +1,8 @@ FROM mhubai/base:latest -# Update Python, nnUNet needs Python 3.9 +# Update Python, nnUNet needs Python >= 3.9 RUN apt-get update && apt-get install -y \ - python3.9 \ + python3.11 \ python3-pip # clone mhub implementation @@ -10,7 +10,7 @@ ARG MHUB_MODELS_REPO RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} # Install MRSegmentator -RUN python3.9 -m pip install --no-cache-dir mrsegmentator==1.2 +RUN python3.11 -m pip install --no-cache-dir mrsegmentator # Execute mrsegmentator once to download the weights, this will fail to run but download regardless RUN touch .temp_image.nii.gz From 44c719a6c8aff383c26956a2474c8c2267b6fd74 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 12:35:53 +0000 Subject: [PATCH 19/34] update dockerfile --- models/mrsegmentator/dockerfiles/Dockerfile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 9399a9bd..940c44ba 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -1,16 +1,17 @@ FROM mhubai/base:latest # Update Python, nnUNet needs Python >= 3.9 -RUN apt-get update && apt-get install -y \ - python3.11 \ - python3-pip +#RUN apt-get update && apt-get install -y \ +# python3.11 \ +# python3-pip # clone mhub implementation ARG MHUB_MODELS_REPO RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} # Install MRSegmentator -RUN python3.11 -m pip install --no-cache-dir mrsegmentator +RUN uv venv -p 3.11 .venv +RUN uv pip install -p .venv mrsegmentator # Execute mrsegmentator once to download the weights, this will fail to run but download regardless RUN touch .temp_image.nii.gz From 4d06795e1e7bb475502081da94f4569f6172d3eb Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 13:06:09 +0000 Subject: [PATCH 20/34] update dockerfile to properly use venv --- models/mrsegmentator/dockerfiles/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 940c44ba..31d41857 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -19,5 +19,5 @@ RUN mrsegmentator -i .temp_image.nii.gz; exit 0 RUN rm .temp_image.nii.gz # Default run script -ENTRYPOINT ["python3", "-m", "mhubio.run"] +ENTRYPOINT [".venv/bin/python3", "-m", "mhubio.run"] CMD ["--workflow", "default"] \ No newline at end of file From fb1b01f736493bf0cd04bf8a9dc321af697c1710 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 13:10:44 +0000 Subject: [PATCH 21/34] fixed the dockerfile again --- models/mrsegmentator/dockerfiles/Dockerfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 31d41857..98b74ee5 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -10,8 +10,9 @@ ARG MHUB_MODELS_REPO RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} # Install MRSegmentator -RUN uv venv -p 3.11 .venv -RUN uv pip install -p .venv mrsegmentator +RUN uv venv -p 3.11 /app/.venv +ENV PATH="/app/.venv/bin:$PATH" +RUN uv pip install -p /app/.venv mrsegmentator # Execute mrsegmentator once to download the weights, this will fail to run but download regardless RUN touch .temp_image.nii.gz @@ -19,5 +20,5 @@ RUN mrsegmentator -i .temp_image.nii.gz; exit 0 RUN rm .temp_image.nii.gz # Default run script -ENTRYPOINT [".venv/bin/python3", "-m", "mhubio.run"] +ENTRYPOINT ["/app/.venv/bin/python3", "-m", "mhubio.run"] CMD ["--workflow", "default"] \ No newline at end of file From e28d034eeb5254efc80ae4bd07c9bd1ec0661276 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 13:22:08 +0000 Subject: [PATCH 22/34] some more dockerfile stuff --- models/mrsegmentator/dockerfiles/Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 98b74ee5..6eab038b 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -10,8 +10,6 @@ ARG MHUB_MODELS_REPO RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} # Install MRSegmentator -RUN uv venv -p 3.11 /app/.venv -ENV PATH="/app/.venv/bin:$PATH" RUN uv pip install -p /app/.venv mrsegmentator # Execute mrsegmentator once to download the weights, this will fail to run but download regardless From 8f3fb21ddde6fbfeddddfb85179b6d5001694a97 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 13:26:24 +0000 Subject: [PATCH 23/34] updated dockerfile again --- models/mrsegmentator/dockerfiles/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 6eab038b..e3e0f615 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -18,5 +18,5 @@ RUN mrsegmentator -i .temp_image.nii.gz; exit 0 RUN rm .temp_image.nii.gz # Default run script -ENTRYPOINT ["/app/.venv/bin/python3", "-m", "mhubio.run"] -CMD ["--workflow", "default"] \ No newline at end of file +ENTRYPOINT ["mhub.run"] +CMD ["--config", "/app/models/mrsegmentator/config/default.yml"] \ No newline at end of file From 2728f086af85b2365fad2d61c7956a5ff8917ffc Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 13:56:36 +0000 Subject: [PATCH 24/34] new try --- models/mrsegmentator/dockerfiles/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index e3e0f615..e6f0e05a 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -18,5 +18,5 @@ RUN mrsegmentator -i .temp_image.nii.gz; exit 0 RUN rm .temp_image.nii.gz # Default run script -ENTRYPOINT ["mhub.run"] +ENTRYPOINT ["/app/.venv/bin/python", "-m", "mhub.run"] CMD ["--config", "/app/models/mrsegmentator/config/default.yml"] \ No newline at end of file From ddce17d0428dcdb6d147f3a18d43aaf183e102fd Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 14:00:55 +0000 Subject: [PATCH 25/34] update dockerfile --- models/mrsegmentator/dockerfiles/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index e6f0e05a..e3e0f615 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -18,5 +18,5 @@ RUN mrsegmentator -i .temp_image.nii.gz; exit 0 RUN rm .temp_image.nii.gz # Default run script -ENTRYPOINT ["/app/.venv/bin/python", "-m", "mhub.run"] +ENTRYPOINT ["mhub.run"] CMD ["--config", "/app/models/mrsegmentator/config/default.yml"] \ No newline at end of file From 4723e849914476e197de7e498f4bc81cfab760ec Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 15:19:22 +0000 Subject: [PATCH 26/34] switch to uv run --- models/mrsegmentator/dockerfiles/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index e3e0f615..17257590 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -10,11 +10,11 @@ ARG MHUB_MODELS_REPO RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} # Install MRSegmentator -RUN uv pip install -p /app/.venv mrsegmentator +RUN uv pip install mrsegmentator # Execute mrsegmentator once to download the weights, this will fail to run but download regardless RUN touch .temp_image.nii.gz -RUN mrsegmentator -i .temp_image.nii.gz; exit 0 +RUN uv run mrsegmentator -i .temp_image.nii.gz; exit 0 RUN rm .temp_image.nii.gz # Default run script From 5c068b05fcfdcc88566cd168fde6ed1caf6411af Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 15:43:50 +0000 Subject: [PATCH 27/34] updated install command --- models/mrsegmentator/dockerfiles/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index 17257590..e37e8a25 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -10,7 +10,7 @@ ARG MHUB_MODELS_REPO RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} # Install MRSegmentator -RUN uv pip install mrsegmentator +RUN uv pip install mrsegmentator blosc2 acvl-utils==0.2 # Execute mrsegmentator once to download the weights, this will fail to run but download regardless RUN touch .temp_image.nii.gz From f3e51dcb7c01b26e84e67c59027cda8d3726a81f Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Wed, 27 Nov 2024 16:30:05 +0000 Subject: [PATCH 28/34] Final edit to the dockerfile --- models/mrsegmentator/dockerfiles/Dockerfile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/models/mrsegmentator/dockerfiles/Dockerfile b/models/mrsegmentator/dockerfiles/Dockerfile index e37e8a25..dba82729 100644 --- a/models/mrsegmentator/dockerfiles/Dockerfile +++ b/models/mrsegmentator/dockerfiles/Dockerfile @@ -1,10 +1,5 @@ FROM mhubai/base:latest -# Update Python, nnUNet needs Python >= 3.9 -#RUN apt-get update && apt-get install -y \ -# python3.11 \ -# python3-pip - # clone mhub implementation ARG MHUB_MODELS_REPO RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} From e3aa7ce5af56f169cb951029eada333c4339b0e9 Mon Sep 17 00:00:00 2001 From: "Felix J. Dorfner" <122161540+FJDorfner@users.noreply.github.com> Date: Thu, 28 Nov 2024 09:40:31 -0500 Subject: [PATCH 29/34] Create mhub.toml --- models/mrsegmentator/mhub.toml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 models/mrsegmentator/mhub.toml diff --git a/models/mrsegmentator/mhub.toml b/models/mrsegmentator/mhub.toml new file mode 100644 index 00000000..1e08affe --- /dev/null +++ b/models/mrsegmentator/mhub.toml @@ -0,0 +1,2 @@ +[model.deployment] +test = "https://zenodo.org/records/14236786/files/mrsegmentator.test.zip" From 0728bb20f1d97d7f35fff0eabd6188c39161e6a0 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Fri, 29 Nov 2024 13:12:45 +0000 Subject: [PATCH 30/34] Set nproc to 1 --- models/mrsegmentator/utils/MRSegmentatorMLRunner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py index 62662e36..fc339e1b 100644 --- a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py +++ b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py @@ -34,6 +34,7 @@ def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData bash_command = ["mrsegmentator"] bash_command += ["-i", in_data.abspath] bash_command += ["--outdir", tmp_dir] + bash_command += ["--nproc", "1"] if self.use_fast_mode: self.v("Running MRSegmentator in lower memory footprint mode ('--split_level', 1)") From fc17471f24c410cecab131e78db7b077384e6605 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Fri, 29 Nov 2024 14:12:51 +0000 Subject: [PATCH 31/34] changed number of export processes --- models/mrsegmentator/utils/MRSegmentatorMLRunner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py index fc339e1b..dc9f4ffa 100644 --- a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py +++ b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py @@ -34,7 +34,7 @@ def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData bash_command = ["mrsegmentator"] bash_command += ["-i", in_data.abspath] bash_command += ["--outdir", tmp_dir] - bash_command += ["--nproc", "1"] + bash_command += ["--nproc_export", "4"] if self.use_fast_mode: self.v("Running MRSegmentator in lower memory footprint mode ('--split_level', 1)") From 8ef89807e6bbec75befe678137f2dabd43fe3e11 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Fri, 29 Nov 2024 14:23:47 +0000 Subject: [PATCH 32/34] created minimal memory use example --- models/mrsegmentator/utils/MRSegmentatorMLRunner.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py index dc9f4ffa..1d068fba 100644 --- a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py +++ b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py @@ -34,7 +34,9 @@ def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData bash_command = ["mrsegmentator"] bash_command += ["-i", in_data.abspath] bash_command += ["--outdir", tmp_dir] - bash_command += ["--nproc_export", "4"] + bash_command += ["--nproc_export", "1"] + bash_command += ["--nproc", "1"] + bash_command += ["--batchsize", "1"] if self.use_fast_mode: self.v("Running MRSegmentator in lower memory footprint mode ('--split_level', 1)") From 290c7fdfecb5dac8864f8b0185f32f8a9707aa91 Mon Sep 17 00:00:00 2001 From: FJDorfner Date: Tue, 3 Dec 2024 12:16:25 +0000 Subject: [PATCH 33/34] set split_level as the default configuration and removed fast configuration --- models/mrsegmentator/config/default.yml | 1 - models/mrsegmentator/config/fast.yml | 33 ------------------- .../utils/MRSegmentatorMLRunner.py | 14 +------- 3 files changed, 1 insertion(+), 47 deletions(-) delete mode 100644 models/mrsegmentator/config/fast.yml diff --git a/models/mrsegmentator/config/default.yml b/models/mrsegmentator/config/default.yml index 90b8dd70..da15d1d8 100644 --- a/models/mrsegmentator/config/default.yml +++ b/models/mrsegmentator/config/default.yml @@ -19,7 +19,6 @@ modules: mod: '%Modality' MRSegmentatorMLRunner: - use_fast_mode: false DsegConverter: model_name: MRSegmentator diff --git a/models/mrsegmentator/config/fast.yml b/models/mrsegmentator/config/fast.yml deleted file mode 100644 index 9b1c94c9..00000000 --- a/models/mrsegmentator/config/fast.yml +++ /dev/null @@ -1,33 +0,0 @@ -general: - data_base_dir: /app/data - version: 1.0.0 - description: MRSegmentator default lower memory footprint config (dicom to dicom) - -execute: -- DicomImporter -- NiftiConverter -- MRSegmentatorMLRunner -- DsegConverter -- DataOrganizer - -modules: - DicomImporter: - source_dir: input_data - import_dir: sorted_data - sort_data: true - meta: - mod: '%Modality' - - MRSegmentatorMLRunner: - use_fast_mode: true - - DsegConverter: - model_name: MRSegmentator - body_part_examined: WHOLEBODY - source_segs: nifti:mod=seg - skip_empty_slices: True - target_dicom: dicom:mod=ct|mr - - DataOrganizer: - targets: - - dicomseg:mod=seg-->[i:sid]/MRSegmentator.seg.dcm diff --git a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py index 1d068fba..0ed014e7 100644 --- a/models/mrsegmentator/utils/MRSegmentatorMLRunner.py +++ b/models/mrsegmentator/utils/MRSegmentatorMLRunner.py @@ -19,11 +19,8 @@ # register custom segmentation before class definition Segment.register("SPINE", name="Spine") -@IO.Config('use_fast_mode', bool, False, the="flag to set to run MRSegmentator in a faster mode") class MRSegmentatorMLRunner(Module): - use_fast_mode: bool - @IO.Instance() @IO.Input('in_data', 'nifti:mod=ct|mr', the="input whole body mr/ct scan") @IO.Output('out_data', 'segmentations.nii.gz', 'nifti:mod=seg:model=MRSegmentator:roi=SPLEEN,RIGHT_KIDNEY,LEFT_KIDNEY,GALLBLADDER,LIVER,STOMACH,PANCREAS,RIGHT_ADRENAL_GLAND,LEFT_ADRENAL_GLAND,LEFT_LUNG,RIGHT_LUNG,HEART,AORTA,INFERIOR_VENA_CAVA,PORTAL_AND_SPLENIC_VEIN,LEFT_ILIAC_ARTERY,RIGHT_ILIAC_ARTERY,ESOPHAGUS,SMALL_INTESTINE,DUODENUM,COLON,URINARY_BLADDER,SPINE,SACRUM,LEFT_HIP,RIGHT_HIP,LEFT_FEMUR,RIGHT_FEMUR,LEFT_AUTOCHTHONOUS_BACK_MUSCLE,RIGHT_AUTOCHTHONOUS_BACK_MUSCLE,LEFT_ILIOPSOAS,RIGHT_ILIOPSOAS,LEFT_GLUTEUS_MAXIMUS,RIGHT_GLUTEUS_MAXIMUS,LEFT_GLUTEUS_MEDIUS,RIGHT_GLUTEUS_MEDIUS,LEFT_GLUTEUS_MINIMUS,RIGHT_GLUTEUS_MINIMUS', data='in_data', the="output segmentation mask containing all labels") @@ -34,16 +31,7 @@ def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData bash_command = ["mrsegmentator"] bash_command += ["-i", in_data.abspath] bash_command += ["--outdir", tmp_dir] - bash_command += ["--nproc_export", "1"] - bash_command += ["--nproc", "1"] - bash_command += ["--batchsize", "1"] - - if self.use_fast_mode: - self.v("Running MRSegmentator in lower memory footprint mode ('--split_level', 1)") - self.v("Note: This increases runtime and possibly reduces segmentation performance.") - bash_command += ["--split_level", "1"] - else: - self.v("Running MRSegmentator in default mode.") + bash_command += ["--split_level", "1"] self.v(">> run: ", " ".join(bash_command)) From a5eb12c58c33b2668a7249510a89ad2fdc62b206 Mon Sep 17 00:00:00 2001 From: "Felix J. Dorfner" <122161540+FJDorfner@users.noreply.github.com> Date: Tue, 3 Dec 2024 07:38:27 -0500 Subject: [PATCH 34/34] Update mhub.toml --- models/mrsegmentator/mhub.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/mrsegmentator/mhub.toml b/models/mrsegmentator/mhub.toml index 1e08affe..8377c5a2 100644 --- a/models/mrsegmentator/mhub.toml +++ b/models/mrsegmentator/mhub.toml @@ -1,2 +1,2 @@ [model.deployment] -test = "https://zenodo.org/records/14236786/files/mrsegmentator.test.zip" +test = "https://zenodo.org/records/14266540/files/mrsegmentator.test.zip"