Skip to content
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

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
bddcbba
added first files, duplicated from the totalsegmentator implementation
FJDorfner Jun 25, 2024
910d727
Added different Configurations and finalized scripts
FJDorfner Jun 26, 2024
85fb186
Removed empty tmp image
FJDorfner Jun 26, 2024
b7944e8
Updated Readme
FJDorfner Jun 26, 2024
9f65218
Update meta.json
FJDorfner Jun 27, 2024
4ac1ac4
BUGFIX: MR data was not included in the filtering
FJDorfner Jun 28, 2024
0fd58f0
Updated to the Metadata file
FJDorfner Jul 4, 2024
0e0b8d8
Update meta.json
FJDorfner Jul 4, 2024
f0f5774
Update Dockerfile
FJDorfner Jul 4, 2024
28ef827
Removed logging from default.yml
FJDorfner Jul 18, 2024
7b257b8
Remove Logging and rename low_memory.yml to fast.yml
FJDorfner Jul 18, 2024
0081d97
Update Code Date meta.json
FJDorfner Jul 18, 2024
6141cf7
Update default.yml to remove / from DataOrganizer
FJDorfner Jul 18, 2024
46c911a
Update fast.yml to remove / from DataOrganizer
FJDorfner Jul 18, 2024
dd9a8e0
Implement robuster way for findings the output segmentation file in t…
FJDorfner Jul 18, 2024
5600ff3
updated mrsegmentator version to 1.2
FJDorfner Aug 25, 2024
7861529
Merge branch 'main' into MRSegmentator
FJDorfner Nov 27, 2024
6ba6f92
updated dockerfile to include new entrypoint
FJDorfner Nov 27, 2024
6de8080
update dockerfile for newest mrsegmentator version
FJDorfner Nov 27, 2024
44c719a
update dockerfile
FJDorfner Nov 27, 2024
4d06795
update dockerfile to properly use venv
FJDorfner Nov 27, 2024
fb1b01f
fixed the dockerfile again
FJDorfner Nov 27, 2024
e28d034
some more dockerfile stuff
FJDorfner Nov 27, 2024
8f3fb21
updated dockerfile again
FJDorfner Nov 27, 2024
2728f08
new try
FJDorfner Nov 27, 2024
ddce17d
update dockerfile
FJDorfner Nov 27, 2024
4723e84
switch to uv run
FJDorfner Nov 27, 2024
5c068b0
updated install command
FJDorfner Nov 27, 2024
f3e51dc
Final edit to the dockerfile
FJDorfner Nov 27, 2024
e3aa7ce
Create mhub.toml
FJDorfner Nov 28, 2024
0728bb2
Set nproc to 1
FJDorfner Nov 29, 2024
fc17471
changed number of export processes
FJDorfner Nov 29, 2024
8ef8980
created minimal memory use example
FJDorfner Nov 29, 2024
290c7fd
set split_level as the default configuration and removed fast configu…
FJDorfner Dec 3, 2024
a5eb12c
Update mhub.toml
FJDorfner Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions models/mrsegmentator/README.md
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)
1 change: 1 addition & 0 deletions models/mrsegmentator/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .utils import *
34 changes: 34 additions & 0 deletions models/mrsegmentator/config/default.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
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:
use_fast_mode: false

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
LennyN95 marked this conversation as resolved.
Show resolved Hide resolved
- log-->[i:sid]/logs/[d:module]/[filename]
LennyN95 marked this conversation as resolved.
Show resolved Hide resolved
34 changes: 34 additions & 0 deletions models/mrsegmentator/config/low_memory.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
general:
LennyN95 marked this conversation as resolved.
Show resolved Hide resolved
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:
LennyN95 marked this conversation as resolved.
Show resolved Hide resolved
- dicomseg:mod=seg-->[i:sid]//MRSegmentator.seg.dcm
- log-->[i:sid]/logs/[d:module]/[filename]
22 changes: 22 additions & 0 deletions models/mrsegmentator/dockerfiles/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM mhubai/base:latest

# Update Python, nnUNet needs Python 3.9
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

# 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be the issue? I am not sure if mrsegmentator is available, try uv run mrsegmentator if it's installed in the .venv.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this would be the issue, these lines seem to run fine when building the container, and there is no error message produced. The problem mainly is that the dicomsort module does not seem to find any data. I will still revise and use uv run mrsegmentator.


# Default run script
ENTRYPOINT ["python3", "-m", "mhubio.run"]
CMD ["--config", "/app/models/mrsegmentator/config/default.yml"]
140 changes: 140 additions & 0 deletions models/mrsegmentator/meta.json
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",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • TODO @LennyN95: Add support for multi-modality inputs. Dash separation is a good idea and in line with DTQ syntax.

"bodypartexamined": "WHOLEBODY",
"slicethickness": "n/a",
"non-contrast": true,
"contrast": true
}
],
"outputs": [
{
"type": "Segmentation",
"classes": [
"SPLEEN",
Copy link
Member

@LennyN95 LennyN95 Jul 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add SPINE to SegDB. I can lookup the codes, but feel free to add SCT code's if you already have them ;))

Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Author

Choose a reason for hiding this comment

The 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:)

Screenshot 2024-07-24 at 10 24 47

"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": "n/a",
LennyN95 marked this conversation as resolved.
Show resolved Hide resolved
"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"
}
]
}
}
}
60 changes: 60 additions & 0 deletions models/mrsegmentator/utils/MRSegmentatorMLRunner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""
-------------------------------------------------
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")

@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")
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)
LennyN95 marked this conversation as resolved.
Show resolved Hide resolved
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.")
bash_command += ["--split_level", "1"]
else:
self.v("Running MRSegmentator in default mode.")


self.v(">> run: ", " ".join(bash_command))

# run the model
self.subprocess(bash_command, text=True)

# copy data
shutil.copy(os.path.join(tmp_dir, new_filename), out_data.abspath)
Empty file.
Loading