Answer the short essays and short answers of these 2 documents Use flowcharts and diagrams
cd /tmp/workspace/attachments/b6fda5c1-3962-4346-ab8c-c3bf126f0cfc/ && python3 -c " from docx import Document doc = Document('Ear - Question bank.docx') for i, para in enumerate(doc.paragraphs): if para.text.strip(): print(f'{i}: {para.text}') "
mkdir -p /tmp/workspace/ent-answers && python3 << 'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.patches as mpatches from matplotlib.patches import FancyArrowPatch, FancyBboxPatch import numpy as np # ── FIGURE 1: Nasal Polyp Etiopathogenesis & Management Flowchart ── fig, ax = plt.subplots(figsize=(14, 18)) ax.set_xlim(0, 14) ax.set_ylim(0, 18) ax.axis('off') ax.set_facecolor('#f8f9fa') fig.patch.set_facecolor('#f8f9fa') def box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9, style='round,pad=0.1'): ax.add_patch(FancyBboxPatch((x-w/2, y-h/2), w, h, boxstyle=style, facecolor=color, edgecolor='#333', linewidth=1.2)) ax.text(x, y, text, ha='center', va='center', fontsize=fontsize, color=textcolor, fontweight='bold', wrap=True, multialignment='center') def arrow(ax, x1, y1, x2, y2): ax.annotate('', xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle='->', color='#333', lw=1.5)) ax.text(7, 17.5, 'NASAL POLYPS — Etiopathogenesis & Management', ha='center', va='center', fontsize=13, fontweight='bold', color='#1a237e') # Etiopathogenesis box(ax, 7, 16.5, 10, 0.7, 'ETIOPATHOGENESIS', '#1a237e') box(ax, 3.5, 15.5, 5.5, 0.7, 'Chronic Inflammation\n(allergic/non-allergic)', '#1565C0') box(ax, 10.5, 15.5, 5.5, 0.7, 'Risk Factors:\nAllergy, Asthma, Aspirin sensitivity,\nCystic Fibrosis, Samter\'s Triad', '#1565C0') arrow(ax, 5, 16.15, 5, 15.85) arrow(ax, 9, 16.15, 10.5, 15.85) box(ax, 7, 14.5, 10, 0.8, 'Eosinophilic Inflammation → TH2 cytokines (IL-4, IL-5, IL-13)\n→ Mucosal oedema → Polyp formation', '#0288D1', fontsize=8.5) arrow(ax, 3.5, 15.15, 5.5, 14.9) arrow(ax, 10.5, 15.15, 8.5, 14.9) # STAGING box(ax, 7, 13.4, 10, 0.7, 'STAGING (Mygind / Johanssen)', '#1a237e') stages = ['Stage I\nPolyps confined\nto middle meatus', 'Stage II\nPolyps beyond\nmiddle meatus', 'Stage III\nPolyps completely\nfilling nasal cavity'] cols = [2.5, 7, 11.5] colors = ['#43A047','#FB8C00','#E53935'] for i, (s, c, col) in enumerate(zip(stages, cols, colors)): box(ax, c, 12.4, 3.5, 1.4, s, col, fontsize=8) arrow(ax, 7, 13.05, 2.5, 13.1) arrow(ax, 7, 13.05, 7, 13.1) arrow(ax, 7, 13.05, 11.5, 13.1) # INVESTIGATIONS box(ax, 7, 11.1, 10, 0.7, 'INVESTIGATIONS', '#1a237e') inv = ['Nasal Endoscopy\n(1st line)', 'CT PNS\n(extent/staging)', 'Allergy tests\n(RAST/SPT)', 'Biopsy\n(if unilateral)'] for i, (inv_t, xp) in enumerate(zip(inv, [2, 5.5, 9, 12.5])): box(ax, xp, 10.1, 3, 0.9, inv_t, '#0097A7', fontsize=8) arrow(ax, 7, 10.75, 2, 10.55) arrow(ax, 7, 10.75, 5.5, 10.55) arrow(ax, 7, 10.75, 9, 10.55) arrow(ax, 7, 10.75, 12.5, 10.55) # MEDICAL MANAGEMENT box(ax, 7, 9.0, 10, 0.7, 'MEDICAL MANAGEMENT', '#1a237e') med = ['Intranasal\nCorticosteroids\n(INCS) — 1st line\nMometasone/Fluticasone', 'Systemic\nCorticosteroids\n(Short course)\nPrednisolone 0.5mg/kg', 'Antihistamines\n+ Saline\nIrrigation', 'Biologics:\nMepolizumab\nDupilumab\n(refractory)'] xcols = [2, 5.3, 9, 12.3] for m, xp in zip(med, xcols): box(ax, xp, 7.9, 3.2, 1.8, m, '#388E3C', fontsize=7.5) arrow(ax, 7, 8.65, 2, 8.8) arrow(ax, 7, 8.65, 5.3, 8.8) arrow(ax, 7, 8.65, 9, 8.8) arrow(ax, 7, 8.65, 12.3, 8.8) # SURGICAL MANAGEMENT box(ax, 7, 6.8, 10, 0.7, 'SURGICAL MANAGEMENT', '#1a237e') box(ax, 4, 5.8, 5.5, 1.4, 'FESS\n(Functional Endoscopic\nSinus Surgery)\n— Gold Standard\nFor recurrent/Stage III', '#7B1FA2', fontsize=8) box(ax, 10, 5.8, 5.5, 1.4, 'Polypectomy\n(Simple avulsion)\n— Outpatient\nFor Stage I-II\nunder local anaesthesia', '#AD1457', fontsize=8) arrow(ax, 7, 6.45, 4, 6.5) arrow(ax, 7, 6.45, 10, 6.5) # RECURRENCE / FOLLOW UP box(ax, 7, 4.5, 10, 0.7, 'POST-OPERATIVE: Lifelong INCS to prevent recurrence', '#BF360C') arrow(ax, 7, 5.1, 7, 4.85) # SAMTER'S TRIAD NOTE box(ax, 7, 3.5, 10, 0.8, "Samter's Triad = Nasal Polyps + Asthma + Aspirin Sensitivity\n(Aspirin Exacerbated Respiratory Disease — AERD)", '#37474F', fontsize=8.5) plt.tight_layout() plt.savefig('/tmp/workspace/ent-answers/fig1_nasal_polyps.png', dpi=150, bbox_inches='tight') plt.close() print("Fig 1 saved") PYEOF
python3 << 'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.patches as mpatches from matplotlib.patches import FancyBboxPatch def box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9): ax.add_patch(FancyBboxPatch((x-w/2, y-h/2), w, h, boxstyle='round,pad=0.1', facecolor=color, edgecolor='#333', linewidth=1.2)) ax.text(x, y, text, ha='center', va='center', fontsize=fontsize, color=textcolor, fontweight='bold', multialignment='center') def arrow(ax, x1, y1, x2, y2, label=''): ax.annotate('', xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle='->', color='#333', lw=1.5)) if label: mx, my = (x1+x2)/2, (y1+y2)/2 ax.text(mx+0.1, my, label, fontsize=7.5, color='#333') # ── FIGURE 2: JNA (Juvenile Nasopharyngeal Angiofibroma) ── fig, ax = plt.subplots(figsize=(14, 16)) ax.set_xlim(0, 14) ax.set_ylim(0, 16) ax.axis('off') ax.set_facecolor('#f8f9fa') fig.patch.set_facecolor('#f8f9fa') ax.text(7, 15.5, 'JUVENILE NASOPHARYNGEAL ANGIOFIBROMA (JNA)\nEtiopathogenesis, Clinical Features & Management', ha='center', va='center', fontsize=12, fontweight='bold', color='#1a237e', multialignment='center') # ETIOPATHOGENESIS box(ax, 7, 14.5, 12, 0.7, 'ETIOPATHOGENESIS', '#1a237e') box(ax, 3.5, 13.5, 5.5, 1.2, 'Fibrovascular benign tumour\narising from posterolateral\nwall of nasopharynx\n(sphenopalatine foramen)', '#1565C0', fontsize=8) box(ax, 10.5, 13.5, 5.5, 1.2, 'Androgen-dependent growth\n(Testosterone receptors)\nAffects adolescent males\n(10-25 yrs)', '#1565C0', fontsize=8) arrow(ax, 7, 14.15, 3.5, 14.1) arrow(ax, 7, 14.15, 10.5, 14.1) box(ax, 7, 12.3, 12, 0.7, 'Vascular supply: Internal maxillary artery (main) + branches of external carotid artery', '#0288D1', fontsize=8.5) arrow(ax, 3.5, 12.9, 5.5, 12.65) arrow(ax, 10.5, 12.9, 8.5, 12.65) # STAGING - Sessions box(ax, 7, 11.4, 12, 0.7, 'STAGING (Sessions Classification)', '#1a237e') stages_jna = [ 'Stage I\nNasopharynx only', 'Stage II\nNasal cavity,\nsinus, pterygoid\nfossa extension', 'Stage III\nOrbital extension\nor ICE (intracranial\nextradural)', 'Stage IV\nIntracranial\nintradural\nextension' ] xcols = [2, 5.3, 9, 12.3] colors_s = ['#43A047', '#FB8C00', '#E53935', '#880E4F'] for s, xp, col in zip(stages_jna, xcols, colors_s): box(ax, xp, 10.2, 3.2, 2.0, s, col, fontsize=7.5) for xp in xcols: arrow(ax, 7, 11.05, xp, 11.2) # CLINICAL FEATURES box(ax, 7, 8.9, 12, 0.7, 'CLINICAL FEATURES', '#1a237e') cfs = ['Profuse\nrecurrent\nepistaxis\n(cardinal feature)', 'Nasal\nobstruction\n(unilateral)', 'Cheek swelling\nAnterior bowing\nof posterior\nmaxillary wall', 'Proptosis\n(orbital\nextension)', 'Conductive\ndeafness\n(ETD)', 'Visual\nchanges\n(late)'] xcols2 = [1.5, 3.8, 6.5, 9, 11.2, 13] for cf, xp in zip(cfs, xcols2): box(ax, xp, 7.7, 2.3, 1.7, cf, '#0097A7', fontsize=7.5) for xp in xcols2: arrow(ax, 7, 8.55, xp, 8.6) # INVESTIGATIONS box(ax, 7, 6.5, 12, 0.7, 'INVESTIGATIONS', '#1a237e') invs = ['CT PNS/Skull Base\n(calcification,\nbone erosion)', 'MRI\n(extent, ICE,\ncavernous sinus)', 'Angiography\n(preop vascular\nmapping)', 'Biopsy\nCONTRAINDICATED\n(massive bleed risk)'] xcols3 = [2.2, 5.5, 9.2, 12.3] inv_colors = ['#1565C0','#1565C0','#1565C0','#C62828'] for inv, xp, col in zip(invs, xcols3, inv_colors): box(ax, xp, 5.4, 3.0, 1.7, inv, col, fontsize=8) for xp in xcols3: arrow(ax, 7, 6.15, xp, 6.3) # MANAGEMENT box(ax, 7, 4.3, 12, 0.7, 'MANAGEMENT', '#1a237e') box(ax, 4, 3.2, 5.5, 1.5, 'Pre-operative\nEmbolization\n(DSA guided, 24-48h\nbefore surgery)\n→ reduces blood loss', '#7B1FA2', fontsize=7.5) box(ax, 10, 3.2, 5.5, 1.5, 'Surgery:\nEndoscopic resection (Stage I-II)\nOpen approaches (Stage III-IV):\n- Lateral rhinotomy\n- Infratemporal fossa approach\n- Combined craniofacial', '#7B1FA2', fontsize=7.5) arrow(ax, 7, 3.95, 4, 4.0) arrow(ax, 7, 3.95, 10, 4.0) box(ax, 7, 1.9, 12, 0.8, 'Radiotherapy — reserved for residual/recurrent unresectable Stage IV disease\nHormonal therapy (Testosterone antagonists) — adjunct, limited use\nSpontaneous regression reported after puberty', '#37474F', fontsize=8) arrow(ax, 7, 2.45, 7, 2.3) plt.tight_layout() plt.savefig('/tmp/workspace/ent-answers/fig2_JNA.png', dpi=150, bbox_inches='tight') plt.close() print("Fig 2 saved") PYEOF
python3 << 'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch def box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9): ax.add_patch(FancyBboxPatch((x-w/2, y-h/2), w, h, boxstyle='round,pad=0.1', facecolor=color, edgecolor='#333', linewidth=1.2)) ax.text(x, y, text, ha='center', va='center', fontsize=fontsize, color=textcolor, fontweight='bold', multialignment='center') def arrow(ax, x1, y1, x2, y2): ax.annotate('', xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle='->', color='#555', lw=1.5)) # ── FIGURE 3: CSF Rhinorrhea + Epistaxis Management ── fig, axes = plt.subplots(1, 2, figsize=(18, 14)) # --- LEFT: CSF Rhinorrhea --- ax = axes[0] ax.set_xlim(0, 10) ax.set_ylim(0, 14) ax.axis('off') ax.set_facecolor('#f8f9fa') ax.text(5, 13.5, 'Q3: CSF RHINORRHEA\n(30y male, bike accident,\nclear watery nasal discharge)', ha='center', va='center', fontsize=10, fontweight='bold', color='#1a237e', multialignment='center') box(ax, 5, 12.5, 8, 0.7, 'Dx: Traumatic CSF Rhinorrhea\n(Anterior skull base fracture / cribriform plate)', '#C62828') arrow(ax, 5, 12.15, 5, 11.8) box(ax, 5, 11.5, 8, 0.6, 'INVESTIGATIONS', '#1a237e', fontsize=9) invs = ['Beta-2 Transferrin\n(Gold Standard)\nin nasal fluid', 'CT Head/Skull Base\n(non-contrast, thin cuts)\nbone defect', 'MRI cisternography\n(localize defect)', 'Halo/Ring test\n(CSF + blood —\nouter clear ring)'] ys = [10.6, 10.6, 10.6, 10.6] xs = [1.5, 4, 6.8, 9.2] for i, (text, xp) in enumerate(zip(invs, xs)): ax.add_patch(FancyBboxPatch((xp-1.2, 9.8), 2.4, 1.5, boxstyle='round,pad=0.1', facecolor='#0288D1', edgecolor='#333', linewidth=1)) ax.text(xp, 10.55, text, ha='center', va='center', fontsize=7, color='white', fontweight='bold', multialignment='center') arrow(ax, 5, 11.2, xp, 11.3) box(ax, 5, 9.1, 8, 0.6, 'MANAGEMENT', '#1a237e') # Conservative box(ax, 2.5, 8.2, 4, 1.2, 'CONSERVATIVE (1st line)\n— Bed rest, head elevation 30°\n— Avoid nose blowing/straining\n— Prophylactic antibiotics?\n (controversial)', '#388E3C', fontsize=7.5) arrow(ax, 5, 8.8, 2.5, 8.8) # Surgical box(ax, 7.5, 8.2, 4, 1.2, 'SURGICAL\n(if leak persists >2 wks)\n— Endoscopic skull base\n repair (fascia lata/fat\n graft + fibrin glue)', '#AD1457', fontsize=7.5) arrow(ax, 5, 8.8, 7.5, 8.8) box(ax, 5, 7.0, 8, 0.6, 'Watch for: MENINGITIS (fever, neck stiffness, Kernig\'s sign)', '#BF360C', fontsize=8) arrow(ax, 5, 7.65, 5, 7.3) # Note on halo sign box(ax, 5, 5.8, 8, 1.5, 'HALO / RING SIGN:\nWhen blood-tinged CSF is placed on tissue paper\nor linen — CSF travels faster forming outer clear\nhalo around the central blood spot\n(Positive = CSF rhinorrhea)', '#4527A0', fontsize=8) # Glucose test note box(ax, 5, 4.3, 8, 0.9, 'Glucose >30mg/dL in nasal fluid suggests CSF\n(glucose oxidase test — but low specificity)', '#37474F', fontsize=8) # --- RIGHT: Epistaxis Management --- ax2 = axes[1] ax2.set_xlim(0, 10) ax2.set_ylim(0, 14) ax2.axis('off') ax2.set_facecolor('#f8f9fa') ax2.text(5, 13.5, 'Q6: MANAGEMENT OF EPISTAXIS', ha='center', va='center', fontsize=11, fontweight='bold', color='#1a237e') box(ax2, 5, 12.7, 8, 0.6, 'INITIAL ABC + Resuscitation', '#C62828') # Site identification box(ax2, 2.5, 11.9, 4, 0.6, 'Anterior Epistaxis\n(Kiesselbach\'s plexus)\n90% cases', '#1565C0', fontsize=8) box(ax2, 7.5, 11.9, 4, 0.6, 'Posterior Epistaxis\n(Woodruff\'s plexus)\n10% — severe', '#1565C0', fontsize=8) arrow(ax2, 5, 12.4, 2.5, 12.2) arrow(ax2, 5, 12.4, 7.5, 12.2) # Anterior management box(ax2, 2.5, 10.8, 4, 1.5, 'ANTERIOR:\n1. Pinch nose 10-15 min\n2. Cold compress\n3. Silver nitrate cautery\n4. Anterior nasal pack\n (BIPP/Merocel)\n5. Septoplasty (septal defects)', '#388E3C', fontsize=7.5) arrow(ax2, 2.5, 11.6, 2.5, 11.55) # Posterior management box(ax2, 7.5, 10.8, 4, 1.5, 'POSTERIOR:\n1. Posterior nasal pack\n (Foley catheter balloon)\n2. Endoscopic\n sphenopalatine artery\n ligation (ESPAL)\n3. Embolization', '#7B1FA2', fontsize=7.5) arrow(ax2, 7.5, 11.6, 7.5, 11.55) # CAUSES box(ax2, 5, 9.3, 8, 0.6, 'CAUSES OF EPISTAXIS', '#1a237e') causes = ['Local:\nTrauma, Rhinitis\nForeign body\nTumours', 'Systemic:\nHTN, Coagulopathy\nAnticoagulants\nLiver disease', 'Vascular:\nHHT\nAngioma'] xcs = [2, 5.5, 8.8] for c, xp in zip(causes, xcs): box(ax2, xp, 8.3, 2.9, 1.5, c, '#0097A7', fontsize=7.5) for xp in xcs: arrow(ax2, 5, 9.0, xp, 9.05) # Kiesselbach's plexus note box(ax2, 5, 7.0, 8, 1.5, "KIESSELBACH'S PLEXUS (Little's area):\nAnastomosis at anteroinferior nasal septum\nArteries: Anterior ethmoidal (ICA) +\nPosterior ethmoidal (ICA) +\nSphenopalatine (ECA) +\nGreater palatine (ECA) +\nSuperior labial (ECA)", '#1B5E20', fontsize=8) box(ax2, 5, 5.4, 8, 0.9, 'Investigations: FBC, PT/APTT, Platelet, LFT, BP, Endoscopy\nBlood transfusion if Hb <8 or haemodynamically unstable', '#37474F', fontsize=8) plt.tight_layout() plt.savefig('/tmp/workspace/ent-answers/fig3_csf_epistaxis.png', dpi=150, bbox_inches='tight') plt.close() print("Fig 3 saved") PYEOF
python3 << 'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch def box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9): ax.add_patch(FancyBboxPatch((x-w/2, y-h/2), w, h, boxstyle='round,pad=0.1', facecolor=color, edgecolor='#333', linewidth=1.2)) ax.text(x, y, text, ha='center', va='center', fontsize=fontsize, color=textcolor, fontweight='bold', multialignment='center') def arrow(ax, x1, y1, x2, y2): ax.annotate('', xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle='->', color='#555', lw=1.5)) # ── FIGURE 4: Ear Questions — Cholesteatoma + CSOM Complications ── fig, axes = plt.subplots(1, 2, figsize=(18, 16)) # --- LEFT: Cholesteatoma --- ax = axes[0] ax.set_xlim(0, 10) ax.set_ylim(0, 16) ax.axis('off') ax.set_facecolor('#f8f9fa') ax.text(5, 15.5, 'CHOLESTEATOMA\nClassification, Etiopathogenesis & Management', ha='center', va='center', fontsize=10, fontweight='bold', color='#1a237e', multialignment='center') box(ax, 5, 14.7, 8, 0.6, 'DEFINITION: Keratinizing stratified squamous\nepithelium in middle ear cleft', '#1a237e', fontsize=8.5) # Classification box(ax, 5, 13.8, 8, 0.6, 'CLASSIFICATION', '#1a237e') box(ax, 2.5, 12.9, 4, 1.5, 'CONGENITAL\n(behind intact TM,\nno hx of ear disease)\n— Epidermoid\n (pearly white mass)', '#1565C0', fontsize=8) box(ax, 7.5, 12.9, 4, 1.5, 'ACQUIRED\nPrimary: Attic retraction\npocket (no perforation)\nSecondary: From marginal\nperforation (ASOM/CSOM)', '#1565C0', fontsize=8) arrow(ax, 5, 13.5, 2.5, 13.65) arrow(ax, 5, 13.5, 7.5, 13.65) # Pathogenesis box(ax, 5, 11.7, 8, 0.6, 'ETIOPATHOGENESIS', '#1a237e') pathways = ['Invagination\ntheory\n(retraction pocket)', 'Squamous\nmetaplasia\ntheory', 'Basal cell\nhyperplasia\ntheory', 'Implantation\n(post-traumatic\nor iatrogenic)'] xs4 = [1.5, 4, 7, 9.2] colors4 = ['#0288D1','#0288D1','#0288D1','#0288D1'] for p, xp in zip(pathways, xs4): box(ax, xp, 10.8, 2.3, 1.5, p, '#0288D1', fontsize=7.5) arrow(ax, 5, 11.4, xp, 11.55) # Clinical features box(ax, 5, 9.9, 8, 0.6, 'CLINICAL FEATURES', '#1a237e') cfs = ['Painless otorrhoea\n(scanty, foul-smelling\n"cheese-like" discharge)', 'Conductive\nhearing loss', 'Retraction pocket\n/ marginal\nperforation (attic)', 'Complications:\nFacial palsy, vertigo,\nmeningitis, abscess'] xs5 = [1.5, 4, 6.8, 9.2] for c, xp in zip(cfs, xs5): box(ax, xp, 8.9, 2.3, 1.5, c, '#0097A7', fontsize=7.5) arrow(ax, 5, 9.6, xp, 9.65) # Investigations box(ax, 5, 7.9, 8, 0.6, 'INVESTIGATIONS', '#1a237e') box(ax, 2, 7.0, 3.5, 1.2, 'CT Temporal Bone\n(Schueller\'s view)\nBone erosion, extent', '#4527A0', fontsize=7.5) box(ax, 5.7, 7.0, 3.5, 1.2, 'Audiometry\n(PTA + impedance)\nCHL pattern', '#4527A0', fontsize=7.5) box(ax, 8.7, 7.0, 2.2, 1.2, 'DW-MRI\n(recurrence\ncheck)', '#4527A0', fontsize=7.5) for xp in [2, 5.7, 8.7]: arrow(ax, 5, 7.6, xp, 7.6) # Surgery box(ax, 5, 5.9, 8, 0.6, 'SURGICAL MANAGEMENT', '#1a237e') box(ax, 2.5, 4.8, 4, 2.0, 'Canal Wall UP (CWU)\nMastoidectomy\n+ Atticotomy\n— Preserves ear canal\n— Risk: residual/\n recurrent disease\n— 2nd look at 9-12mo', '#7B1FA2', fontsize=7.5) box(ax, 7.5, 4.8, 4, 2.0, 'Canal Wall DOWN (CWD)\nModified Radical\nMastoidectomy\n— Open cavity\n— Lower recurrence\n— Cavity maintenance\n required lifelong', '#AD1457', fontsize=7.5) arrow(ax, 5, 5.6, 2.5, 5.8) arrow(ax, 5, 5.6, 7.5, 5.8) box(ax, 5, 3.3, 8, 0.7, 'STAGING (EAONO/JOS): S0→S3\nS0=No cholesteatoma | S1=Mesotympanum only\nS2=Epitympanum/mastoid | S3=Outside ME cleft', '#37474F', fontsize=7.5) # --- RIGHT: CSOM Complications --- ax2 = axes[1] ax2.set_xlim(0, 10) ax2.set_ylim(0, 16) ax2.axis('off') ax2.set_facecolor('#f8f9fa') ax2.text(5, 15.5, 'COMPLICATIONS OF CSOM\n(Atticoantral Type — Unsafe CSOM)', ha='center', va='center', fontsize=10, fontweight='bold', color='#1a237e', multialignment='center') box(ax2, 5, 14.7, 8, 0.6, 'CSOM Unsafe (Atticoantral) = Cholesteatoma + Bony erosion', '#C62828', fontsize=8.5) # Extracranial box(ax2, 3, 13.7, 5, 0.6, 'EXTRACRANIAL (EXTRADURAL) COMPLICATIONS', '#AD1457') excr = [('Mastoiditis\n(acute coalescent)', '#E53935'), ('Subperiosteal\nabscess', '#E53935'), ('Bezold\'s abscess\n(SCM groove)', '#E53935'), ('Luc\'s abscess\n(zygomatic root)', '#E53935'), ('Facial nerve\nparalysis', '#E53935'), ('Labyrinthitis\n(fistula)', '#E53935'), ('Petrositis /\nGradenigo\'s\nsyndrome', '#E53935')] xs_ex = [1, 2.8, 5, 7.5, 9.3, 1, 3.5] ys_ex = [12.6, 12.6, 12.6, 12.6, 12.6, 11.5, 11.5] for (text, col), xp, yp in zip(excr, xs_ex, ys_ex): box(ax2, xp, yp, 1.8*0.9, 1.5*0.7, text, col, fontsize=6.5) arrow(ax2, 3, 13.4, xp, yp+0.5) # Intracranial box(ax2, 7, 13.7, 5, 0.6, 'INTRACRANIAL COMPLICATIONS', '#7B1FA2') incr = [('Extradural\nabscess', '#7B1FA2'), ('Subdural\nabscess', '#7B1FA2'), ('Meningitis\n(most common IC)', '#7B1FA2'), ('Brain abscess\n(temporal lobe\nor cerebellum)', '#7B1FA2'), ('Lateral sinus\nthrombophlebitis', '#7B1FA2'), ('Otitic\nhydrocephalus', '#7B1FA2')] xs_in = [5.5, 7, 8.7, 5.5, 7.5, 9.2] ys_in = [12.6, 12.6, 12.6, 11.5, 11.5, 11.5] for (text, col), xp, yp in zip(incr, xs_in, ys_in): box(ax2, xp, yp, 2.5*0.7, 1.2*0.7, text, col, fontsize=6.5) arrow(ax2, 7, 13.4, xp, yp+0.4) # Warning signs box(ax2, 5, 10.3, 8, 0.6, 'WARNING SIGNS OF COMPLICATIONS ("CSOM Danger Signs")', '#C62828') warns = ['Increasing\nearache', 'Headache\n(dull, persistent)', 'Fever\n(spiking)', 'Vomiting', 'Vertigo', 'Facial palsy', 'Neck stiffness', 'Subperiosteal\nswelling'] xs_w = [0.8, 2.5, 4, 5.5, 7, 8, 9.2, 5] ys_w = [9.4, 9.4, 9.4, 9.4, 9.4, 9.4, 9.4, 8.6] for w, xp, yp in zip(warns, xs_w, ys_w): box(ax2, xp, yp, 1.8, 1.0, w, '#BF360C', fontsize=6.5) arrow(ax2, 5, 10.0, xp, yp+0.5) # Gradenigo's syndrome box(ax2, 5, 7.5, 8, 1.2, "GRADENIGO'S SYNDROME:\nTriad: Otorrhoea + Deep facial/retro-orbital pain\n(V nerve = trigeminal) + Diplopia (VI nerve = abducens)\nDue to: Petrositis (apicitis of petrous apex)", '#1565C0', fontsize=8) # Lateral sinus thrombosis box(ax2, 5, 6.0, 8, 1.2, "LATERAL SINUS THROMBOSIS:\nPicket fence (spiking) fever + Rigors\n+ Griesinger's sign (oedema over mastoid emissary vein)\n+ Tobey-Ayer test (compression of IJV — no ICP rise on affected side)", '#1565C0', fontsize=8) # Bezold box(ax2, 5, 4.6, 8, 0.9, "BEZOLD'S ABSCESS: Pus tracks through medial surface of\nmastoid tip → into SCM muscle sheath → neck mass\n(Tip cell erosion)", '#37474F', fontsize=8) # Management note box(ax2, 5, 3.5, 8, 0.8, 'MANAGEMENT: IV antibiotics + URGENT mastoidectomy (MRM)\n± Neurosurgical consultation for intracranial complications', '#1B5E20', fontsize=8) plt.tight_layout() plt.savefig('/tmp/workspace/ent-answers/fig4_cholesteatoma_csom.png', dpi=150, bbox_inches='tight') plt.close() print("Fig 4 saved") PYEOF
python3 << 'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch def box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9): ax.add_patch(FancyBboxPatch((x-w/2, y-h/2), w, h, boxstyle='round,pad=0.1', facecolor=color, edgecolor='#333', linewidth=1.2)) ax.text(x, y, text, ha='center', va='center', fontsize=fontsize, color=textcolor, fontweight='bold', multialignment='center') def arrow(ax, x1, y1, x2, y2): ax.annotate('', xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle='->', color='#555', lw=1.5)) # ── FIGURE 5: Meniere's Disease + Otosclerosis ── fig, axes = plt.subplots(1, 2, figsize=(18, 16)) # --- LEFT: Meniere's Disease --- ax = axes[0] ax.set_xlim(0, 10) ax.set_ylim(0, 16) ax.axis('off') ax.set_facecolor('#f8f9fa') ax.text(5, 15.5, "MÉNIÈRE'S DISEASE\nEtiopathogenesis, Symptoms & Management", ha='center', va='center', fontsize=10, fontweight='bold', color='#1a237e', multialignment='center') box(ax, 5, 14.7, 8, 0.7, 'ETIOPATHOGENESIS: ENDOLYMPHATIC HYDROPS\n(Excess endolymph in membranous labyrinth)', '#1a237e', fontsize=8.5) causes_m = ['Idiopathic\n(most common)', 'Allergy', 'Autoimmune', 'Viral\n(HSV)', 'Obstruction of\nendolymphatic duct'] xs_m = [1, 3, 5, 7, 9] for c, xp in zip(causes_m, xs_m): box(ax, xp, 13.7, 1.7, 0.9, c, '#1565C0', fontsize=7.5) arrow(ax, 5, 14.35, xp, 14.15) box(ax, 5, 12.9, 8, 0.7, 'CLINICAL FEATURES — CLASSIC TETRAD', '#1a237e') tetrad = [('Episodic\nvertigo\n(20min-24h)', '#E53935'), ('Fluctuating\nSNHL\n(low frequency)', '#E53935'), ('Tinnitus\n(roaring/\nlow-pitched)', '#E53935'), ('Aural fullness\n/ pressure', '#E53935')] for i, ((text, col), xp) in enumerate(zip(tetrad, [1.5, 4, 6.5, 9])): box(ax, xp, 11.9, 2.5, 1.7, text, col, fontsize=8) arrow(ax, 5, 12.6, xp, 12.75) # Lermoyez variant box(ax, 5, 10.8, 8, 0.6, "Lermoyez Variant: Tinnitus/deafness IMPROVE with onset of vertigo attack", '#7B1FA2', fontsize=8) # INVESTIGATIONS box(ax, 5, 10.0, 8, 0.6, 'INVESTIGATIONS', '#1a237e') invs_m = ['Pure Tone\nAudiometry\n(low-freq SNHL)', 'Electrocochleography\n(ECochG)\nSP/AP ratio >0.4', 'Glycerol test\n(dehydration test\n→ hearing improves)', 'MRI with\nGadolinium\n(endolymph\nvisualization)', 'Caloric test\n(canal paresis\naffected side)'] xs_inv = [0.8, 3, 5.5, 7.7, 9.3] ys_inv = [8.9]*5 for text, xp, yp in zip(invs_m, xs_inv, ys_inv): box(ax, xp, yp, 2.3, 1.7, text, '#0288D1', fontsize=7) arrow(ax, 5, 9.7, xp, 9.75) # Management box(ax, 5, 7.7, 8, 0.6, 'MANAGEMENT', '#1a237e') # Medical box(ax, 2.5, 6.5, 4, 2.3, 'MEDICAL (Acute attack):\n— Betahistine 16-24mg TDS\n (mainstay)\n— Prochlorperazine\n (for vertigo)\n— Diuretics\n (Frusemide/HCTZ)\n— Low-salt diet (<1g/day)\n— Avoid caffeine, alcohol', '#388E3C', fontsize=7.5) arrow(ax, 5, 7.4, 2.5, 7.65) # Surgical box(ax, 7.5, 6.5, 4, 2.3, 'SURGICAL/ABLATIVE:\n— IT Gentamicin\n (chemical labyrinthectomy)\n— IT Steroids\n (dexamethasone)\n— Endolymphatic sac\n decompression\n— Labyrinthectomy\n— Vestibular neurectomy\n (hearing preserved)', '#AD1457', fontsize=7.5) arrow(ax, 5, 7.4, 7.5, 7.65) box(ax, 5, 4.7, 8, 0.7, 'STAGING (AAO-HNS): Stage I-IV (by PTA)\nStage I:<25dB | II:26-40 | III:41-70 | IV:>70dB', '#37474F', fontsize=8) # --- RIGHT: Otosclerosis --- ax2 = axes[1] ax2.set_xlim(0, 10) ax2.set_ylim(0, 16) ax2.axis('off') ax2.set_facecolor('#f8f9fa') ax2.text(5, 15.5, 'OTOSCLEROSIS (OTOSPONGIOSIS)\nEtiology, Features & Management', ha='center', va='center', fontsize=10, fontweight='bold', color='#1a237e', multialignment='center') box(ax2, 5, 14.7, 8, 0.7, 'DEFINITION: Abnormal bony remodelling of otic capsule\n→ Stapedial fixation → Conductive Hearing Loss', '#1a237e', fontsize=8.5) # Etiology box(ax2, 5, 13.8, 8, 0.6, 'ETIOLOGY (multifactorial)', '#1a237e') eti = ['Autosomal\ndominant\n(variable penetrance)', 'Female > Male\n(2:1)', 'Pregnancy\n(accelerates)', 'Measles\nvirus\n(proposed)', 'Fluoride\ndeficiency'] xs_e = [1, 3, 5, 7.2, 9] for e, xp in zip(eti, xs_e): box(ax2, xp, 12.9, 1.7, 1.5, e, '#1565C0', fontsize=7.5) arrow(ax2, 5, 13.5, xp, 13.65) # Clinical features box(ax2, 5, 11.9, 8, 0.6, 'CLINICAL FEATURES', '#1a237e') cfs2 = ['Progressive\nbilateral CHL\n(insidious onset\n15-45 yrs)', 'Paracusis\nWillisi\n(hear better\nin noisy env)', 'Tinnitus\n(usually low\nfrequency)', 'Schwartz\nsign\n(Flamingo pink\nhue through TM)'] for c, xp in zip(cfs2, [1.5, 4, 6.8, 9.2]): box(ax2, xp, 10.9, 2.5, 1.6, c, '#0097A7', fontsize=7.5) arrow(ax2, 5, 11.6, xp, 11.7) # Audiometric features box(ax2, 5, 9.8, 8, 0.6, 'AUDIOMETRIC FEATURES', '#1a237e') box(ax2, 2.5, 8.8, 4, 1.5, 'PTA: CHL pattern\n(high ABG)\nCarhart\'s notch at 2000Hz\n(mechanical notch — artifact)', '#4527A0', fontsize=8) box(ax2, 7.5, 8.8, 4, 1.5, 'Impedance (Tympanometry):\nType As (shallow/stiff)\nor Type B pattern\nAbsent stapedius reflex', '#4527A0', fontsize=8) arrow(ax2, 5, 9.5, 2.5, 9.55) arrow(ax2, 5, 9.5, 7.5, 9.55) # Tuning fork box(ax2, 5, 7.7, 8, 0.7, 'Tuning Fork Tests: Rinne NEGATIVE (BC>AC) | Weber LATERALISES to worse ear\n(Both ears affected in 70% — Weber may be midline)', '#37474F', fontsize=8) # Management box(ax2, 5, 6.8, 8, 0.6, 'MANAGEMENT', '#1a237e') box(ax2, 2.5, 5.6, 4, 2.0, 'MEDICAL:\n— Sodium fluoride\n 10mg TDS (arrests\n progression)\n— Vitamin D\n— Hearing aid\n (definitive non-surgical\n alternative)', '#388E3C', fontsize=7.5) box(ax2, 7.5, 5.6, 4, 2.0, 'SURGICAL: STAPEDECTOMY\n(Gold standard)\n— Remove stapes\n— Replace with\n Teflon piston\n prosthesis on\n oval window\nSuccess rate: 90%\nRisk: SNHL (1-2%)', '#AD1457', fontsize=7.5) arrow(ax2, 5, 6.5, 2.5, 6.6) arrow(ax2, 5, 6.5, 7.5, 6.6) box(ax2, 5, 4.1, 8, 0.8, "CARHART'S NOTCH:\nDip in bone conduction at 2000 Hz in audiogram\nNot true SNHL — due to loss of ossicular resonance\nResolves after stapedectomy", '#1B5E20', fontsize=8) box(ax2, 5, 2.9, 8, 0.6, "PARACUSIS WILLISI: Hearing better in noisy environments\n(background noise forces others to raise voice to match)", '#37474F', fontsize=8) plt.tight_layout() plt.savefig('/tmp/workspace/ent-answers/fig5_meniere_otosclerosis.png', dpi=150, bbox_inches='tight') plt.close() print("Fig 5 saved") PYEOF
python3 << 'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch def box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9): ax.add_patch(FancyBboxPatch((x-w/2, y-h/2), w, h, boxstyle='round,pad=0.1', facecolor=color, edgecolor='#333', linewidth=1.2)) ax.text(x, y, text, ha='center', va='center', fontsize=fontsize, color=textcolor, fontweight='bold', multialignment='center') def arrow(ax, x1, y1, x2, y2): ax.annotate('', xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle='->', color='#555', lw=1.5)) # ── FIGURE 6: Miscellaneous Short Answers — Ear ── fig, axes = plt.subplots(2, 2, figsize=(18, 16)) fig.patch.set_facecolor('#f8f9fa') # ─ Panel A: Facial Nerve Course ─ ax = axes[0][0] ax.set_xlim(0, 10) ax.set_ylim(0, 10) ax.axis('off') ax.set_facecolor('#f8f9fa') ax.text(5, 9.6, 'INTRATEMPORAL COURSE OF FACIAL NERVE (CN VII)', ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') segments = [ ('Meatal\nsegment\n(IAC, 8-10mm)', '#1565C0'), ('Labyrinthine\nsegment\n(3-4mm)\nGeniculate ganglion', '#1565C0'), ('Greater\nsuperficial\npetrosal n.\n(parasympathetics\nto lacrimal gland)', '#0097A7'), ('Tympanic\nsegment\n(horizontal, 11mm)\nRuns over oval window', '#1565C0'), ('Nerve to\nstapedius\n(hyperacusis if\nlesion above)', '#0097A7'), ('Mastoid\nsegment\n(vertical, 13mm)', '#1565C0'), ('Chorda\ntympani n.\n(taste anterior 2/3\ntongue + submand gland)', '#0097A7'), ('Stylomastoid\nforamen\n(exits skull)', '#E53935'), ] ys_fn = [8.8, 7.8, 7.3, 6.5, 5.8, 5.0, 4.3, 3.3] xs_fn = [5, 5, 8, 5, 8, 5, 8, 5] cols_fn = [s[1] for s in segments] for i, ((seg, col), xp, yp) in enumerate(zip(segments, xs_fn, ys_fn)): box(ax, xp, yp, 4.5 if xp==5 else 4.2, 1.0, seg, col, fontsize=7.5) if i>0 and xs_fn[i-1]==5 and xs_fn[i]==5: arrow(ax, 5, ys_fn[i-1]-0.5, 5, yp+0.5) if xp==8: ax.annotate('', xy=(6.1, yp), xytext=(5, ys_fn[i-1]-0.1), arrowprops=dict(arrowstyle='->', color='#0097A7', lw=1, linestyle='dashed')) arrow(ax, 5, 3.3-0.5, 5, 2.5) box(ax, 5, 2.1, 4.5, 0.6, 'Parotid plexus → 5 branches: Temporal, Zygomatic, Buccal, Marginal mandibular, Cervical', '#C62828', fontsize=7) # ─ Panel B: Tympanoplasty types ─ ax2 = axes[0][1] ax2.set_xlim(0, 10) ax2.set_ylim(0, 10) ax2.axis('off') ax2.set_facecolor('#f8f9fa') ax2.text(5, 9.6, 'TYMPANOPLASTY — WULLSTEIN CLASSIFICATION', ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') types = [ ('Type I\n(MYRINGOPLASTY)\nIntact ossicles\nGraft on TM', '#388E3C'), ('Type II\nMalleus eroded\nGraft on incus', '#43A047'), ('Type III\nMalleus & incus\neroded\nGraft on stapes\nhead (Columella)', '#FB8C00'), ('Type IV\nAll ossicles gone\nExcept stapes\nfootplate (mobile)\nSmall sound window', '#F57F17'), ('Type V\nStapes footplate\nfixed\n(otosclerosis)\nFenestration\nof lateral\nsemicircular canal', '#C62828'), ] ys_t = [8.5, 7.2, 5.9, 4.4, 2.7] for (text, col), yp in zip(types, ys_t): box(ax2, 5, yp, 9, 1.0, text, col, fontsize=8) if yp != ys_t[0]: arrow(ax2, 5, ys_t[ys_t.index(yp)-1]-0.5, 5, yp+0.5) # ─ Panel C: Cochlear Implant ─ ax3 = axes[1][0] ax3.set_xlim(0, 10) ax3.set_ylim(0, 10) ax3.axis('off') ax3.set_facecolor('#f8f9fa') ax3.text(5, 9.6, 'COCHLEAR IMPLANT — Indications & Components', ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') box(ax3, 5, 8.8, 9, 0.6, 'INDICATION: Profound bilateral SNHL with poor hearing aid benefit', '#1a237e', fontsize=8.5) comp = [('Microphone\n(external)', '#1565C0'), ('Speech\nProcessor\n(external)', '#1565C0'), ('Transmitter\ncoil\n(external, magnetic)', '#1565C0'), ('Receiver-\nstimulator\n(implanted, bone)', '#AD1457'), ('Electrode\narray\n(cochlea, 22 channels)', '#AD1457')] xs_c = [1, 3, 5.5, 7.5, 9.2] for c, xp in zip(comp, xs_c): box(ax3, xp, 7.7, 1.8, 1.3, c[0], c[1], fontsize=7.5) arrow(ax3, 5, 8.5, xp, 8.35) box(ax3, 5, 6.5, 9, 0.8, 'SELECTION CRITERIA:\n— Age: >12 months | Bilateral profound SNHL\n— PTA >90dB | Speech discrimination <50% with HAs\n— No medical contraindication | Motivated family', '#0288D1', fontsize=7.5) box(ax3, 5, 5.4, 9, 0.6, 'CONTRAINDICATIONS: Cochlear aplasia | Absent CN VIII | Severe CSOM', '#C62828', fontsize=8) box(ax3, 5, 4.5, 9, 0.8, 'OUTCOMES:\n— Best results: Prelingual deafness with early implantation\n— Post-lingual deafness: Excellent results\n— Requires auditory-verbal therapy (AVT) post-implant', '#388E3C', fontsize=7.5) box(ax3, 5, 3.4, 9, 0.6, 'COMPLICATIONS: Device failure | Infection | Perilymph gusher | Meningitis (rare)', '#BF360C', fontsize=8) box(ax3, 5, 2.6, 9, 0.7, 'BAHA (Bone-Anchored Hearing Aid): For unilateral deafness,\ncongenital CHL (atresia), ossicular fixation — bypasses ME\nOsseointegration with titanium implant in skull', '#37474F', fontsize=7.5) # ─ Panel D: Acoustic Neuroma / Vestibular Schwannoma ─ ax4 = axes[1][1] ax4.set_xlim(0, 10) ax4.set_ylim(0, 10) ax4.axis('off') ax4.set_facecolor('#f8f9fa') ax4.text(5, 9.6, 'ACOUSTIC NEUROMA\n(VESTIBULAR SCHWANNOMA)', ha='center', fontsize=9.5, fontweight='bold', color='#1a237e', multialignment='center') box(ax4, 5, 8.7, 9, 0.6, 'Origin: Superior vestibular nerve (CN VIII) — Schwann cells at glial-Schwann junction (Obersteiner-Redlich zone)', '#1a237e', fontsize=7.5) cfs4 = [('Unilateral progressive\nSNHL (90%)\n(High frequency first)', '#E53935'), ('Tinnitus\n(high-pitched,\nunilateral)', '#E53935'), ('Unsteadiness/\ndisequilibrium\n(rarely acute vertigo)', '#E53935'), ('Facial numbness\n(V nerve — large\ntumours)', '#E53935'), ("Hitselberger's sign\n(absent sensation\nposterior EAC wall)", '#E53935')] xs_cf = [1, 3, 5, 7.3, 9.3] for (text, col), xp in zip(cfs4, xs_cf): box(ax4, xp, 7.5, 1.8, 1.3, text, col, fontsize=7) arrow(ax4, 5, 8.4, xp, 8.15) box(ax4, 5, 6.5, 9, 0.8, 'INVESTIGATIONS:\n— MRI with gadolinium (GOLD STANDARD — "ice-cream on cone" sign at IAC)\n— BERA (increased I-V interpeak latency)\n— PTA (high frequency SNHL)\n— ABR, Caloric test (canal paresis)', '#0288D1', fontsize=7.5) # Staging Koos box(ax4, 5, 5.4, 9, 0.7, 'KOOS GRADING: I (IAC only) → II (<2cm) → III (large, brainstem contact) → IV (compresses brainstem)', '#1565C0', fontsize=8) # Management box(ax4, 5, 4.5, 9, 0.7, 'MANAGEMENT:', '#1a237e', fontsize=8.5) mgmt4 = [('Observation\n+ serial MRI\n(elderly, small)', '#388E3C'), ('Stereotactic\nRadiosurgery\n(Gamma Knife)\n<3cm', '#43A047'), ('Surgery:\nTranslabyrinthine\nor Middle fossa\nor Retrosigmoid\napproach', '#AD1457')] for (m, col), xp in zip(mgmt4, [2, 5, 8]): box(ax4, xp, 3.4, 3.0, 1.8, m, col, fontsize=7.5) arrow(ax4, 5, 4.15, xp, 4.3) box(ax4, 5, 2.1, 9, 0.9, 'NF2 (Neurofibromatosis type 2): BILATERAL acoustic neuromas\nAutosomal dominant | Chromosome 22 mutation (merlin/schwannomin)\nOther features: Meningiomas, ependymomas, lens opacities', '#37474F', fontsize=7.5) plt.tight_layout() plt.savefig('/tmp/workspace/ent-answers/fig6_ear_misc.png', dpi=150, bbox_inches='tight') plt.close() print("Fig 6 saved") PYEOF
python3 << 'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch def box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9): ax.add_patch(FancyBboxPatch((x-w/2, y-h/2), w, h, boxstyle='round,pad=0.1', facecolor=color, edgecolor='#333', linewidth=1.2)) ax.text(x, y, text, ha='center', va='center', fontsize=fontsize, color=textcolor, fontweight='bold', multialignment='center') def arrow(ax, x1, y1, x2, y2): ax.annotate('', xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle='->', color='#555', lw=1.5)) # ── FIGURE 7: Short Answers (Image paper) ── fig, axes = plt.subplots(2, 2, figsize=(18, 16)) fig.patch.set_facecolor('#f8f9fa') # ─ Panel A: FESS Complications & Counselling ─ ax = axes[0][0] ax.set_xlim(0, 10) ax.set_ylim(0, 10) ax.axis('off') ax.set_facecolor('#f8f9fa') ax.text(5, 9.6, 'Q7: FESS COMPLICATIONS & PRE-OP COUNSELLING', ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') box(ax, 5, 8.9, 9, 0.6, 'FESS = Functional Endoscopic Sinus Surgery', '#1a237e') # Minor complications box(ax, 3, 8.1, 5, 0.6, 'MINOR COMPLICATIONS (5-10%)', '#FB8C00') minor = ['Haemorrhage\n(synechiae)', 'Post-op\nadhesions', 'Anosmia\n(temp)', 'Crusting', 'Infection'] for m, xp in zip(minor, [0.8, 2.8, 5, 7.2, 9.2]): box(ax, xp, 7.2, 1.7, 1.2, m, '#FB8C00', fontsize=7.5) arrow(ax, 3, 7.8, xp, 7.8) box(ax, 7, 8.1, 5, 0.6, 'MAJOR COMPLICATIONS (<1%)', '#C62828') major = ['CSF leak\n(cribriform\nplate injury)', 'Orbital\ncomplications\n(medial wall,\nnasolacrimal\nduct)', 'Optic nerve\ninjury\n→ blindness', 'Carotid artery\ninjury\n(fatal)', 'Intracranial\ninjury\n(meningitis)'] ys_mj = [5.8, 5.8, 5.8, 5.8, 5.8] xs_mj = [0.8, 2.8, 5, 7.2, 9.2] for m, xp in zip(major, xs_mj): box(ax, xp, 5.8, 1.7, 1.5, m, '#C62828', fontsize=7) arrow(ax, 7, 7.8, xp, 6.55) box(ax, 5, 4.7, 9, 0.7, 'COUNSELLING POINTS (Consent):\n1. Up to 10% require revision surgery 2. Nasal packing post-op (24-48h)\n3. Nasal toilet + saline irrigation essential 4. INCS spray long-term', '#1B5E20', fontsize=7.5) box(ax, 5, 3.8, 9, 0.7, '5. Risk of smell change (temp anosmia) 6. Avoid NSAIDs 1 week pre-op\n7. CT scan to be reviewed with patient 8. Possible need for revision\n9. Rare but serious: CSF leak, orbital injury, blindness, death', '#37474F', fontsize=7.5) # ─ Panel B: Inverted Papilloma ─ ax2 = axes[0][1] ax2.set_xlim(0, 10) ax2.set_ylim(0, 10) ax2.axis('off') ax2.set_facecolor('#f8f9fa') ax2.text(5, 9.6, 'Q9: INVERTED PAPILLOMA', ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') box(ax2, 5, 8.9, 9, 0.6, 'Schneiderian papilloma — inverted into stroma (Ringertz tumour)\nHPV 6, 11, 16, 18 implicated | Unilateral | Lateral nasal wall', '#1a237e', fontsize=8) box(ax2, 5, 8.0, 9, 0.6, 'CLINICAL FEATURES', '#1565C0') cfs_ip = ['Unilateral nasal\npolyp', 'Nasal obstruction', 'Epistaxis', 'Anosmia', 'Facial pain'] for cf, xp in zip(cfs_ip, [0.8, 3, 5, 7.2, 9.2]): box(ax2, xp, 7.1, 1.7, 1.2, cf, '#0097A7', fontsize=7.5) arrow(ax2, 5, 7.7, xp, 7.7) box(ax2, 5, 6.2, 9, 0.7, 'Krouse Staging:\nT1: Confined to inferior/middle meatus T2: Any sinus involvement\nT3: Extension to orbit/skull base (extranasal) T4: Malignant transformation', '#4527A0', fontsize=7.5) box(ax2, 5, 5.2, 9, 0.7, 'MALIGNANT TRANSFORMATION: 5-10% → SCC\n(Key concern — must biopsy all polyps to exclude)', '#C62828', fontsize=8) box(ax2, 5, 4.2, 9, 0.7, 'INVESTIGATIONS:\nEndoscopy + CT PNS (for extent, bone erosion, calcification)\nMRI (orbital/skull base extension) | BIOPSY (mandatory)', '#0288D1', fontsize=7.5) box(ax2, 5, 3.2, 9, 0.8, 'MANAGEMENT: SURGICAL (complete excision)\nMedial maxillectomy (Gold standard) — via FESS or lateral rhinotomy\nRecurrence rate: 10-15% (high if incomplete excision)\nLong-term endoscopic follow-up mandatory', '#388E3C', fontsize=7.5) # ─ Panel C: Rhinosporidiosis ─ ax3 = axes[1][0] ax3.set_xlim(0, 10) ax3.set_ylim(0, 10) ax3.axis('off') ax3.set_facecolor('#f8f9fa') ax3.text(5, 9.6, 'Q5: RHINOSPORIDIOSIS', ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') box(ax3, 5, 8.9, 9, 0.6, 'Organism: Rhinosporidium seeberi (classified as mesomycetozoea/protist)\nEndemic: South India, Sri Lanka | Affects: Nasal mucosa, eye, rectum', '#1a237e', fontsize=7.5) box(ax3, 5, 8.0, 9, 0.6, 'MODE OF INFECTION: Contact with stagnant water (bathing in ponds)', '#1565C0', fontsize=8) box(ax3, 5, 7.1, 9, 0.7, 'CLINICAL FEATURES:\n— Sessile/pedunculated polyp (strawberry-like surface, red/pink)\n— Nasal bleeding, obstruction | Fruiting bodies visible in polyp\n— Frequently bilateral | May bleed profusely on manipulation', '#0097A7', fontsize=7.5) box(ax3, 5, 6.0, 9, 0.7, 'DIAGNOSIS:\nEndoscopy (Strawberry mass — tiny white dots = sporangia)\nBiopsy: Large sporangia (300-350μm) containing endospores\nHPE: PAS positive sporangia; Mucicarmine stains wall', '#4527A0', fontsize=7.5) box(ax3, 5, 5.0, 9, 0.7, 'MANAGEMENT:\nSurgical excision + cauterization of base\n(prevents recurrence from released spores)\nDapsone 100mg OD (adjunct — inhibits spore maturation)\nRecurrence common if incomplete excision', '#388E3C', fontsize=7.5) # ─ Panel D: Fungal Rhinosinusitis ─ ax4 = axes[1][1] ax4.set_xlim(0, 10) ax4.set_ylim(0, 10) ax4.axis('off') ax4.set_facecolor('#f8f9fa') ax4.text(5, 9.6, 'Q10: FUNGAL RHINOSINUSITIS', ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') types_fr = [('INVASIVE FUNGAL RHINOSINUSITIS', '#C62828'), ('Acute invasive\n(<4 wks)\nMucor / Aspergillus\nImmunocompromised\n(DM, AIDS, neutropenia)\nHigh mortality', '#AD1457'), ('Chronic invasive\n(>12 wks)\nAspergillus\nSlowly progressive\norbit/intracranial', '#E53935'), ('Granulomatous\ninvasive\nAspergillus flavus\nImmunocompetent\n(Sudan/India)', '#EF5350')] box(ax4, 5, 8.9, 9, 0.5, types_fr[0][0], types_fr[0][1]) for i, (t, col) in enumerate(types_fr[1:]): box(ax4, 1.5 + i*3, 7.7, 2.7, 1.9, t, col, fontsize=7) arrow(ax4, 5, 8.65, 1.5 + i*3, 8.65) types_nin = [('NON-INVASIVE FUNGAL RHINOSINUSITIS', '#1565C0'), ('Fungal ball\n(Aspergillus)\nIn one sinus\n(maxillary usually)\nHyperdense CT\n"dirty grey" density', '#1565C0'), ('Saprophytic\nfungal sinusitis\nFungi on mucus crust\nNo mucosal invasion', '#0288D1'), ('Allergic Fungal\nSinusitis (AFRS)\nAspergillus\nAtopic patient\nAOIS criteria\n"Peanut butter"\nallergic mucin', '#0097A7')] box(ax4, 5, 5.9, 9, 0.5, types_nin[0][0], types_nin[0][1]) for i, (t, col) in enumerate(types_nin[1:]): box(ax4, 1.5 + i*3, 4.8, 2.7, 2.0, t, col, fontsize=7) arrow(ax4, 5, 5.65, 1.5 + i*3, 5.8) box(ax4, 5, 3.3, 9, 0.8, 'MANAGEMENT:\nNon-invasive: FESS + antifungals (itraconazole) ± steroids (AFRS)\nInvasive: Urgent surgical debridement + IV antifungal\n(Amphotericin B — liposomal) + treat underlying disease\nACUTE INVASIVE: EMERGENCY — high mortality (50-80%)', '#1B5E20', fontsize=7.5) box(ax4, 5, 2.2, 9, 0.7, "MUCORMYCOSIS: Mucor/Rhizopus | DKA/immunocompromised\nBlack eschar on palate/nasal mucosa | Angioinvasion → thrombosis\nTx: Surgical debridement + Liposomal Amphotericin B + control DM", '#37474F', fontsize=7.5) plt.tight_layout() plt.savefig('/tmp/workspace/ent-answers/fig7_rhinology_misc.png', dpi=150, bbox_inches='tight') plt.close() print("Fig 7 saved") PYEOF
python3 << 'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch def box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9): ax.add_patch(FancyBboxPatch((x-w/2, y-h/2), w, h, boxstyle='round,pad=0.1', facecolor=color, edgecolor='#333', linewidth=1.2)) ax.text(x, y, text, ha='center', va='center', fontsize=fontsize, color=textcolor, fontweight='bold', multialignment='center') def arrow(ax, x1, y1, x2, y2): ax.annotate('', xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle='->', color='#555', lw=1.5)) # ── FIGURE 8: Rhinology Short Answers ── fig, axes = plt.subplots(2, 2, figsize=(18, 14)) fig.patch.set_facecolor('#f8f9fa') # ─ Panel A: Kiesselbach's Plexus & OMC ─ ax = axes[0][0] ax.set_xlim(0, 10) ax.set_ylim(0, 10) ax.axis('off') ax.set_facecolor('#f8f9fa') ax.text(5, 9.6, "Q11: KIESSELBACH'S PLEXUS (Little's Area)", ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') box(ax, 5, 8.8, 9, 0.6, "Location: Anteroinferior part of nasal septum (mucocutaneous junction)", '#1a237e', fontsize=8.5) vessels = [("Anterior\nethmoidal artery\n(from ophthalmic/ICA)", '#1565C0'), ("Posterior\nethmoidal artery\n(from ophthalmic/ICA)", '#1565C0'), ("Sphenopalatine\nartery\n(from maxillary/ECA)", '#E53935'), ("Greater\npalatine artery\n(from maxillary/ECA)", '#E53935'), ("Superior\nlabial artery\n(from facial/ECA)", '#E53935')] xs_k = [0.8, 2.8, 5, 7.2, 9.2] for (v, col), xp in zip(vessels, xs_k): box(ax, xp, 7.7, 1.7, 1.4, v, col, fontsize=7) arrow(ax, 5, 8.5, xp, 8.45) box(ax, 5, 6.6, 9, 0.7, "CLINICAL SIGNIFICANCE:\n— Most common site of anterior epistaxis (90%)\n— Visible by anterior rhinoscopy\n— Amenable to cautery (silver nitrate)\n— Vulnerable due to anastomosis of ICA + ECA branches", '#0097A7', fontsize=7.5) # OMC ax.text(5, 5.6, "Q12: OSTIOMEATAL COMPLEX (OMC)", ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') box(ax, 5, 4.9, 9, 0.6, "Final common pathway for drainage of anterior sinuses", '#1a237e', fontsize=8.5) components = ["Middle turbinate", "Infundibulum", "Uncinate process", "Hiatus semilunaris", "Maxillary ostium", "Anterior ethmoid cells"] for i, c in enumerate(components): xp = 0.8 + (i%3)*3.5 yp = 4.1 if i < 3 else 3.0 box(ax, xp, yp, 3.2, 0.7, c, '#0288D1', fontsize=8) box(ax, 5, 2.0, 9, 0.7, "SIGNIFICANCE: OMC blockage → Maxillary + anterior ethmoid + frontal sinus disease\nTarget of FESS | Visualized by CT PNS (coronal view)\nDrainage of: Frontal (nasofrontal recess) + Maxillary + Ant. Ethmoid sinuses", '#37474F', fontsize=7.5) # ─ Panel B: Septoplasty vs SMR ─ ax2 = axes[0][1] ax2.set_xlim(0, 10) ax2.set_ylim(0, 10) ax2.axis('off') ax2.set_facecolor('#f8f9fa') ax2.text(5, 9.6, "Q13: SEPTOPLASTY vs SMR\n(Submucous Resection)", ha='center', fontsize=9.5, fontweight='bold', color='#1a237e', multialignment='center') headers = ['Feature', 'Septoplasty', 'SMR (Killian)'] data = [ ['Full name', 'Submucous\nresection & realignment', 'Submucous resection\n(Killian\'s operation)'], ['Principle', 'Correct deviation;\npreserve cartilage', 'Remove deviated\ncartilage/bone'], ['Mucosa', 'Both flaps\npreserved', 'Both flaps\npreserved'], ['Cartilage', 'Repositioned\n(preserved)', 'Resected\n(removed)'], ['Support', 'Nasal tip support\nmaintained', 'May lose dorsal\nsupport (saddle nose)'], ['Indication', 'Deviated nasal\nseptum (any)', 'Limited to caudal\nor body deviations'], ['Age limit', 'After 17-18 yrs\n(growth complete)', 'After 17-18 yrs'], ['Complication', 'Septal haematoma\nPerforation', 'Saddle nose deformity\n(if L-strut lost)'], ['Preferred', 'YES (modern\npreferred)', 'Older technique'], ] col_colors = ['#1a237e', '#1565C0', '#AD1457'] row_colors = ['#E8EAF6', '#EDE7F6', '#E8F5E9'] y_start = 8.7 for i, row in enumerate(data): yp = y_start - i*0.87 for j, (cell, hdr_c, rc) in enumerate(zip(row, col_colors, ['#E8EAF6','#EDE7F6','#E8F5E9'])): fc = col_colors[j] if yp > 8.4 else rc tc = 'white' if yp > 8.4 else '#1a237e' box(ax2, 1.2 + j*3.5, yp, 3.2, 0.75, cell, fc, tc, fontsize=7 if i>0 else 8) # headers for j, (h, col) in enumerate(zip(headers, col_colors)): box(ax2, 1.2 + j*3.5, y_start, 3.2, 0.75, h, col, fontsize=8.5) # ─ Panel C: Rhinolith ─ ax3 = axes[1][0] ax3.set_xlim(0, 10) ax3.set_ylim(0, 10) ax3.axis('off') ax3.set_facecolor('#f8f9fa') ax3.text(5, 9.6, "Q15: RHINOLITH | Q16: SAMTER'S TRIAD | Q17: CHOANAL ATRESIA", ha='center', fontsize=9, fontweight='bold', color='#1a237e', multialignment='center') box(ax3, 5, 8.7, 9, 0.6, 'RHINOLITH = Calcified foreign body in nasal cavity', '#1a237e', fontsize=8.5) box(ax3, 5, 8.0, 9, 0.6, 'Forms around: FB (endogenous: dried secretion/blood clot OR exogenous: bead, button)\nPresents: Unilateral nasal block + foul-smelling nasal discharge (unilateral)\nTreatment: Removal under GA (fragmentation with forceps) + treat infection', '#1565C0', fontsize=7.5) box(ax3, 5, 7.0, 9, 0.6, "SAMTER'S TRIAD (ASPIRIN EXACERBATED RESPIRATORY DISEASE - AERD):", '#C62828') box(ax3, 5, 6.3, 9, 0.5, "1. NASAL POLYPS + 2. BRONCHIAL ASTHMA + 3. ASPIRIN/NSAID HYPERSENSITIVITY\nMechanism: Aspirin blocks COX-1 → shunts arachidonic acid to lipoxygenase pathway → excess LTC4/LTD4 (leukotrienes)", '#0097A7', fontsize=7.5) box(ax3, 5, 5.4, 9, 0.6, 'CHOANAL ATRESIA:', '#1a237e') box(ax3, 5, 4.7, 9, 0.9, 'Failure of bucconasal membrane resorption at 7th week of embryogenesis\n90% bony, 10% membranous | R>L | Unilateral (presents later) vs Bilateral (neonatal emergency)\nBilateral: Cyclical cyanosis (relieves on crying) | Apnoea | Cannot feed\nCOACHES mnemonic: Coloboma, Heart defects, Atresia choanae, Retarded growth, Genital abnormalities, Ear anomalies (CHARGE syndrome)\nDiagnosis: Inability to pass 6Fr catheter | CT coronal (gold standard)\nManagement: Bilateral = EMERGENCY airway (oral airway/McGovern nipple) → early surgical repair (transnasal endoscopic repair)\nUnilateral = elective surgery', '#4527A0', fontsize=7) # ─ Panel D: Short Answers misc ─ ax4 = axes[1][1] ax4.set_xlim(0, 10) ax4.set_ylim(0, 10) ax4.axis('off') ax4.set_facecolor('#f8f9fa') ax4.text(5, 9.6, "Q18: SEPTAL HAEMATOMA | Q19: ANOSMIA\nQ20: ALLERGIC vs VASOMOTOR RHINITIS", ha='center', fontsize=9, fontweight='bold', color='#1a237e', multialignment='center') box(ax4, 5, 8.7, 9, 0.6, 'SEPTAL HAEMATOMA: Blood between perichondrium and cartilage', '#C62828') box(ax4, 5, 8.0, 9, 0.6, 'Causes: Trauma | Sx: Bilateral nasal block (saddle-shaped swelling) + pain\nRisk: Avascular necrosis of cartilage → saddle nose deformity + abscess formation\nManagement: URGENT incision & drainage + bolster sutures + antibiotics', '#1565C0', fontsize=7.5) box(ax4, 5, 7.0, 9, 0.6, 'ANOSMIA: Complete loss of smell', '#1a237e') box(ax4, 5, 6.3, 9, 0.6, 'Causes: Nasal (polyps, rhinitis, FB) | Neurogenic (head injury, cribriform plate fracture)\nCOVID-19 | Neurodegenerative (Parkinson, Alzheimer) | Medications\nTests: Sniffin sticks | Smell identification tests (UPSIT) | MRI brain + olfactory bulb', '#0288D1', fontsize=7.5) # Allergic vs Vasomotor table ax4.text(5, 5.4, "ALLERGIC vs VASOMOTOR RHINITIS", ha='center', fontsize=9, fontweight='bold', color='#1a237e') rows_avr = [ ['Feature', 'Allergic', 'Vasomotor'], ['Mechanism', 'IgE-mediated\n(Type I hypersensitivity)', 'Autonomic imbalance\n(parasympathetic)'], ['Trigger', 'Allergen (pollen,\ndust, pet dander)', 'Non-specific (cold air,\nsmoke, emotion, posture)'], ['Age', 'Usually <30yrs', 'Usually >20yrs'], ['Eosinophils', 'PRESENT (smear)', 'ABSENT or few'], ['IgE', 'Elevated | +ve RAST/SPT', 'Normal | -ve tests'], ['Dominant Sx', 'Sneezing, itching,\nwatery discharge', 'Nasal block + watery\ndischarge (no itch/sneeze)'], ['Treatment', 'Antihistamines\n+ INCS + Allergen\nimmunotherapy', 'Nasal decongestant\n+ INCS + Ipratropium\nSurgery: LICA/turbinate'] ] y_start2 = 4.9 col_colors2 = ['#37474F', '#1565C0', '#AD1457'] for i, row in enumerate(rows_avr): yp = y_start2 - i*0.62 for j, cell in enumerate(row): fc = col_colors2[j] if i==0 else ['#ECEFF1','#E3F2FD','#FCE4EC'][j] tc = 'white' if i==0 else '#212121' box(ax4, 1.2 + j*3.5, yp, 3.2, 0.55, cell, fc, tc, fontsize=6.5 if i>0 else 7.5) plt.tight_layout() plt.savefig('/tmp/workspace/ent-answers/fig8_rhinology_shorts.png', dpi=150, bbox_inches='tight') plt.close() print("Fig 8 saved") PYEOF
python3 << 'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch def box(ax, x, y, w, h, text, color='#2196F3', textcolor='white', fontsize=9): ax.add_patch(FancyBboxPatch((x-w/2, y-h/2), w, h, boxstyle='round,pad=0.1', facecolor=color, edgecolor='#333', linewidth=1.2)) ax.text(x, y, text, ha='center', va='center', fontsize=fontsize, color=textcolor, fontweight='bold', multialignment='center') def arrow(ax, x1, y1, x2, y2): ax.annotate('', xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle='->', color='#555', lw=1.5)) # ── FIGURE 9: Ear Short Answers (from Question Bank) ── fig, axes = plt.subplots(2, 2, figsize=(18, 16)) fig.patch.set_facecolor('#f8f9fa') # ─ Panel A: Hearing Loss Types + Conductive Causes ─ ax = axes[0][0] ax.set_xlim(0, 10) ax.set_ylim(0, 10) ax.axis('off') ax.set_facecolor('#f8f9fa') ax.text(5, 9.6, 'TYPES OF HEARING LOSS\n& Conductive Deafness Causes', ha='center', fontsize=9.5, fontweight='bold', color='#1a237e', multialignment='center') box(ax, 5, 8.9, 9, 0.6, 'CLASSIFICATION OF HEARING LOSS', '#1a237e') types_hl = [('CONDUCTIVE\n(CHL)\nDefect in sound\ntransmission\n(EAC, TM, ossicles)', '#1565C0'), ('SENSORINEURAL\n(SNHL)\nDefect in cochlea\n(sensory) or\nCN VIII (neural)', '#0097A7'), ('MIXED\nBoth CHL\nand SNHL\ncomponents\npresent', '#388E3C')] for (t, col), xp in zip(types_hl, [2, 5, 8]): box(ax, xp, 7.7, 2.7, 1.9, t, col, fontsize=8) arrow(ax, 5, 8.6, xp, 8.65) box(ax, 5, 6.5, 9, 0.5, 'CAUSES OF CONDUCTIVE HEARING LOSS', '#C62828') chl_causes = { 'EAC': 'Foreign body\nWax (cerumen)\nOtitis externa\nEAC atresia\nExostosis/Osteoma\nCholesteatoma', 'Tympanic\nMembrane': 'Perforation (CSOM)\nSerous OM\nTympanosclerosis\nTrauma', 'Middle Ear': 'Otosclerosis\nOssicular disruption\nTympanosclerosis\nOtitis media\nCholesteatoma\nOtobarotrauma' } xs_c = [2, 5, 8] for (title, causes), xp in zip(chl_causes.items(), xs_c): box(ax, xp, 4.8, 2.7, 2.8, f"{title}:\n{causes}", '#4527A0', fontsize=7) arrow(ax, 5, 6.2, xp, 6.15) box(ax, 5, 3.0, 9, 0.7, 'SUDDEN SNHL: Sudden loss >30dB in 3 contiguous frequencies over <72hrs\nCauses: Vascular (MC), Viral, Autoimmune, Perilymphatic fistula\nTx: Oral/IT steroids (prednisolone 1mg/kg/day), vasodilators, bed rest | Recovery: 65% spontaneous', '#37474F', fontsize=7.5) box(ax, 5, 2.0, 9, 0.7, 'NIHL (Noise-Induced HL): 4000 Hz SNHL notch (4kHz notch)\nC5 dip on audiogram | Bilateral, symmetrical\nPrevention: Hearing protection devices (HPDs) | Noise limits: 85dB/8hrs (OSHA)\nManagement: Remove noise exposure, hearing aids, legal compensation', '#1B5E20', fontsize=7.5) # ─ Panel B: Facial Nerve Palsy - Topodiagnosis ─ ax2 = axes[0][1] ax2.set_xlim(0, 10) ax2.set_ylim(0, 10) ax2.axis('off') ax2.set_facecolor('#f8f9fa') ax2.text(5, 9.6, "TOPODIAGNOSTIC TESTS FOR FACIAL NERVE PALSY\n(Sunderland's Tests)", ha='center', fontsize=9.5, fontweight='bold', color='#1a237e', multialignment='center') tests_fn = [ ('Lacrimation\n(Schirmer\'s test)', 'Tests GSPN branch\n(geniculate ganglion)', 'Lesion proximal to\ngeniculate ganglion'), ('Stapedius reflex\n(Impedance)', 'Tests nerve to\nstapedius', 'Lesion above\nstapedius branch'), ('Taste anterior 2/3\ntongue\n(Electrogustometry)', 'Tests chorda\ntympani', 'Lesion above\nchorda tympani'), ('Salivary flow\n(Submandibular\ncatheterization)', 'Tests chorda\ntympani (parasym)', 'Lesion above\nchorda tympani'), ('Electroneurography\n(ENoG)', 'Quantifies nerve\ndegeneration', '>90% degeneration\n= poor prognosis'), ] hdrs = ['Test', 'Anatomical\nBranch', 'If Abnormal =\nLesion Location'] y_start3 = 8.7 for j, h in enumerate(hdrs): box(ax2, 1.2 + j*3.2, y_start3, 2.9, 0.6, h, '#1a237e', fontsize=8) for i, row in enumerate(tests_fn): yp = y_start3 - (i+1)*0.88 cols_r = ['#1565C0','#0097A7','#4527A0'] for j, (cell, col) in enumerate(zip(row, cols_r)): box(ax2, 1.2 + j*3.2, yp, 2.9, 0.75, cell, '#E3F2FD', '#212121', fontsize=7) box(ax2, 5, 3.5, 9, 1.5, "BELL'S PALSY:\nIdiopathic LMN facial palsy (most common cause of facial palsy)\nHSV-1 reactivation theory\nSigns: Inability to close eye, forehead uninvolved (LMN — ALL muscles affected)\nTreatment: Prednisolone 60mg/day x 7-10d (within 72h) + Acyclovir\n(controversial for antiviral) + Eye protection\nPrognosis: 85% recover fully; ENoG guides prognosis", '#388E3C', fontsize=7.5) box(ax2, 5, 2.2, 9, 0.7, "RAMSAY HUNT SYNDROME (Herpes Zoster Oticus):\nVZV reactivation in geniculate ganglion\nTriad: LMN facial palsy + Herpetic vesicles (pinna/EAC) + SNHL/vertigo\nTx: Prednisolone + Acyclovir/Valacyclovir (better prognosis)\nPrognosis: Worse than Bell's — only 50-70% recovery", '#7B1FA2', fontsize=7.5) # ─ Panel C: Hearing Rehabilitation ─ ax3 = axes[1][0] ax3.set_xlim(0, 10) ax3.set_ylim(0, 10) ax3.axis('off') ax3.set_facecolor('#f8f9fa') ax3.text(5, 9.6, "HEARING REHABILITATION OF DEAF CHILD\n+ AUDITORY TESTS", ha='center', fontsize=9.5, fontweight='bold', color='#1a237e', multialignment='center') box(ax3, 5, 8.8, 9, 0.5, 'HEARING ASSESSMENT IN CHILDREN (Age-appropriate tests)', '#1a237e') tests_aud = [ ('0-6 months:\nBERA/ABR\n(Brainstem\nEvoked Response\nAudiometry)', '#1565C0'), ('6-24 months:\nBOA\n(Behavioural\nObservation\nAudiometry)', '#1565C0'), ('2-5 yrs:\nVRA\n(Visual\nReinforcement\nAudiometry)', '#1565C0'), ('>5 yrs:\nPure Tone\nAudiometry\n(standard)', '#1565C0'), ('All ages:\nOAE\n(Otoacoustic\nEmissions)\nnewborn screen', '#388E3C'), ] xs_ta = [0.8, 2.9, 5, 7.1, 9.2] for (t, col), xp in zip(tests_aud, xs_ta): box(ax3, xp, 7.7, 1.9, 1.8, t, col, fontsize=7.5) arrow(ax3, 5, 8.55, xp, 8.6) box(ax3, 5, 6.5, 9, 0.6, 'REHABILITATION ALGORITHM', '#1a237e') reha = [('Mild-Moderate SNHL\n(26-70dB)\n→ Conventional\nHearing Aid\n(BTE/ITE/ITC/CIC)', '#0097A7'), ('Severe SNHL\n(71-90dB)\n→ Powerful HA\nor Cochlear\nImplant candidate', '#FB8C00'), ('Profound SNHL\n(>90dB)\n→ COCHLEAR\nIMPLANT\n(best outcome)', '#C62828'), ('Conductive HL\n(atresia)\n→ BAHA\n(Bone-Anchored\nHearing Aid)', '#7B1FA2')] for (r, col), xp in zip(reha, [1.5, 3.7, 6.3, 8.5]): box(ax3, xp, 5.3, 2.8, 2.0, r, col, fontsize=7.5) arrow(ax3, 5, 6.2, xp, 6.3) box(ax3, 5, 4.0, 9, 0.7, 'AUDITORY-VERBAL THERAPY (AVT): After cochlear implant\nGoal: Develop spoken language using residual/implanted hearing\nFor maximum benefit: Implantation before 2 years of age\n3-6 months: Implant assessment → 6-12m: surgery → lifelong AVT', '#4527A0', fontsize=7.5) # ─ Panel D: Tinnitus + Glomus ─ ax4 = axes[1][1] ax4.set_xlim(0, 10) ax4.set_ylim(0, 10) ax4.axis('off') ax4.set_facecolor('#f8f9fa') ax4.text(5, 9.6, "TINNITUS & GLOMUS TUMOUR", ha='center', fontsize=9.5, fontweight='bold', color='#1a237e') box(ax4, 5, 8.9, 9, 0.5, 'TINNITUS = Perception of sound without external stimulus', '#1a237e') box(ax4, 5, 8.2, 9, 0.6, 'Classification:\nSUBJECTIVE (only patient hears) vs OBJECTIVE (examiner can hear with stethoscope)\nPulsatile vs Non-pulsatile', '#1565C0', fontsize=8) tcauses = ['Conductive:\nWax, OME\nOtosclerosis', 'Sensorineural:\nNoise, Meniere\'s\nAcoustic neuroma', 'Vascular (pulsatile):\nGlomus, AVM\nHTN, Anaemia', 'Drugs:\nAspirin, Loop\ndiuretics, Quinine\nAminoglycosides'] for tc, xp in zip(tcauses, [1.5, 4, 6.5, 9]): box(ax4, xp, 7.1, 2.7, 1.3, tc, '#0097A7', fontsize=7) arrow(ax4, 5, 7.9, xp, 7.75) box(ax4, 5, 6.1, 9, 0.5, 'Management: TRT (Tinnitus Retraining Therapy), CBT, masking, treat underlying cause, melatonin', '#37474F', fontsize=7.5) box(ax4, 5, 5.3, 9, 0.5, 'GLOMUS TUMOUR (Paraganglioma) — most common tumour of middle ear', '#C62828') box(ax4, 5, 4.7, 9, 0.7, 'Glomus Tympanicum: On promontory (inside ME)\nGlomus Jugulare: Jugular bulb → extends into ME\nFeatures: Pulsatile tinnitus + Conductive HL + Red pulsating mass behind TM\nBrown\'s sign: Blanching of mass on pneumatic otoscopy\nSchwartze sign (vascular) seen', '#4527A0', fontsize=7.5) box(ax4, 5, 3.8, 9, 0.7, 'Investigations: CT temporal bone (bone erosion), MRI (salt-and-pepper pattern)\nAngiography (vascular supply), Catecholamines/24hr urine (multicentric)\nManagement: Surgery (tympanotomy/infratemporal fossa) ± pre-op embolization\nRadiotherapy for large/inoperable tumours', '#388E3C', fontsize=7.5) box(ax4, 5, 2.8, 9, 0.7, "PREAURICULAR SINUS:\nCongenital pit/fistula anterior to tragus (ascending helix)\nEmbryological: Failure of fusion of auricular hillocks (I, II of 1st arch)\nPersistent sinus tract → recurrent infection → abscess\nManagement: Excision of entire sinus tract (Bowen technique)\nAntibiotic cover for infection pre-operatively", '#1B5E20', fontsize=7.5) box(ax4, 5, 1.8, 9, 0.7, "STAPEDECTOMY:\nIndication: Otosclerosis with ABG >25dB (if HA rejected)\nProcedure: Remove stapes suprastructure, mobile footplate, insert piston prosthesis\n(Teflon piston 0.4-0.6mm) on round window fat graft/vein\nComplications: SNHL (dead ear 1%), perilymph gusher, vertigo, facial palsy, altered taste", '#AD1457', fontsize=7.5) plt.tight_layout() plt.savefig('/tmp/workspace/ent-answers/fig9_ear_shorts.png', dpi=150, bbox_inches='tight') plt.close() print("Fig 9 saved") PYEOF
ls /tmp/workspace/ent-answers/