Cookbook 60: Offline Orthopedic Fracture & Joint Space Narrowing Classifier

This cookbook details how to deploy a localized orthopedic radiography engine to detect acute bone fractures and stage chronic joint degeneration (osteoarthritis) directly from weight-bearing knee and limb X-rays without internet dependence.

1. Overview & Use Case

In urgent care, sports medicine, and remote clinics, waiting for cloud-based PACS radiology processing introduces critical delays. Similarly, tracking progressive joint diseases (like knee osteoarthritis) requires precise, repeatable geometric measurements of the joint space.

This engine enables:

       [ Weight-Bearing X-Ray / DICOM ]
                      │
                      ▼
             [ FractureNet-XRay-v1 ] 
             ├── Bone Segmentation
             └── Fracture Line Heatmap
                      │
                      ▼
         [ Osteoarthritis-Staging-CLI ]
         ├── Joint Gap Micrometry (mm)
         └── Kellgren-Lawrence Grade (0-4)
                      │
                      ▼
     [ Structured Orthopedic Summary JSON ]

2. Installation & Prerequisites

To run this pipeline offline, install the core SDK and download the local orthopedic weight files:

# Install the OpenPHR Orthopedic package
openphr install orthopedics-core

# Pre-fetch the local models and staging database
openphr models pull FractureNet-XRay-v1 --precision fp16
openphr db pull Orthopedics-Joint-DB-Local

3. Python Implementation Example

The following script loads a weight-bearing knee radiograph, detects bone borders, computes minimum joint space gap width, and classifies the osteoarthritis severity.

import os
import json
import numpy as np
from openphr.models import FractureNetClassifier
from openphr.ortho import JointSpaceProfiler, OsteoarthritisStaging

def run_ortho_diagnostic(dicom_path, output_report_path):
    print(f"[*] Processing orthopedic radiograph: {dicom_path}...")
    
    # 1. Initialize local deep learning fracture & bone segmentation engine
    model = FractureNetClassifier(model_name="FractureNet-XRay-v1", device="cpu")
    
    # 2. Segment bones and extract joint interface coordinates
    segmentation_map, fracture_candidates = model.segment_and_detect(dicom_path)
    
    # 3. Analyze joint space gap using the local joint database
    profiler = JointSpaceProfiler(database_path="Orthopedics-Joint-DB-Local")
    joint_metrics = profiler.calculate_gap_width(segmentation_map)
    
    # 4. Stage Osteoarthritis according to Kellgren-Lawrence criteria
    stager = OsteoarthritisStaging()
    kl_result = stager.stage_knee_oa(
        min_gap_mm=joint_metrics["min_gap_mm"], 
        osteophyte_present=joint_metrics["osteophyte_detected"]
    )
    
    # 5. Compile structured clinical payload
    report_payload = {
        "status": "success",
        "modality": "Radiograph (X-Ray)",
        "fracture_screening": {
            "fracture_detected": len(fracture_candidates) > 0,
            "fractures": [
                {
                    "location": f.location,
                    "confidence": float(f.confidence),
                    "morphology": f.morphology
                } for f in fracture_candidates
            ]
        },
        "joint_degeneration": {
            "minimum_joint_space_width_mm": float(joint_metrics["min_gap_mm"]),
            "osteophyte_detected": bool(joint_metrics["osteophyte_detected"]),
            "kellgren_lawrence_grade": int(kl_result["kl_grade"]),
            "interpretation": kl_result["description"]
        }
    }
    
    with open(output_report_path, "w") as f:
        json.dump(report_payload, f, indent=2)
        
    print(f"[+] Diagnostic processing complete. Report saved to: {output_report_path}")
    return report_payload

if __name__ == "__main__":
    # Execute clinical run on sample patient knee X-ray
    run_ortho_diagnostic(
        dicom_path="./data/patient_knee_092.dcm",
        output_report_path="./data/knee_diagnostic_report.json"
    )

Sample Output JSON Report

{
  "status": "success",
  "modality": "Radiograph (X-Ray)",
  "fracture_screening": {
    "fracture_detected": false,
    "fractures": []
  },
  "joint_degeneration": {
    "minimum_joint_space_width_mm": 1.85,
    "osteophyte_detected": true,
    "kellgren_lawrence_grade": 3,
    "interpretation": "Grade 3: Moderate joint space narrowing, multiple osteophytes, mild sclerosis, possible bony deformity."
  }
}

4. Verification & Testing

Verify CLI and model inference functionality locally:

# Validate model inference pipeline
openphr verify model FractureNet-XRay-v1

# Run sample osteoarthritis classification loop
openphr ortho diagnose --input ./data/patient_knee_092.dcm --output report.json