This cookbook details how to deploy a localized, containerized medical toxicology, occupational health, and pulmonary critical care decision-support engine for chemical disaster response teams, industrial medicine clinics, and intensive care units ($\text{ICUs}$) to ingest toxic chemical exposure telemetry, blood gas metrics, and respiratory mechanics, differentiate between Intermediate-Solubility Rapid Airway Irritants (Chlorine [$\text{Cl}_2$]) and Low-Solubility Latent Alveolar Toxins (Phosgene [$\text{COCl}_2$]), calculate Predicted Body Weight ($\text{PBW}$), gate Nebulized Sodium Bicarbonate ($3.75\% - 4.2\%$) Neutralization and Inhaled Corticosteroid Delivery, enforce $6 - 24\text{ Hour}$ Asymptomatic Latency Observation Sentinels, and generate ARDS Lung-Protective Mechanical Ventilation Protocols ($4 - 6\text{ mL/kg}$ PBW) according to ACMT, ATS, and CHEST consensus guidelines without external cloud API reliance.
Toxic gas inhalation in industrial accidents, transport derailments, or domestic chemical mixing produces acute lung injury through water solubility and chemical reactivity gradients:
[Exposure Telemetry: Agent (Cl2 vs COCl2), Concentration, Latency Hours, SpO2, ABG]
│
▼
[Solubility & Toxicity Classifier: Immediate Spasm vs 6-24h Latent Alveolar Risk]
│
▼
[Pharmacotherapy Gating: Nebulized NaHCO3 3.75-4.2% + Inhaled Budesonide Orders]
│
▼
[Predicted Body Weight & ARDS Lung-Protective Mechanical Ventilation (4-6 mL/kg)]
│
▼
[Mandatory 24h Latency Hospitalization Sentinel & Restrictive Fluid Directive]
Install required scientific Python and pulmonary toxicology modeling packages:
pip install numpy scipy pandas torch torchvision matplotlib
"""
Cookbook 317: Offline Clinical Toxicology Chlorine & Phosgene Toxic Inhalation 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 ToxicInhalationTelemetry:
patient_id: str
age_years: float
gender: str # "Male" or "Female"
height_cm: float # e.g. 178.0 cm
actual_weight_kg: float # e.g. 88.0 kg
# Chemical Exposure Parameters
toxic_chemical_agent: str # "Chlorine (Cl2)", "Phosgene (COCl2)", "Ammonia (NH3)", "Hydrogen Chloride (HCl)"
estimated_exposure_intensity: str # "Low", "Moderate", "High / Confined Space"
time_since_exposure_hours: float # e.g. 4.5 hours
# Clinical Signs & Symptoms
stridor_or_laryngeal_edema: bool = False # Flag for emergent airway intubation
severe_wheezing_or_bronchospasm: bool = True
cough_and_choking_sensation: bool = True
conjunctivitis_or_corneal_burns: bool = True
hemoptysis_or_pink_frothy_sputum: bool = False # Direct alveolar hemorrhage / flooding
# Gas Exchange & Arterial Blood Gas (ABG)
room_air_spo2_percent: float = 91.0
fio2_delivered: float = 0.50 # e.g. 50% via NRB mask
pao2_mmhg: float = 68.0 # PaO2 / FiO2 = 136 mmHg (Moderate ARDS)
paco2_mmhg: float = 46.0
arterial_ph: float = 7.34
# Chest Radiograph / Imaging
chest_xray_bilateral_alveolar_infiltrates: bool = True
trauma_or_secondary_blast_injury: bool = False
@dataclass
class ToxicInhalationReport:
patient_id: str
toxic_agent: str
predicted_body_weight_kg: float
pao2_fio2_ratio: float
pulmonary_edema_ards_severity: str # "None / Mild Airway Irritation", "Mild ARDS (P/F 200-300)", "Moderate ARDS (P/F 100-200)", "Severe ARDS (P/F < 100)"
antidote_and_pharmacotherapy_orders: List[str]
ventilator_and_respiratory_orders: List[str]
inpatient_monitoring_sentinels: List[str]
clinical_acmt_ats_directive: str
class ToxicInhalationDecisionEngine:
"""
Offline clinical engine for acute chlorine and phosgene gas exposure triage,
ARDS severity classification, nebulized bicarbonate gating, and lung-protective ventilation.
"""
def compute_pbw(self, height_cm: float, gender: str) -> float:
height_inches = height_cm / 2.54
if height_inches <= 60.0:
return 50.0 if gender.lower().startswith("m") else 45.5
diff_inches = height_inches - 60.0
if gender.lower().startswith("m"):
pbw = 50.0 + 2.3 * diff_inches
else:
pbw = 45.5 + 2.3 * diff_inches
return round(float(pbw), 1)
def calculate_ards_severity(self, pao2: float, fio2: float, infiltrates: bool) -> Tuple[float, str]:
pf_ratio = round(pao2 / max(0.21, fio2), 1)
if not infiltrates:
if pf_ratio >= 300.0:
return pf_ratio, "Acute Airway Chemical Irritation (No Pulmonary Edema)"
else:
return pf_ratio, "Acute Hypoxemic Respiratory Failure (Suspected Early Edema)"
if pf_ratio <= 100.0:
return pf_ratio, "Severe Toxic ARDS (PaO2/FiO2 <= 100 mmHg)"
elif pf_ratio <= 200.0:
return pf_ratio, "Moderate Toxic ARDS (PaO2/FiO2 101 - 200 mmHg)"
elif pf_ratio <= 300.0:
return pf_ratio, "Mild Toxic ARDS (PaO2/FiO2 201 - 300 mmHg)"
else:
return pf_ratio, "Toxic Chemical Pulmonary Edema (Compensated Gas Exchange)"
def generate_pharmacotherapy_orders(self, d: ToxicInhalationTelemetry) -> List[str]:
orders = []
is_chlorine = "chlorine" in d.toxic_chemical_agent.lower() or "cl2" in d.toxic_chemical_agent.lower()
is_phosgene = "phosgene" in d.toxic_chemical_agent.lower() or "cocl2" in d.toxic_chemical_agent.lower()
# 1. Decontamination
orders.append("1. DECONTAMINATION: Immediately remove all contaminated clothing; flush exposed skin and irrigate eyes with copious normal saline/water for >= 15 minutes.")
# 2. Nebulized Sodium Bicarbonate for Chlorine
if is_chlorine and (d.severe_wheezing_or_bronchospasm or d.cough_and_choking_sensation):
orders.append("2. NEBULIZED SODIUM BICARBONATE: Administer 3.0 to 4.0 mL of 3.75% - 4.2% Sodium Bicarbonate solution via nebulizer every 4-6 hours PRN persistent coughing or reactive airway spasm (Prepare by diluting 8.4% NaHCO3 1:1 with sterile water).")
# 3. Bronchodilators & Inhaled Corticosteroids
orders.append("3. INHALED BRONCHODILATOR: Nebulized Albuterol 2.5 - 5.0 mg + Ipratropium Bromide 0.5 mg every 20-30 minutes for acute bronchospasm, then q4h scheduled.")
orders.append("4. INHALED & SYSTEMIC CORTICOSTEROIDS: Administer Budesonide 1.0 - 2.0 mg nebulized BID (or Methylprednisolone 1.0 - 2.0 mg/kg/day IV) to suppress progressive alveolar capillary permeability.")
# 4. Fluid Restriction
orders.append("5. RESTRICTIVE FLUID STRATEGY: Maintain strict conservative IV fluid rate (e.g. 50-75 mL/hr D5 1/2NS); avoid crystalloid boluses to prevent aggravating toxic capillary leak alveolar flooding.")
return orders
def generate_ventilator_orders(self, d: ToxicInhalationTelemetry, pbw: float, ards_sev: str) -> List[str]:
v_orders = []
vt_6ml = round(6.0 * pbw, 0)
vt_4ml = round(4.0 * pbw, 0)
if d.stridor_or_laryngeal_edema:
v_orders.append("1. CRITICAL AIRWAY ALERT: Immediate endotracheal intubation by expert under video laryngoscopy (High risk of sudden complete upper airway obstruction from laryngeal/glottic edema).")
if "ARDS" in ards_sev or d.chest_xray_bilateral_alveolar_infiltrates:
v_orders.append(f"1. ARDS LUNG-PROTECTIVE VENTILATION (Predicted Body Weight = {pbw} kg):")
v_orders.append(f" • Initial Tidal Volume (Vt): 6.0 mL/kg PBW ({vt_6ml:.0f} mL); titrate down to 4.0 mL/kg PBW ({vt_4ml:.0f} mL) if Plateau Pressure > 30 cm H2O.")
v_orders.append(" • Plateau Pressure Target: Maintain Pplat <= 30 cm H2O (Driving Pressure <= 14 cm H2O).")
v_orders.append(" • Positive End-Expiratory Pressure (PEEP): Titrate PEEP 8 - 14 cm H2O according to ARDSNet High-PEEP/Low-FiO2 titration grid.")
v_orders.append(" • Permissive Hypercapnia: Allow arterial pH 7.20 - 7.30 to avoid high tidal volume barotrauma.")
else:
v_orders.append("1. HIGH-FLOW OXYGEN / CPAP: Deliver 100% humidified oxygen via non-rebreather mask or High-Flow Nasal Cannula (HFNC) titrated to maintain SpO2 >= 92-95%.")
return v_orders
def evaluate_case(self, data: ToxicInhalationTelemetry) -> ToxicInhalationReport:
pbw = self.compute_pbw(data.height_cm, data.gender)
pf_ratio, ards_sev = self.calculate_ards_severity(data.pao2_mmhg, data.fio2_delivered, data.chest_xray_bilateral_alveolar_infiltrates)
rx_orders = self.generate_pharmacotherapy_orders(data)
vent_orders = self.generate_ventilator_orders(data, pbw, ards_sev)
sentinels = []
is_phosgene = "phosgene" in data.toxic_chemical_agent.lower() or "cocl2" in data.toxic_chemical_agent.lower()
if is_phosgene and data.time_since_exposure_hours < 24.0:
sentinels.append(f"CRITICAL PHOSGENE LATENCY SENTINEL (Time Post-Exposure: {data.time_since_exposure_hours}h): Mandatory minimum 24-hour hospital admission with continuous pulse oximetry and serial CXRs. Fatal pulmonary edema can develop suddenly between 6-24 hours despite a completely normal initial presentation.")
if data.stridor_or_laryngeal_edema:
sentinels.append("AIRWAY EMERGENCY: Stridor indicates advanced laryngeal edema; prepare difficult airway cart and surgical cricothyrotomy backup immediately.")
directives = []
directives.append(f"AGENT & TIME: {data.toxic_chemical_agent} Exposure ({data.time_since_exposure_hours}h post-incident).")
directives.append(f"RESPIRATORY STATUS: {ards_sev} (PaO2/FiO2 = {pf_ratio:.0f} mmHg).")
directives.append(f"MANAGEMENT: {'ARDS Lung-Protective Ventilation (Vt 4-6 mL/kg PBW) + Restrictive Fluids' if 'ARDS' in ards_sev else 'Nebulized NaHCO3 / Budesonide + 24h Latency Inpatient Observation'}.")
return ToxicInhalationReport(
patient_id=data.patient_id,
toxic_agent=data.toxic_chemical_agent,
predicted_body_weight_kg=pbw,
pao2_fio2_ratio=pf_ratio,
pulmonary_edema_ards_severity=ards_sev,
antidote_and_pharmacotherapy_orders=rx_orders,
ventilator_and_respiratory_orders=vent_orders,
inpatient_monitoring_sentinels=sentinels,
clinical_acmt_ats_directive=" ".join(directives)
)
# Example Execution & Verification
if __name__ == "__main__":
engine = ToxicInhalationDecisionEngine()
print("=" * 80)
print("OpenPHR Clinical Toxicology Chlorine & Phosgene Toxic Inhalation Engine")
print("=" * 80)
# Test Case 1: 38-year-old male industrial worker exposed to high-concentration Chlorine (Cl2) gas 4.5h ago
# Height: 178 cm (PBW = 73.1 kg) | Actual Weight: 88 kg
# Presentation: Severe bronchospasm, choking, bilateral diffuse alveolar infiltrates on CXR
# ABG: PaO2 = 68 mmHg on FiO2 50% -> PaO2/FiO2 = 136 mmHg (Moderate Toxic ARDS)
# Management: Nebulized Sodium Bicarbonate (3.75-4.2%) + ARDS Ventilation (Vt 6 mL/kg = 439 mL) + Restrictive Fluids!
chem1 = ToxicInhalationTelemetry(
patient_id="TOX-INHAL-9104",
age_years=38.0,
gender="Male",
height_cm=178.0,
actual_weight_kg=88.0,
toxic_chemical_agent="Chlorine (Cl2)",
estimated_exposure_intensity="High / Confined Space",
time_since_exposure_hours=4.5,
severe_wheezing_or_bronchospasm=True,
cough_and_choking_sensation=True,
conjunctivitis_or_corneal_burns=True,
room_air_spo2_percent=89.0,
fio2_delivered=0.50,
pao2_mmhg=68.0,
chest_xray_bilateral_alveolar_infiltrates=True
)
rep1 = engine.evaluate_case(chem1)
print(f"\n[Patient {rep1.patient_id} - Toxicology Evaluation]")
print(f"Toxic Agent: {rep1.toxic_agent}")
print(f"Predicted Body Weight (PBW): {rep1.predicted_body_weight_kg} kg")
print(f"PaO2 / FiO2 Ratio: {rep1.pao2_fio2_ratio:.0f} mmHg ({rep1.pulmonary_edema_ards_severity})")
print("\nAntidote & Pharmacotherapy Orders:")
for a in rep1.antidote_and_pharmacotherapy_orders:
print(f" • {a}")
print("\nVentilator & Airway Orders:")
for v in rep1.ventilator_and_respiratory_orders:
print(f" • {v}")
print("\nCritical Safety Sentinels:")
for s in rep1.inpatient_monitoring_sentinels:
print(f" {s}")
print(f"\nACMT / ATS Consensus Directive:\n{rep1.clinical_acmt_ats_directive}")
# Test Case 2: Asymptomatic chemical worker exposed to Phosgene (COCl2) 3 hours ago -> Mandatory 24h Admission!
chem2 = ToxicInhalationTelemetry(
patient_id="TOX-INHAL-1042",
age_years=29.0,
gender="Female",
height_cm=165.0,
actual_weight_kg=60.0,
toxic_chemical_agent="Phosgene (COCl2)",
estimated_exposure_intensity="Moderate",
time_since_exposure_hours=3.0,
severe_wheezing_or_bronchospasm=False,
cough_and_choking_sensation=False,
room_air_spo2_percent=98.0,
fio2_delivered=0.21,
pao2_mmhg=94.0,
chest_xray_bilateral_alveolar_infiltrates=False
)
rep2 = engine.evaluate_case(chem2)
print(f"\n[Patient {rep2.patient_id}] - Sentinel: {rep2.inpatient_monitoring_sentinels[0]}")