This cookbook details how to deploy a localized pulmonology CT analysis engine to segment lung parenchyma, calculate low-attenuation area percentages (LAA% <-950 HU), and stage Chronic Obstructive Pulmonary Disease (COPD) severity directly from volumetric chest CT scans without cloud API dependencies.
Quantifying functional lung destruction in COPD and emphysema requires reproducible low-attenuation volumetric measurements across thin-slice chest CT series. In clinical trials, pulmonary rehabilitation centers, and occupational health clinics, localized CT densitometry accelerates disease staging.
This engine enables:
[ Volumetric Thin-Slice Chest CT / DICOM Series ]
│
▼
[ COPDPress-CT-v1 ]
├── 3D Lung Parenchyma Segmentation
└── Airway & Vessel Suppression
│
▼
[ Emphysema-Quant-CLI ]
├── LAA% Densitometry (<-950 HU)
└── GOLD Severity Classification (1-4)
│
▼
[ Structured Pulmonology Diagnostic Summary JSON ]
Ensure Python 3.10+, pydicom, SimpleITK, torch, and numpy are installed:
pip install pydicom SimpleITK torch numpy
Clone the offline model weights:
git clone https://github.com/OpenPHRorg/copdpress-ct-local.git
cd copdpress-ct-local
Resample chest CT volume to isotropic voxel size (1.0mm³) and convert raw pixel data to Hounsfield Units (HU):
import SimpleITK as sitk
import numpy as np
def load_and_calibrate_ct(dicom_dir):
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(dicom_dir)
reader.SetFileNames(dicom_names)
image = reader.Execute()
# Resample to 1.0mm x 1.0mm x 1.0mm isotropic voxels
original_spacing = image.GetSpacing()
new_spacing = [1.0, 1.0, 1.0]
original_size = image.GetSize()
new_size = [
int(round(original_size[i] * original_spacing[i] / new_spacing[i]))
for i in range(3)
]
resample = sitk.ResampleImageFilter()
resample.SetInterpolator(sitk.sitkLinear)
resample.SetOutputSpacing(new_spacing)
resample.SetSize(new_size)
resample.SetOutputDirection(image.GetDirection())
resample.SetOutputOrigin(image.GetOrigin())
resampled_image = resample.Execute(image)
hu_array = sitk.GetArrayFromImage(resampled_image)
return hu_array
# Example loading
ct_volume_hu = load_and_calibrate_ct("./sample_chest_ct_dicom")
print(f"Calibrated CT Volume Shape (HU): {ct_volume_hu.shape}")
Execute lung segmentation and calculate Low-Attenuation Area (LAA% <-950 HU):
import torch
def quantize_emphysema(hu_volume):
model = torch.hub.load('OpenPHRorg/copdpress-ct-local', 'copd_seg_v1', pretrained=True)
model.eval()
tensor_input = torch.from_numpy(hu_volume).unsqueeze(0).unsqueeze(0).float()
with torch.no_grad():
lung_mask = model(tensor_input)
lung_mask_binary = (torch.sigmoid(lung_mask) > 0.5).numpy()[0, 0]
# Mask lung parenchyma
lung_hu = hu_volume[lung_mask_binary]
# Calculate Emphysema Index (LAA% <-950 HU)
laa_950 = np.sum(lung_hu < -950) / float(len(lung_hu)) * 100.0
laa_910 = np.sum(lung_hu < -910) / float(len(lung_hu)) * 100.0
gold_stage = "GOLD 4 (Very Severe)" if laa_950 > 25.0 else "GOLD 3 (Severe)" if laa_950 > 15.0 else "GOLD 2 (Moderate)" if laa_950 > 5.0 else "GOLD 1 (Mild / Normal)"
return {
"emphysema_index_laa950_pct": round(laa_950, 2),
"laa910_pct": round(laa_910, 2),
"copd_gold_stage": gold_stage,
"total_lung_volume_liters": round(len(lung_hu) / 1e6, 2)
}
# Run quantitation assessment
result = quantize_emphysema(ct_volume_hu)
print(f"Pulmonology Diagnostic Summary: {result}")
This engine delivers instant, offline pulmonary densitometry conforming to GOLD COPD guidelines.