This cookbook details how to deploy a localized, containerized infectious diseases, transplant oncology, and medical mycology decision-support engine for bone marrow transplant units, solid organ transplant services, hematologic malignancy wards, and medical ICUs to ingest absolute neutrophil counts ($\text{ANC}$), immunosuppressive exposure histories, high-resolution chest $\text{CT}$ imaging features, serum and bronchoalveolar lavage ($\text{BAL}$) Galactomannan Optical Density Indices ($\text{ODI}$), Aspergillus polymerase chain reaction ($\text{PCR}$) cycle thresholds, and triazole serum trough levels, classify Invasive Pulmonary Aspergillosis ($\text{IPA}$) according to the Revised EORTC / MSGERC 2020 Consensus Definitions (Proven, Probable, Possible IFD), guide First-Line Targeted Antifungal Therapy (Isavuconazonium Sulfate vs Voriconazole vs Liposomal Amphotericin B), perform Voriconazole Therapeutic Drug Monitoring ($\text{TDM}$ Target Trough $1.0 - 5.5\text{ mcg/mL}$), and enforce Triazole $\text{QTc}$ Interval & Hepatotoxicity Safety Sentinels according to Infectious Diseases Society of America ($\text{IDSA}$), ECIL-8, and ESCMID / ECMM consensus guidelines without external cloud API reliance.
Invasive Aspergillosis ($\text{IA}$), predominantly caused by Aspergillus fumigatus, A. flavus, A. niger, and A. terreus, carries a $30 - 60\%$ mortality rate in immunocompromised hosts. Early diagnosis and rapid antifungal initiation within $48 - 72\text{ hours}$ of radiological onset are critical to patient survival:
[Patient Telemetry: ANC, Transplant/Steroid History, CT Chest Findings, Galactomannan, Labs]
│
▼
[EORTC/MSGERC 2020 IFD Classifier: Proven vs Probable vs Possible IPA vs Unlikely]
│
▼
[Antifungal Selection Engine: Isavuconazole vs Voriconazole vs Liposomal Ampho B]
│
▼
[Voriconazole TDM Titrator: Target Trough 1.0 - 5.5 mcg/mL Pharmacokinetic Gating]
│
▼
[Triazole QTc Interval & Cyclodextrin Renal Accumulation Safety Sentinels]
Install required scientific Python and clinical mycology modeling packages:
pip install numpy scipy pandas torch torchvision matplotlib
"""
Cookbook 339: Offline Infectious Disease Invasive Aspergillosis, Galactomannan & Isavuconazole Engine
OpenPHR Clinical AI Working Group (https://openphr.org)
"""
import math
import numpy as np
import pandas as pd
from typing import Dict, List, Tuple, Optional
from dataclasses import dataclass
@dataclass
class AspergillosisPatientTelemetry:
patient_id: str
age_years: float = 49.0
sex: str = "Male"
patient_weight_kg: float = 74.0
# Host Factors (EORTC/MSGERC 2020)
absolute_neutrophil_count_cells_ul: float = 120.0 # ANC < 500 for > 10 days
neutropenia_duration_days: int = 14 # >= 10 days = Positive Host Factor
allogeneic_hct_recipient: bool = True
active_graft_versus_host_disease: bool = True # Severe acute GvHD
systemic_corticosteroid_daily_mg_pred_eq: float = 40.0 # >= 0.3 mg/kg for >= 3 weeks
corticosteroid_duration_days: int = 28
# Clinical & Radiological CT Chest Findings
ct_dense_well_circumscribed_nodule: bool = True
ct_halo_sign_present: bool = True # Classic angioinvasive ground-glass halo
ct_air_crescent_sign: bool = False
ct_cavitary_lesion: bool = False
ct_wedge_shaped_consolidation: bool = True
# Mycological Laboratory Telemetry
serum_galactomannan_odi: float = 1.35 # ODI >= 0.5 = Positive
bal_galactomannan_odi: float = 2.40 # ODI >= 1.0 = Positive
aspergillus_pcr_positive: bool = True
fungal_hyphae_on_tissue_biopsy: bool = False # Sterile biopsy pending
# Cardiac & Hepatic Baseline Safety Telemetry
baseline_qtc_interval_ms: float = 495.0 # ms (> 480 ms = Triazole QTc prolongation risk!)
serum_alt_u_l: float = 42.0 # Normal < 50
serum_total_bilirubin_mg_dl: float = 1.1 # Normal < 1.2
baseline_egfr_ml_min: float = 44.0 # mL/min (< 50 mL/min = IV cyclodextrin risk)
# Active Pharmacotherapy & TDM
current_antifungal: str = "Voriconazole"
voriconazole_trough_mcg_ml: float = 6.4 # mcg/mL (> 5.5 = Toxic range!)
@dataclass
class IPAEvaluationReport:
patient_id: str
eortc_msgerc_classification: str # "PROBABLE INVASIVE PULMONARY ASPERGILLOSIS (IPA)"
host_factors_met: List[str]
radiological_criteria_met: List[str]
mycological_criteria_met: List[str]
antifungal_recommendation: List[str]
voriconazole_tdm_status: str
safety_sentinels: List[str]
clinical_idsa_ecil_directive: str
class InvasiveAspergillosisDecisionEngine:
"""
Offline clinical engine for EORTC/MSGERC 2020 invasive aspergillosis staging,
Galactomannan ODI interpretation, and Isavuconazole / Voriconazole TDM titration.
"""
def evaluate_eortc_criteria(self, d: AspergillosisPatientTelemetry) -> Tuple[str, List[str], List[str], List[str]]:
host_met = []
ct_met = []
myco_met = []
# 1. Host Factors
if d.absolute_neutrophil_count_cells_ul < 500.0 and d.neutropenia_duration_days >= 10:
host_met.append(f"Host 1: Prolonged severe neutropenia (ANC {d.absolute_neutrophil_count_cells_ul:.0f} cells/uL for {d.neutropenia_duration_days} days).")
if d.allogeneic_hct_recipient:
host_met.append("Host 2: Allogeneic hematopoietic cell transplant recipient.")
if d.systemic_corticosteroid_daily_mg_pred_eq >= 20.0 and d.corticosteroid_duration_days >= 21:
host_met.append(f"Host 3: Prolonged systemic corticosteroid therapy ({d.systemic_corticosteroid_daily_mg_pred_eq:.0f} mg/day for {d.corticosteroid_duration_days} days).")
# 2. Radiological CT Findings
if d.ct_dense_well_circumscribed_nodule or d.ct_halo_sign_present:
host_str = "Dense well-circumscribed nodule with Halo sign" if d.ct_halo_sign_present else "Dense pulmonary nodule"
ct_met.append(f"CT 1: {host_str}.")
if d.ct_air_crescent_sign:
ct_met.append("CT 2: Air-crescent sign.")
if d.ct_cavitary_lesion:
ct_met.append("CT 3: Cavitary pulmonary lesion.")
if d.ct_wedge_shaped_consolidation:
ct_met.append("CT 4: Wedge-shaped segmental / lobar consolidation.")
# 3. Mycological Criteria
if d.serum_galactomannan_odi >= 0.5:
myco_met.append(f"Myco 1: Positive Serum Galactomannan (ODI {d.serum_galactomannan_odi:.2f} >= 0.50 cutoff).")
if d.bal_galactomannan_odi >= 1.0:
myco_met.append(f"Myco 2: Positive BAL Galactomannan (ODI {d.bal_galactomannan_odi:.2f} >= 1.00 cutoff).")
if d.aspergillus_pcr_positive:
myco_met.append("Myco 3: Positive Aspergillus qPCR on blood/BAL.")
# Staging Triage
if d.fungal_hyphae_on_tissue_biopsy:
stage = "PROVEN INVASIVE ASPERGILLOSIS (Histopathological / Sterile Culture Proof)"
elif len(host_met) >= 1 and len(ct_met) >= 1 and len(myco_met) >= 1:
stage = "PROBABLE INVASIVE PULMONARY ASPERGILLOSIS (IPA) (EORTC/MSGERC 2020 Criteria Met)"
elif len(host_met) >= 1 and len(ct_met) >= 1:
stage = "POSSIBLE INVASIVE PULMONARY ASPERGILLOSIS (IPA) (Host + Radiologic Features Present)"
else:
stage = "UNLIKELY INVASIVE ASPERGILLOSIS / NON-CLASSIFIED"
return stage, host_met, ct_met, myco_met
def audit_voriconazole_tdm(self, trough: float) -> str:
if trough < 1.0:
return f"⚠️ SUBTHERAPEUTIC VORICONAZOLE TROUGH ({trough:.1f} mcg/mL < 1.0 target) -> High risk of treatment failure. Increase total daily dose by 50%."
elif 1.0 <= trough <= 5.5:
return f"✅ OPTIMAL VORICONAZOLE TROUGH ({trough:.1f} mcg/mL, Target 1.0 - 5.5 mcg/mL) -> Maintain current dosage."
else:
return f"🚨 SUPRATHERAPEUTIC / TOXIC VORICONAZOLE TROUGH ({trough:.1f} mcg/mL > 5.5 mcg/mL) -> High risk of neurotoxicity and cholestatic hepatitis. STAT hold 1-2 doses and decrease daily dose by 30-50%."
def generate_treatment_recommendations(self, stage: str, d: AspergillosisPatientTelemetry) -> Tuple[List[str], List[str]]:
plan = []
sentinels = []
is_prolonged_qtc = d.baseline_qtc_interval_ms >= 480.0
has_renal_impairment = d.baseline_egfr_ml_min < 50.0
# Safety Sentinel: QTc Prolongation on Voriconazole
if is_prolonged_qtc:
sentinels.append(f"🚨 QTC PROLONGATION RISK SENTINEL: Baseline QTc is {d.baseline_qtc_interval_ms:.0f} ms (>= 480 ms). Voriconazole and Posaconazole cause dose-dependent QTc prolongation and risk of Torsades de Pointes. ISAVUCONAZOLE is preferred (causes QTc shortening) or Liposomal Amphotericin B.")
# Safety Sentinel: IV Cyclodextrin Accumulation
if has_renal_impairment and "Voriconazole" in d.current_antifungal:
sentinels.append(f"CYCLODEXTRIN ACCUMULATION ALERT: Patient eGFR is {d.baseline_egfr_ml_min:.0f} mL/min (< 50 mL/min). IV Voriconazole vehicle SBECD accumulates and causes nephrotoxicity. Convert to oral Voriconazole or IV Isavuconazole.")
# Treatment Plan
if "PROBABLE" in stage or "PROVEN" in stage or "POSSIBLE" in stage:
plan.append("1. FIRST-LINE TARGETED ANTIFUNGAL THERAPY (IDSA / ECIL-8 Guidelines):")
if is_prolonged_qtc or has_renal_impairment:
plan.append(" • PREFERRED: ISAVUCONAZONIUM SULFATE (Cresemba):")
plan.append(" - Loading Dose: 372 mg IV/PO every 8 hours x 6 doses (first 48 hours).")
plan.append(" - Maintenance Dose: 372 mg IV/PO once daily starting on Day 3.")
plan.append(f" - Rationales: Baseline QTc {d.baseline_qtc_interval_ms:.0f} ms (Isavuconazole shortens QTc), eGFR {d.baseline_egfr_ml_min:.0f} mL/min (no cyclodextrin), and predictable linear pharmacokinetics.")
else:
plan.append(" • OPTION A: VORICONAZOLE:")
plan.append(" - Loading Dose: 6 mg/kg IV q12h x 2 doses on Day 1.")
plan.append(" - Maintenance Dose: 4 mg/kg IV q12h or 200-300 mg PO BID.")
plan.append(" - Mandatory TDM: Check trough serum level on Day 4-7 (Target 1.0 - 5.5 mcg/mL).")
plan.append(" • OPTION B (ALTERNATIVE / AZOLE-REFRACTORY): Liposomal Amphotericin B (AmBisome) 3 - 5 mg/kg/day IV infusion.")
plan.append("2. DURATION OF THERAPY: Minimum of 6 to 12 weeks, continuing until full radiological resolution and complete resolution of immunosuppression/neutropenia.")
return plan, sentinels
def evaluate_case(self, data: AspergillosisPatientTelemetry) -> IPAEvaluationReport:
stage, host_list, ct_list, myco_list = self.evaluate_eortc_criteria(data)
tdm_status = self.audit_voriconazole_tdm(data.voriconazole_trough_mcg_ml)
rx_plan, sentinels = self.generate_treatment_recommendations(stage, data)
directives = []
directives.append(f"DIAGNOSIS: {stage}.")
directives.append(f"MYCOLOGY: Serum Galactomannan {data.serum_galactomannan_odi:.2f}, BAL {data.bal_galactomannan_odi:.2f}.")
directives.append(f"TDM: {tdm_status}")
return IPAEvaluationReport(
patient_id=data.patient_id,
eortc_msgerc_classification=stage,
host_factors_met=host_list,
radiological_criteria_met=ct_list,
mycological_criteria_met=myco_list,
antifungal_recommendation=rx_plan,
voriconazole_tdm_status=tdm_status,
safety_sentinels=sentinels,
clinical_idsa_ecil_directive=" ".join(directives)
)
# Example Execution & Verification
if __name__ == "__main__":
engine = InvasiveAspergillosisDecisionEngine()
print("=" * 80)
print("OpenPHR Clinical Infectious Disease Invasive Aspergillosis & TDM Engine")
print("=" * 80)
# Test Case 1: 49-year-old male post-allogeneic HCT with active severe GvHD, ANC 120 (Host Factors).
# CT Chest: Dense nodule with classic Halo sign + Wedge-shaped consolidation.
# Mycology: Serum Galactomannan 1.35 (>= 0.5), BAL Galactomannan 2.40 (>= 1.0), PCR Positive.
# Diagnosis: Probable Invasive Pulmonary Aspergillosis (IPA).
# Safety: Baseline QTc 495 ms + eGFR 44 mL/min + Voriconazole trough 6.4 mcg/mL (Toxic!).
# Triage: STAT Hold Voriconazole -> Transition to Isavuconazole 372 mg IV/PO (QTc shortening)!
ipa1 = AspergillosisPatientTelemetry(
patient_id="ID-IPA-9901",
age_years=49.0,
patient_weight_kg=74.0,
absolute_neutrophil_count_cells_ul=120.0,
neutropenia_duration_days=14,
allogeneic_hct_recipient=True,
active_graft_versus_host_disease=True,
systemic_corticosteroid_daily_mg_pred_eq=40.0,
corticosteroid_duration_days=28,
ct_dense_well_circumscribed_nodule=True,
ct_halo_sign_present=True,
ct_wedge_shaped_consolidation=True,
serum_galactomannan_odi=1.35,
bal_galactomannan_odi=2.40,
aspergillus_pcr_positive=True,
baseline_qtc_interval_ms=495.0,
baseline_egfr_ml_min=44.0,
current_antifungal="Voriconazole",
voriconazole_trough_mcg_ml=6.4
)
rep1 = engine.evaluate_case(ipa1)
print(f"\n[Patient {rep1.patient_id} - Invasive Aspergillosis Assessment]")
print(f"EORTC / MSGERC 2020 Stage: {rep1.eortc_msgerc_classification}")
print("\nHost Factors Met:")
for h in rep1.host_factors_met:
print(f" • {h}")
print("\nChest CT Imaging Criteria:")
for c in rep1.radiological_criteria_met:
print(f" • {c}")
print("\nMycological Evidence:")
for m in rep1.mycological_criteria_met:
print(f" • {m}")
print(f"\nVoriconazole TDM Audit:\n {rep1.voriconazole_tdm_status}")
print("\nAntifungal Therapy Recommendations:")
for rx in rep1.antifungal_recommendation:
print(f" {rx}")
if rep1.safety_sentinels:
print("\nSafety Sentinels:")
for s in rep1.safety_sentinels:
print(f" 🚨 {s}")
print(f"\nIDSA / ECIL-8 Consensus Directive:\n{rep1.clinical_idsa_ecil_directive}")