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

MHub / GC - Add LUNA22 ISMI baseline model implementation #46

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 36 additions & 0 deletions models/gc_luna22_ismi_baseline/config/default.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
general:
data_base_dir: /app/data
version: 1.0
description: LUNA22 ISMI Baseline lung CT nodule malignancy and nodule type classification (dicom to json)

execute:
- DicomImporter
- MhaConverter
- Luna22IsmiBaselineRunner
- ReportExporter
- DataOrganizer

modules:
DicomImporter:
source_dir: input_data
import_dir: sorted_data
sort_data: True
meta:
mod: ct

MhaConverter:
engine: panimg

ReportExporter:
format: compact
includes:
- data: malignancy_risk
label: malignancy_risk
value: value
- data: texture
label: texture
value: value

DataOrganizer:
targets:
- json:mod=report-->[i:sid]/nodule_predictions.json
45 changes: 45 additions & 0 deletions models/gc_luna22_ismi_baseline/dockerfiles/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
FROM mhubai/base:latest

# Update authors label
LABEL authors="[email protected]"

# Install git-lfs (required for unpacking model weights)
RUN apt update && apt install -y --no-install-recommends git-lfs && rm -rf /var/lib/apt/lists/*

# build/install CUDA 11 toolkit cudnn 8 and tensorflow 2.11.0 with GPU support (without conda)
RUN pip3 install --no-cache-dir \
nvidia-cuda-runtime-cu11 \
nvidia-cusolver-cu11 \
nvidia-curand-cu11 \
nvidia-cufft-cu11 \
nvidia-cublas-cu11 \
nvidia-cusparse-cu11 \
nvidia-cudnn-cu11 \
tensorflow==2.11.0 \
nvidia-tensorrt==7.2.3.4 \
--extra-index-url https://pypi.ngc.nvidia.com

# Configure required paths for tensorflow with GPU support
ENV NVIDIA_DIR /usr/local/lib/python3.8/dist-packages/nvidia
ENV LD_LIBRARY_PATH /usr/local/lib/python3.8/dist-packages/tensorrt:$NVIDIA_DIR/cublas/lib:$NVIDIA_DIR/cuda_runtime/lib:$NVIDIA_DIR/cudnn/lib:$NVIDIA_DIR/cufft/lib:$NVIDIA_DIR/curand/lib:$NVIDIA_DIR/cusolver/lib:$NVIDIA_DIR/cusparse/lib

# Clone the main branch of MHubAI/models TODO enable
#RUN git stash \
# && git fetch https://github.com/MHubAI/models.git main \
# && git merge FETCH_HEAD \
# && git sparse-checkout set "models/gc_luna22_ismi_baseline" \
# && git fetch https://github.com/MHubAI/models.git main

# Install luna22 ismi baseline algorithm and model weights (main branch, commit 68c5e93be62dae54d15a8a3d8821ca2138e0fe2e)
RUN git clone https://github.com/DIAGNijmegen/bodyct-luna22-ismi-algorithm-baseline.git /opt/algorithm && \
cd /opt/algorithm && git reset --hard 68c5e93be62dae54d15a8a3d8821ca2138e0fe2e

# Install algorithm requirements
RUN pip3 install --no-cache-dir evalutils==0.3.1

# Set PYTHONPATH to include algorithm code
ENV PYTHONPATH "/app:/opt/algorithm"

# Default run script
ENTRYPOINT ["python3", "-m", "mhubio.run"]
CMD ["--config", "/app/models/gc_luna22_ismi_baseline/config/default.yml"]
73 changes: 73 additions & 0 deletions models/gc_luna22_ismi_baseline/utils/Luna22IsmiBaselineRunner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
------------------------------------------------------------------
Mhub / DIAG - Run Module for the GC Luna22 ISMI baseline Algorithm
------------------------------------------------------------------

------------------------------------------------------------------
Author: Sil van de Leemput
Email: [email protected]
------------------------------------------------------------------
"""

import json
from pathlib import Path
from typing import Optional

from mhubio.core import Instance, InstanceData, IO, Module, ValueOutput, ClassOutput, Meta

import SimpleITK

import tensorflow as tf

# Import the Luna22 baseline algorithm class from the luna22-ismi-algorithm repository
from process import Nodule_classifier as NoduleClassifier


@ValueOutput.Name('malignancy_risk')
@ValueOutput.Meta(Meta(key="value"))
@ValueOutput.Label('MalignancyRisk')
@ValueOutput.Type(float)
@ValueOutput.Description('Probability of the nodule malignancy.')
class MalignancyRiskOutput(ValueOutput):
pass


@ClassOutput.Name('texture')
@ClassOutput.Label('NoduleType')
@ClassOutput.Description('Prediction of the nodule type.')
@ClassOutput.Class(0, 'Non-solid', 'Non-solid.')
@ClassOutput.Class(1, 'Part-solid', 'Part-solid.')
@ClassOutput.Class(2, 'Solid', 'Solid.')
class NoduleTypeOutput(ClassOutput):
pass


class Luna22IsmiBaselineRunner(Module):

_cached_classifier: Optional[NoduleClassifier] = None

@IO.Instance()
@IO.Input('in_data', 'mha|nrrd|nifti:mod=ct', the='input volume centered around a nodule from a lung CT image')
@IO.OutputData('malignancy_risk', MalignancyRiskOutput, data='in_data', the='Luna22 Ismi nodule malignancy probability')
@IO.OutputData('texture', NoduleTypeOutput, data='in_data', the='Luna22 Ismi nodule type classification')
def task(self, instance: Instance, in_data: InstanceData, malignancy_risk: MalignancyRiskOutput, texture: NoduleTypeOutput) -> None:
assert len(tf.config.list_physical_devices("GPU")) >= 1, \
"Error: Luna22IsmiBaselineRunner must be run on a GPU! Because: " \
"The Conv2D op currently only supports the NHWC tensor format on" \
" the CPU. The op was given the format: NCHW [Op:Conv2D]"

# Read input image
input_image = SimpleITK.ReadImage(in_data.abspath)

# Create classifier and load model weights if not already loaded
if self._cached_classifier is None:
self.v("Luna22IsmiBaselineRunner - Loading and caching model weights")
self._cached_classifier = NoduleClassifier()
classifier = self._cached_classifier

# Run the classifier on the input image
predictions = classifier.predict(input_image=input_image)

# Output the predicted values
malignancy_risk.value = predictions["malignancy_risk"]
texture.value = predictions["texture"]
1 change: 1 addition & 0 deletions models/gc_luna22_ismi_baseline/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from Luna22IsmiBaselineRunner import *