Back to projects
MedViz 1 month 4 pers.

Medical Prediction & 3D Visualization

Full-stack medical application combining 3D CT scan processing, Quantile Machine Learning, and WebGL visualization to predict Pulmonary Fibrosis decline.

Python FastAPI XGBoost Next.js Three.js Docker DICOM
Aperçu du projet MedViz

Context & Problem Statement

Idiopathic Pulmonary Fibrosis (IPF) is a chronic lung disease that causes progressive scarring of lung tissue, irreversibly compromising respiratory capacity. The primary clinical parameter for monitoring disease progression is Forced Vital Capacity (FVC), measured in mL.

The goal of MedViz was to design a full-stack medical application capable of:

The project builds upon the OSIC (Open Source Imaging Consortium) challenge, whose dataset includes volumetric DICOM series and tabular clinical metadata (age, sex, smoking status, historical FVC).

Data Type Format Description
3D CT Scanners DICOM (.dcm) Volumetric axial slice series
Clinical Data CSV (.csv) Patient metadata & historical FVC
Volumetric axial CT scan slices (OSIC patient)
Volumetric axial CT scan slices (OSIC patient)

Workflow Overview

01 Raw DICOM 3D CT Scanner
02 HU Normalization DICOM Preprocessing
03 Segmentation K-Means + 3D Morpho
04 3D Radiomics Biomarkers + GLB Mesh
05 ML Prediction Quantile XGBoost
06 Disease Score 3D Web Visualization

3D Medical Image Processing

1. Hounsfield Normalization (DICOM Preprocessing)

Raw grayscale values in DICOM scanners are specific to each equipment manufacturer and lack direct physical meaning. They must be converted into Hounsfield Units (HU), an absolute scale calibrated against biological tissue density:

Tissue HU Range
Outer Air ≈ −1000 HU
Lung Parenchyma −900 to −400 HU
Soft Tissue / Water ≈ 0 HU
Dense Fibrotic Tissue > −250 HU

Once converted to HU, thresholding isolates clinically relevant regions and normalizes data across patients.

HU Standardization: (1) Raw DICOM slice, (2) Hounsfield thresholding
HU Standardization: (1) Raw DICOM slice, (2) Hounsfield thresholding

2. Isotropic 3D Resampling

CT slice thickness varies across hospital equipment. To ensure consistent geometric and volumetric measurements between patients, the 3D volume is resampled to 1 voxel = 1 mm³ (3rd-order spline interpolation via scipy.ndimage.zoom).

3. Automatic 3D Lung Segmentation

Segmentation isolates lung parenchyma from surrounding tissue (bones, muscles, outer air) via 6 numbered steps:

  1. Original CT Slice: Raw input axial slice.
  2. FOV Boundary: Masking field of view to exclude scanner borders.
  3. Raw Air (K-Means): Adaptive $K=2$ thresholding separating air from tissue.
  4. Internal Lungs: Connected Component Analysis isolating the 2 main air cavities.
  5. Final Mask: 3D morphological operations (closing, dilation) and noise cleanup (< 5% max volume).
  6. Segmented Lungs: Final result applied to the original image.
3D Lung segmentation pipeline steps
3D Lung segmentation pipeline steps

4. 3D Volumetric Reconstruction of the Lungs

Once the stack of 2D axial slices is segmented, all masks are stacked in 3D space to reconstruct the complete respiratory system. The Marching Cubes algorithm (skimage.measure.marching_cubes) is applied to this volume to extract the isosurface of the lung parenchyma, generating a high-fidelity 3D representation of both lungs.

3D Lung parenchyma reconstruction from segmented slices
3D Lung parenchyma reconstruction from segmented slices

5. Extraction of Radiomic Biomarkers

From the reconstructed 3D volume and validated mask, three quantitative biomarkers are extracted per patient:

6. 3D Mesh Generation & WebGL Export (GLB)

The extracted 3D mesh is optimized for interactive web rendering in two steps:

  1. Surface Smoothing & Simplification: Normalizing vertices and computing surface normals.
  2. Export to GLB / glTF 2.0 Format via trimesh for real-time WebGL rendering directly in the browser using Three.js.

Prediction Model: Quantile XGBoost

Rather than a simple point estimate, MedViz trains 5 distinct XGBoost models corresponding to quantiles of the FVC distribution:

Quantile Clinical Interpretation
q = 0.025 Lower bound 95% CI (worst case)
q = 0.10 Lower bound 80% CI
q = 0.50 Median — central prediction
q = 0.90 Upper bound 80% CI
q = 0.975 Upper bound 95% CI (best case)

Each model takes as input: target week, age, lung volume, mean HU, std HU, fibrosis ratio, sex, smoking status, baseline FVC, baseline week, and time delta.

Confidence Index and Severity Score

A continuous confidence index $C \in [0.01, 0.99]$ is derived from the width of the 95% confidence interval — the more certain the model, the higher the index.

Temporal FVC predictions and quantile confidence intervals
Temporal FVC predictions and quantile confidence intervals

To provide a standardized medical reference, the Severity Score is calculated using GLI-2012 (Global Lung Function Initiative) equations based on patient age, height, and sex:

$$ \text{Score} = \frac{\text{FVC}_{\text{Baseline}}}{\text{FVC}_{\text{Optimal}}} $$
GLI Severity Score and patient risk status
GLI Severity Score and patient risk status

Results

A rigorous comparative study evaluates the direct contribution of 3D radiomic biomarkers (CT Scans) compared to tabular clinical data alone:

Model MAE with Radiomics MAE without Radiomics MAE Gain Radiomic Benefit
SVR (RBF) 119.4 mL 116.7 mL −2.7 mL ❌ Not useful
XGBoost 87.1 mL 94.7 mL +7.6 mL ✅ Useful
Random Forest 98.6 mL 109.4 mL +10.8 mL ✅ Useful

XGBoost with radiomics achieves 87.1 mL MAE, the top result, confirming that 3D imaging features significantly enhance the model’s predictive capability.

LLL Score with and without radiomic biomarkers
LLL Score with and without radiomic biomarkers
MAE and RMSE errors per architecture vs baseline
MAE and RMSE errors per architecture vs baseline

Architecture & Deployment

MedViz adopts a decoupled microservices architecture in 2 independent Docker containers:

Containerized Backend & Frontend Architecture (Docker)
Containerized Backend & Frontend Architecture (Docker)

Code Quality & Continuous Integration (CI/CD)

The project achieves a 91% test coverage rate on the Python backend, with a complete CI/CD pipeline (GitLab CI) structured across 3 automated phases: style checking (ruff, prettier), unit testing (pytest), and static type analysis (ty check, tsc).

Backend Module Pytest Coverage
database.py 100%
schemas.py 100%
logger.py 94%
services.py 94%
routes.py 89%
processing/pipeline.py 80%
TOTAL 91%
Continuous Integration Pipeline (GitLab CI)
Continuous Integration Pipeline (GitLab CI)

User Interface & Complex Web Application

MedViz User Interface Overview
MedViz User Interface Overview