# explainer.py # ECG Condition Classifier - Clinical Explanation Generator CONDITION_MAP = { "NORM": { "summary": "Normal Sinus Rhythm", "urgency": "Routine", "description": "The ECG shows a normal sinus rhythm with regular rate and rhythm, normal P waves, QRS complexes, and T waves. No significant ST changes or conduction abnormalities detected.", "recommendation": "No immediate cardiac intervention required. Continue routine follow-up as clinically indicated.", }, "AFIB": { "summary": "Atrial Fibrillation", "urgency": "Elevated", "description": "The ECG pattern is consistent with Atrial Fibrillation. Characteristic findings include an irregularly irregular rhythm, absence of distinct P waves, and variable R-R intervals. AFib is associated with increased risk of stroke and heart failure.", "recommendation": "Clinical evaluation recommended. Rate/rhythm management and stroke risk assessment advised.", }, "MI": { "summary": "Myocardial Infarction", "urgency": "URGENT", "description": "The ECG pattern is consistent with Myocardial Infarction. Findings may include ST-segment elevation or depression and pathological Q waves suggesting myocardial injury or ischemia.", "recommendation": "⚠️ IMMEDIATE clinical review strongly recommended. Activate emergency cardiac protocols if STEMI suspected.", }, "STTC": { "summary": "ST/T-Wave Change", "urgency": "Moderate", "description": "Non-specific ST-segment and/or T-wave changes detected. These findings can represent myocardial ischemia, electrolyte abnormalities, medication effects, or normal variants. Clinical context is essential for interpretation.", "recommendation": "Clinical correlation advised. Serial ECGs and lab results may be warranted.", }, "CD": { "summary": "Conduction Disturbance", "urgency": "Moderate", "description": "The ECG shows features consistent with a conduction disturbance, such as bundle branch block or AV conduction delay. These findings alter the normal electrical pathway through the ventricles.", "recommendation": "Cardiology consultation recommended to evaluate hemodynamic significance and underlying etiology.", }, } DISCLAIMER = "⚠️ DISCLAIMER: For educational and research purposes only. Does not constitute medical advice. Always consult a qualified healthcare provider." def match_condition(label): label_upper = (label or "").upper() for key, val in CONDITION_MAP.items(): if key in label_upper: return {**val, "key": key} return { "key": "UNKNOWN", "summary": "Unrecognized Pattern", "urgency": "Unknown", "description": "The model returned a label that could not be mapped to a known cardiac condition. This may indicate an unusual ECG pattern or a label category outside the standard NORM/AFIB/MI/STTC/CD set.", "recommendation": "Manual review by a qualified cardiologist is recommended.", } def generate_explanation(label, confidence): condition = match_condition(label) urgency = condition["urgency"] text = ( f"Condition: {condition['summary']}\n" f"Raw Model Label: {label}\n" f"Confidence: {confidence:.1f}%\n" f"Urgency: {urgency}\n\n" f"{condition['description']}\n\n" f"Recommendation: {condition['recommendation']}\n\n" f"{DISCLAIMER}" ) return text, urgency def format_top3(results): lines = ["Top Predictions:"] for i, r in enumerate(results[:3], 1): score = r["score"] * 100 bar = "█" * int(score / 5) lines.append(f" {i}. {r['label']}: {score:.1f}% {bar}") return "\n".join(lines)