-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PW41] Add MRSegmentator Model #90
base: main
Are you sure you want to change the base?
Changes from all commits
bddcbba
910d727
85fb186
b7944e8
9f65218
4ac1ac4
0fd58f0
0e0b8d8
f0f5774
28ef827
7b257b8
0081d97
6141cf7
46c911a
dd9a8e0
5600ff3
7861529
6ba6f92
6de8080
44c719a
4d06795
fb1b01f
e28d034
8f3fb21
2728f08
ddce17d
4723e84
5c068b0
f3e51dc
e3aa7ce
0728bb2
fc17471
8ef8980
290c7fd
a5eb12c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# 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/mrsegmentator](https://mhub.ai/models/mrsegmentator) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .utils import * |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
general: | ||
data_base_dir: /app/data | ||
version: 1.0.0 | ||
description: MRSegmentator default 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: | ||
|
||
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
FROM mhubai/base:latest | ||
|
||
# clone mhub implementation | ||
ARG MHUB_MODELS_REPO | ||
RUN buildutils/import_mhub_model.sh mrsegmentator ${MHUB_MODELS_REPO} | ||
|
||
# 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 | ||
RUN uv run mrsegmentator -i .temp_image.nii.gz; exit 0 | ||
RUN rm .temp_image.nii.gz | ||
|
||
# Default run script | ||
ENTRYPOINT ["mhub.run"] | ||
CMD ["--config", "/app/models/mrsegmentator/config/default.yml"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
{ | ||
"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": "Input Image", | ||
"description": "The MR or CT scan of a patient (Thorax, Abdomen and Pelvis).", | ||
"format": "DICOM", | ||
"modality": "MRI|CT", | ||
"bodypartexamined": "WHOLEBODY", | ||
"slicethickness": "n/a", | ||
"non-contrast": true, | ||
"contrast": true | ||
} | ||
], | ||
"outputs": [ | ||
{ | ||
"type": "Segmentation", | ||
"classes": [ | ||
"SPLEEN", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @FJDorfner We're adding a quite broad label here, can you explain weather the model delineates the entire spine or the bone-structure of the spine? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @LennyN95, the model segments the bodies of the vertebrae individually. The disk between is not included in the label. This would be the yellow label in the attached Screenshot as a visual:) |
||
"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": 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 and Charité Universitätsmedizin Berlin", | ||
"type": "nnU-Net (U-Net structure, optimized by data-driven heuristics)", | ||
"date": { | ||
"weights": "05/18/24", | ||
"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.", | ||
"license": { | ||
"code": "Apache 2.0", | ||
"weights": "Apache 2.0" | ||
}, | ||
"publications": [ | ||
{ | ||
"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": "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", | ||
"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. 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", | ||
"uri": "https://arxiv.org/pdf/2405.06463" | ||
} | ||
] | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[model.deployment] | ||
test = "https://zenodo.org/records/14266540/files/mrsegmentator.test.zip" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
""" | ||
------------------------------------------------- | ||
MHub - Run Module for MRSegmentator. | ||
------------------------------------------------- | ||
|
||
------------------------------------------------- | ||
Author: Felix Dorfner | ||
Email: [email protected] | ||
------------------------------------------------- | ||
""" | ||
|
||
from mhubio.core import Module, Instance, InstanceData, DataType, FileType, CT, SEG, IO, DataTypeQuery | ||
import os, subprocess | ||
from segdb.classes.Segment import Segment | ||
import shutil | ||
|
||
|
||
|
||
# register custom segmentation before class definition | ||
Segment.register("SPINE", name="Spine") | ||
|
||
class MRSegmentatorMLRunner(Module): | ||
|
||
@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") | ||
def task(self, instance: Instance, in_data: InstanceData, out_data: InstanceData) -> None: | ||
|
||
tmp_dir = self.config.data.requestTempDir("mr_segmentator") | ||
|
||
bash_command = ["mrsegmentator"] | ||
bash_command += ["-i", in_data.abspath] | ||
bash_command += ["--outdir", tmp_dir] | ||
bash_command += ["--split_level", "1"] | ||
|
||
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, output_file), out_data.abspath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.