This cookbook details how to deploy a localized musculoskeletal ultrasound (MSKUS) analysis engine to segment joint synovial thickening, detect Power Doppler (PD) vascular signals, and stage rheumatoid arthritis (RA) inflammatory activity conforming to OMERACT (Outcome Measures in Rheumatology) standards without cloud dependence.
Quantifying joint synovitis and intra-articular hyperemia in metacarpophalangeal (MCP) and wrist joints is central to monitoring therapeutic response to biologic disease-modifying antirheumatic drugs (bDMARDs). In rheumatology suites and point-of-care ultrasound (POCUS) clinics, automated grayscale and Power Doppler grading standardizes disease activity scores.
This engine enables:
[ Dual-Mode B-Mode & Power Doppler MSK Sonogram ]
│
▼
[ RheumaNet-MSK-v1 ]
├── Joint Capsule Alignment
└── Synovial & Power Doppler Mask
│
▼
[ OMERACT-Scoring-CLI ]
├── Synovial Thickness Micrometry (mm)
└── OMERACT Synovitis Grade (0-3)
│
▼
[ Structured Rheumatology Diagnostic Summary JSON ]
Ensure Python 3.10+, pydicom, torch, torchvision, scikit-image, and OpenCV are installed:
pip install pydicom torch torchvision opencv-python-headless scikit-image numpy
Clone the offline model weights:
git clone https://github.com/OpenPHRorg/rheumanet-msk-local.git
cd rheumanet-msk-local
Separate grayscale B-mode anatomical joint structure from Power Doppler (PD) vascular color channels:
import pydicom
import cv2
import numpy as np
def preprocess_mskus_frame(dicom_path):
ds = pydicom.dcmread(dicom_path)
pixel_array = ds.pixel_array
if len(pixel_array.shape) == 3:
bgr = cv2.cvtColor(pixel_array, cv2.COLOR_RGB2BGR)
else:
bgr = cv2.cvtColor(pixel_array, cv2.COLOR_GRAY2BGR)
hsv = cv2.cvtColor(bgr, cv2.COLOR_BGR2HSV)
# Isolate Power Doppler orange/red vascular signal in HSV space
lower_pd = np.array([0, 120, 120])
upper_pd = np.array([25, 255, 255])
pd_mask = cv2.inRange(hsv, lower_pd, upper_pd)
# Convert to grayscale for anatomical B-mode segmentation
gray_bmode = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY)
return gray_bmode, pd_mask
# Example preprocessing
bmode, pd_signal = preprocess_mskus_frame("sample_mcp_joint_pd.dcm")
cv2.imwrite("bmode_joint.png", bmode)
cv2.imwrite("power_doppler_mask.png", pd_signal)
print("MSKUS joint preprocessing completed.")
Execute synovial boundary segmentation and OMERACT joint grading:
import torch
def evaluate_joint_synovitis(gray_bmode, pd_mask):
model = torch.hub.load('OpenPHRorg/rheumanet-msk-local', 'rheumanet_v1', pretrained=True)
model.eval()
tensor_input = torch.from_numpy(gray_bmode).unsqueeze(0).unsqueeze(0).float() / 255.0
with torch.no_grad():
synovial_mask = model(tensor_input)
synovial_binary = (torch.sigmoid(synovial_mask) > 0.5).numpy()[0, 0]
# Calculate synovial ROI area & max thickness (mm)
voxel_mm = 0.05 # mm per pixel calibration
synovial_area_mm2 = float(np.sum(synovial_binary) * (voxel_mm ** 2))
# Measure Power Doppler signal inside synovial ROI
pd_in_synovium = np.sum((pd_mask > 0) & synovial_binary)
pd_fraction = float(pd_in_synovium / np.sum(synovial_binary)) if np.sum(synovial_binary) > 0 else 0.0
# OMERACT Synovitis Grading (Grades 0-3)
if pd_fraction > 0.30 or synovial_area_mm2 > 25.0:
omeract_grade = "Grade 3 (Severe Synovitis / Marked PD Signal)"
elif pd_fraction > 0.10 or synovial_area_mm2 > 12.0:
omeract_grade = "Grade 2 (Moderate Synovitis / Moderate PD Signal)"
elif synovial_area_mm2 > 4.0:
omeract_grade = "Grade 1 (Mild Synovitis / Minimal PD Signal)"
else:
omeract_grade = "Grade 0 (Normal Joint / No Synovitis)"
return {
"omeract_synovitis_grade": omeract_grade,
"synovial_area_mm2": round(synovial_area_mm2, 2),
"power_doppler_hyperemia_pct": round(pd_fraction * 100.0, 1),
"active_inflammation": pd_fraction > 0.05,
"bmard_response_monitoring": "Escalate Therapy" if "Grade 3" in omeract_grade else "Maintain Current Regimen"
}
# Run assessment
result = evaluate_joint_synovitis(bmode, pd_signal)
print(f"Rheumatology MSKUS Diagnostic Summary: {result}")
This engine delivers instant, offline joint inflammation scoring conforming to EULAR and OMERACT MSK ultrasound consensus guidelines.