ENT
| Fiber Type | Function |
|---|---|
| Special Visceral Efferent (SVE) | Motor supply to muscles of facial expression, stapedius, stylohyoid, posterior belly of digastric |
| General Visceral Efferent (GVE) | Parasympathetic supply to lacrimal gland (via GSPN), submandibular and sublingual glands (via chorda tympani) |
| Special Visceral Afferent (SVA) | Taste from anterior 2/3 of tongue (via chorda tympani), tonsillar fossae, and posterior palate (via GSPN) |
| General Somatic Afferent (GSA) | Sensation from EAC and conchal skin of auricle |
| Visceral Afferent | From mucosa of nose, pharynx, and palate |

| Facial Nerve Segment | Surgical Landmark |
|---|---|
| Labyrinthine segment | Vertical crest (Bill's bar) in IAC; cochlea (superior) |
| Geniculate ganglion | Cochleariform process (medially); tegmen (superiorly); middle fossa dura |
| Tympanic segment | Cochleariform process anteriorly; oval window niche inferiorly; lateral SCC |
| Second genu | Just anteroinferior to the lateral semicircular canal; anterior to short process of incus |
| Mastoid segment | Posterior to digastric ridge; medial to tympanomastoid suture; lateral to jugular bulb |
| Stylomastoid foramen | Digastric ridge (tympanomastoid suture); tragal pointer (pointer of tragal cartilage ~1 cm anteromedial); posterior belly of digastric |
| Feature | UMN Palsy (Supranuclear) | LMN Palsy (Infranuclear) |
|---|---|---|
| Forehead sparing | YES - forehead spared (bilateral cortical supply to upper face) | NO - forehead involved (all muscles affected) |
| Eye closure | Preserved (or only mildly affected) | Impaired - lagophthalmos |
| Bell's phenomenon | Absent | Present |
| Emotional movements | May be selectively preserved (emotional vs. volitional dissociation) | Both volitional and emotional affected equally |
| Taste, lacrimation, salivation | Normal | May be affected (depends on level) |
| Cause | Stroke, brain tumor, MS (contralateral hemisphere) | Bell's palsy, Ramsay Hunt, otitis media, parotid tumor, trauma |
| Associated findings | Contralateral limb weakness, hemiplegia | Isolated facial palsy possible |
| Side of weakness | Contralateral lower face to lesion | Ipsilateral entire face |
| Test | Branch Tested | Level Assessed |
|---|---|---|
| Schirmer's Test (Lacrimation test) | Greater Superficial Petrosal Nerve (GSPN) | Proximal to / at geniculate ganglion (labyrinthine segment) |
| Stapedial Reflex (Acoustic reflex) | Nerve to stapedius | At / proximal to pyramidal eminence (tympanic-mastoid junction) |
| Taste testing (anterior 2/3 tongue) | Chorda tympani | At / proximal to mid-mastoid segment |
| Submandibular salivary flow (Salivary flow test) | Chorda tympani → submandibular ganglion | At / proximal to chorda tympani origin |
Brainstem → Geniculate → Pyramidal → Chorda tympani → Stylomastoid → Parotid
ganglion eminence (mid-mastoid) foramen
↓ ↓ ↓
Schirmer Stapedial Taste test
(GSPN) reflex Salivary flow
| Complication | Mechanism | Management |
|---|---|---|
| Exposure keratitis / corneal ulceration | Lagophthalmos → corneal drying and abrasion | Eye care, lubricants, tarsorrhaphy |
| Synkinesis | Aberrant reinnervation (axons regrow to wrong muscles) | Botulinum toxin, physiotherapy |
| Hemifacial spasm | Abnormal ephaptic transmission after reinnervation | Botulinum toxin, microvascular decompression |
| Contracture | Fibrosis of denervated muscles | Physiotherapy, splinting |
| Crocodile tears (gustatory lacrimation) | Aberrant regeneration of salivary fibers → lacrimal gland | Common after Bell's palsy recovery; botulinum toxin |
| Psychological disturbance | Body image, communication difficulty | Counseling, support groups |
| Ectropion | Sagging of lower eyelid | Surgical correction |
| Dysarthria and dysphagia | Buccinator and orbicularis dysfunction | Speech therapy |
Make pdf
ls /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace
mkdir -p /home/daytona/workspace/facial-nerve-palsy && python3 -c "import reportlab; print('reportlab ok')" && python3 -c "import weasyprint; print('weasyprint ok')" 2>&1 || true
~/facial-nerve-palsy/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
OUTPUT = "/home/daytona/workspace/facial-nerve-palsy/Facial_Nerve_Palsy_ENT.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=20*mm, rightMargin=20*mm,
topMargin=18*mm, bottomMargin=18*mm,
title="Facial Nerve Palsy – ENT Case Study",
author="Orris Medical AI"
)
W, H = A4
styles = getSampleStyleSheet()
# ── Custom styles ──────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1a3355")
TEAL = colors.HexColor("#00796b")
LTBLUE = colors.HexColor("#e3f0fa")
LTGRN = colors.HexColor("#e8f5e9")
LTYEL = colors.HexColor("#fffde7")
HEADER_BG = colors.HexColor("#1a3355")
ALT1 = colors.HexColor("#f0f4f8")
ALT2 = colors.white
def style(name, **kw):
s = ParagraphStyle(name, **kw)
return s
title_style = style("MyTitle",
fontName="Helvetica-Bold", fontSize=20, textColor=colors.white,
alignment=TA_CENTER, leading=26, spaceAfter=4)
subtitle_style = style("MySubtitle",
fontName="Helvetica", fontSize=11, textColor=colors.HexColor("#b0c4de"),
alignment=TA_CENTER, leading=14, spaceAfter=2)
h1 = style("H1",
fontName="Helvetica-Bold", fontSize=13, textColor=colors.white,
backColor=NAVY, alignment=TA_LEFT, leading=18,
spaceBefore=10, spaceAfter=6,
leftIndent=4, rightIndent=4,
borderPad=4)
h2 = style("H2",
fontName="Helvetica-Bold", fontSize=11, textColor=TEAL,
leading=15, spaceBefore=8, spaceAfter=4, leftIndent=0)
h3 = style("H3",
fontName="Helvetica-BoldOblique", fontSize=10, textColor=NAVY,
leading=14, spaceBefore=5, spaceAfter=3, leftIndent=6)
body = style("Body",
fontName="Helvetica", fontSize=9.5, textColor=colors.HexColor("#222222"),
leading=14, spaceAfter=4, alignment=TA_JUSTIFY, leftIndent=4)
bullet = style("Bullet",
fontName="Helvetica", fontSize=9.5, textColor=colors.HexColor("#222222"),
leading=13, spaceAfter=2, leftIndent=14, firstLineIndent=-10)
bold_body = style("BoldBody",
fontName="Helvetica-Bold", fontSize=9.5, textColor=NAVY,
leading=13, spaceAfter=2, leftIndent=4)
caption = style("Caption",
fontName="Helvetica-Oblique", fontSize=8.5, textColor=colors.HexColor("#555555"),
alignment=TA_CENTER, leading=11, spaceAfter=4)
case_style = style("Case",
fontName="Helvetica", fontSize=9.5, textColor=colors.HexColor("#1a1a1a"),
backColor=LTBLUE, leading=14, spaceAfter=3, alignment=TA_JUSTIFY,
leftIndent=8, rightIndent=8, borderPad=6)
note_style = style("Note",
fontName="Helvetica-Oblique", fontSize=8.5, textColor=colors.HexColor("#444444"),
backColor=LTYEL, leading=12, spaceAfter=3, leftIndent=6, rightIndent=6)
def tbl(data, col_widths, hdr_rows=1, alt_rows=True, hdr_bg=NAVY, hdr_fg=colors.white):
ts = [
('BACKGROUND', (0,0), (-1, hdr_rows-1), hdr_bg),
('TEXTCOLOR', (0,0), (-1, hdr_rows-1), hdr_fg),
('FONTNAME', (0,0), (-1, hdr_rows-1), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 9),
('LEADING', (0,0), (-1,-1), 12),
('VALIGN', (0,0), (-1,-1), 'TOP'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING',(0,0),(-1,-1), 4),
('LEFTPADDING',(0,0), (-1,-1), 6),
('RIGHTPADDING',(0,0),(-1,-1), 6),
('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#aaaaaa")),
('ROWBACKGROUNDS', (0, hdr_rows), (-1,-1), [ALT1, ALT2] if alt_rows else [ALT2]),
]
t = Table(data, colWidths=col_widths, repeatRows=hdr_rows)
t.setStyle(TableStyle(ts))
return t
def wrap(text, sty):
return Paragraph(text, sty)
def b(text): return f"<b>{text}</b>"
def i(text): return f"<i>{text}</i>"
story = []
# ═══════════════════════════════════════════════════════════════
# COVER BANNER
# ═══════════════════════════════════════════════════════════════
banner_data = [[Paragraph("FACIAL NERVE PALSY", title_style)],
[Paragraph("ENT Case Study & Complete Learning Guide", subtitle_style)],
[Paragraph("Based on: Cummings Otolaryngology · Shambaugh Surgery of the Ear · Bradley & Daroff's Neurology", subtitle_style)]]
banner_tbl = Table(banner_data, colWidths=[170*mm])
banner_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), NAVY),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
('ROUNDEDCORNERS', [6]),
]))
story.append(banner_tbl)
story.append(Spacer(1, 8*mm))
# ═══════════════════════════════════════════════════════════════
# CLINICAL CASE
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("CLINICAL CASE PRESENTATION", h1))
story.append(Spacer(1, 2*mm))
case_box = Table([[Paragraph(
"A <b>35-year-old man</b> presents to ENT OPD with <b>sudden onset weakness of the right side of his face</b> "
"since yesterday morning. He complains of difficulty closing his right eye, drooling of saliva from the right "
"corner of his mouth, and inability to smile properly. He denies limb weakness, headache, loss of "
"consciousness, or recent trauma.",
case_style)]], colWidths=[170*mm])
case_box.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), LTBLUE),
('BOX', (0,0), (-1,-1), 1.5, TEAL),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
]))
story.append(case_box)
story.append(Spacer(1, 4*mm))
story.append(Paragraph(b("On Examination:"), bold_body))
exam_data = [
[wrap(b("Finding"), bold_body), wrap(b("Detail"), bold_body)],
[wrap("Forehead wrinkling", body), wrap("Lost on the right side", body)],
[wrap("Eye closure", body), wrap("Cannot close right eye completely (lagophthalmos)", body)],
[wrap("Nasolabial fold", body), wrap("Flattened on the right", body)],
[wrap("Mouth on smiling", body), wrap("Deviates to the left (unaffected side)", body)],
[wrap("Bell's phenomenon", body), wrap("Present (eye rolls up and out on attempted closure)", body)],
[wrap("Sensory deficits", body), wrap("None", body)],
[wrap("Limb power/reflexes", body), wrap("Normal bilaterally", body)],
]
story.append(tbl(exam_data, [60*mm, 110*mm]))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"⚡ <b>Diagnosis: Bell's Palsy</b> – Right-sided LMN facial palsy (forehead involved + Bell's phenomenon "
"confirms peripheral/infranuclear lesion).",
style("Diag", fontName="Helvetica-Bold", fontSize=10, textColor=colors.HexColor("#ffffff"),
backColor=TEAL, leading=14, spaceAfter=4, leftIndent=6, rightIndent=6, borderPad=5)))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 1 – ANATOMY & FUNCTIONAL COMPONENTS
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 1 – ANATOMY & FUNCTIONAL COMPONENTS OF CN VII", h1))
story.append(Paragraph(
"The facial nerve (CN VII) innervates structures derived from <b>Reichert's cartilage (2nd branchial arch)</b>. "
"Three brainstem nuclei give rise to its fibres:", body))
story.append(Paragraph("• <b>Motor nucleus</b> – caudal pons (SVE)", bullet))
story.append(Paragraph("• <b>Superior salivatory nucleus</b> – dorsal to motor nucleus (GVE)", bullet))
story.append(Paragraph("• <b>Nucleus of the solitary tract</b> – medulla (SVA – taste)", bullet))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(b("Five Fibre Types:"), h2))
ft_data = [
[wrap(b("Fibre Type"), bold_body), wrap(b("Abbreviation"), bold_body), wrap(b("Function"), bold_body)],
[wrap("Special Visceral Efferent", body), wrap("SVE", body),
wrap("Motor to muscles of facial expression, stapedius, stylohyoid, posterior belly of digastric", body)],
[wrap("General Visceral Efferent", body), wrap("GVE", body),
wrap("Parasympathetic to lacrimal gland (via GSPN), submandibular & sublingual glands (via chorda tympani)", body)],
[wrap("Special Visceral Afferent", body), wrap("SVA", body),
wrap("Taste from anterior 2/3 tongue (chorda tympani), tonsillar fossae & palate (GSPN)", body)],
[wrap("General Somatic Afferent", body), wrap("GSA", body),
wrap("Sensation from EAC and conchal skin of auricle", body)],
[wrap("Visceral Afferent", body), wrap("VA", body),
wrap("Mucosa of nose, pharynx, and palate", body)],
]
story.append(tbl(ft_data, [55*mm, 25*mm, 90*mm]))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"<b>Key fact:</b> The <b>superior (rostral) motor nucleus</b> (innervating frontalis & orbicularis oculi) "
"receives <b>bilateral cortical input</b> (crossed + uncrossed). The <b>inferior (caudal) motor nucleus</b> "
"(lower face) receives <b>only contralateral/unilateral</b> input — explaining why UMN lesions spare the forehead.",
note_style))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 2 – COURSE OF THE NERVE
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 2 – COURSE OF THE FACIAL NERVE: ORIGIN TO TERMINAL BRANCHES", h1))
story.append(Paragraph(b("Five Intratemporal Segments (Fallopian Canal):"), h2))
seg_data = [
[wrap(b("Segment"), bold_body), wrap(b("Length"), bold_body),
wrap(b("Course & Key Relations"), bold_body), wrap(b("Branch Given Off"), bold_body)],
[wrap("1. Intracranial", body), wrap("~24 mm", body),
wrap("Lateral pons → porus of IAC; traverses CPA; anterosuperior quadrant at fundus (Bill's bar)", body),
wrap("Nervus intermedius joins here", body)],
[wrap("2. Labyrinthine", body), wrap("~4 mm (shortest & narrowest)", body),
wrap("Fundus of IAC → geniculate ganglion; superior to cochlea; meatal foramen is narrowest point (0.68 mm)", body),
wrap("Greater Superficial Petrosal Nerve (GSPN) – lacrimal gland", body)],
[wrap("3. Tympanic (Horizontal)", body), wrap("~13 mm", body),
wrap("1st genu (geniculate ganglion) → 2nd genu (pyramidal eminence); medial wall of tympanic cavity; "
"superior to cochleariform process & oval window", body),
wrap("Nerve to stapedius", body)],
[wrap("4. Mastoid (Vertical)", body), wrap("~20 mm", body),
wrap("2nd genu at lateral SCC → stylomastoid foramen; anteroinferior to lateral SCC", body),
wrap("Chorda tympani (taste anterior 2/3 tongue + salivary parasympathetics)", body)],
[wrap("5. Extratemporal", body), wrap("Variable", body),
wrap("Exits stylomastoid foramen → posterior auricular nerve → digastric/stylohyoid branches → "
"parotid gland → pes anserinus → terminal branches", body),
wrap("Temporal, Zygomatic, Buccal, Marginal mandibular, Cervical\n"
"Mnemonic: "To Zanzibar By Motor Car"", body)],
]
story.append(tbl(seg_data, [38*mm, 22*mm, 66*mm, 44*mm]))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 3 – SURGICAL LANDMARKS
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 3 – SURGICAL LANDMARKS OF THE FACIAL NERVE", h1))
sl_data = [
[wrap(b("Segment"), bold_body), wrap(b("Surgical Landmark(s)"), bold_body)],
[wrap("Labyrinthine / IAC", body),
wrap("Vertical crest (Bill's bar) separates facial nerve from superior vestibular nerve at fundus", body)],
[wrap("Geniculate ganglion", body),
wrap("Cochleariform process (medial); tegmen (superior); middle fossa dura (superior)", body)],
[wrap("Tympanic segment", body),
wrap("Cochleariform process (anteriorly); oval window niche (inferiorly); lateral SCC (posteriorly)", body)],
[wrap("2nd genu", body),
wrap("Just anteroinferior to lateral semicircular canal; anterior to short process of incus", body)],
[wrap("Mastoid segment", body),
wrap("Posterior to digastric ridge; medial to tympanomastoid suture; lateral to jugular bulb", body)],
[wrap("Stylomastoid foramen", body),
wrap("Digastric ridge (tympanomastoid suture); Tragal pointer (~1 cm anteromedial to tip); posterior belly of digastric", body)],
[wrap("Extratemporal / parotid", body),
wrap("Tympanomastoid suture → foramen 6–8 mm deep; tragal pointer; mastoid tip; posterior belly of digastric", body)],
]
story.append(tbl(sl_data, [45*mm, 125*mm]))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 4 – CLINICAL FEATURES
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 4 – CLINICAL FEATURES OF FACIAL NERVE PALSY", h1))
story.append(Paragraph(b("Motor Features (LMN):"), h2))
for f in [
"<b>Loss of forehead wrinkling</b> – ipsilateral (entire face affected in LMN)",
"<b>Lagophthalmos</b> – inability to close eye completely; widened palpebral fissure",
"<b>Bell's phenomenon</b> – eye rolls upward and laterally on attempted closure (protective reflex)",
"<b>Flattening of nasolabial fold</b> on affected side",
"<b>Deviation of mouth</b> to unaffected side on smiling (contralateral pull)",
"Drooling from ipsilateral angle of mouth",
"Inability to whistle, blow, or puff cheeks",
]:
story.append(Paragraph(f"• {f}", bullet))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(b("Autonomic Features (depending on level of lesion):"), h2))
for f in [
"Reduced tearing (lesion proximal to GSPN – labyrinthine segment or above)",
"Hyperacusis – reduced stapedius function (lesion proximal to pyramidal eminence)",
"Reduced salivation + altered taste (lesion proximal to chorda tympani in mastoid segment)",
"Herpetic vesicles in EAC / concha → Ramsay Hunt syndrome (VZV aetiology)",
]:
story.append(Paragraph(f"• {f}", bullet))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(b("House-Brackmann Grading Scale:"), h2))
hb_data = [
[wrap(b("Grade"), bold_body), wrap(b("Description"), bold_body), wrap(b("Features"), bold_body)],
[wrap("I", body), wrap("Normal", body), wrap("Normal function all areas", body)],
[wrap("II", body), wrap("Slight dysfunction", body),
wrap("Slight forehead movement; complete eye closure with minimal effort; slight asymmetry at rest", body)],
[wrap("III", body), wrap("Moderate dysfunction", body),
wrap("Some forehead movement; complete eye closure with effort; obvious weakness; no synkinesis", body)],
[wrap("IV", body), wrap("Moderately severe", body),
wrap("No forehead movement; incomplete eye closure; obvious disfiguring asymmetry", body)],
[wrap("V", body), wrap("Severe dysfunction", body),
wrap("Barely perceptible motion; asymmetry at rest", body)],
[wrap("VI", body), wrap("Total paralysis", body),
wrap("No movement at all", body)],
]
story.append(tbl(hb_data, [15*mm, 40*mm, 115*mm]))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 5 – UMN vs LMN
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 5 – UMN vs. LMN FACIAL PALSY", h1))
story.append(Paragraph(
"The <b>single most important clinical distinction</b> in facial palsy. Determined by whether the "
"<b>forehead is spared or involved</b>.", body))
story.append(Spacer(1, 2*mm))
ul_data = [
[wrap(b("Feature"), bold_body), wrap(b("UMN (Supranuclear)"), bold_body),
wrap(b("LMN (Infranuclear)"), bold_body)],
[wrap("Forehead sparing", body),
wrap("✅ YES – forehead SPARED (bilateral cortical supply to upper face nucleus)", body),
wrap("❌ NO – forehead INVOLVED (all branches of facial nerve affected)", body)],
[wrap("Eye closure", body),
wrap("Preserved or mildly affected", body),
wrap("Impaired – lagophthalmos present", body)],
[wrap("Bell's phenomenon", body),
wrap("Absent", body),
wrap("Present", body)],
[wrap("Emotional vs volitional", body),
wrap("Dissociation possible: emotional movements preserved", body),
wrap("Both equally affected", body)],
[wrap("Taste / lacrimation", body),
wrap("Normal", body),
wrap("May be affected (level-dependent)", body)],
[wrap("Side of weakness", body),
wrap("Contralateral lower face to hemisphere lesion", body),
wrap("Ipsilateral entire face", body)],
[wrap("Associated CNS signs", body),
wrap("Often: contralateral limb weakness, aphasia, gaze palsy", body),
wrap("Isolated facial palsy usual; no limb signs", body)],
[wrap("Common causes", body),
wrap("Stroke, brain tumour, MS (contralateral hemisphere)", body),
wrap("Bell's palsy, Ramsay Hunt, AOM, parotid tumour, trauma", body)],
]
story.append(tbl(ul_data, [38*mm, 66*mm, 66*mm]))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"<b>Mechanism:</b> The upper face (frontalis, orbicularis oculi) motor nucleus receives <b>bilateral</b> "
"cortical input. A unilateral cortical (UMN) lesion still has intact input from the contralateral "
"hemisphere — so the forehead is spared. The lower face motor nucleus has predominantly <b>unilateral "
"contralateral</b> cortical supply — so UMN lesions cause contralateral lower facial weakness only.",
note_style))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 6 – ELECTRODIAGNOSTIC TESTS
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 6 – ELECTRODIAGNOSTIC TESTS", h1))
story.append(Paragraph(
"Used to determine <b>prognosis</b> and guide surgical decision-making. All tests are useful only in "
"<b>complete paralysis</b>; unnecessary in incomplete palsy (prognosis always good).", body))
story.append(Spacer(1, 2*mm))
ed_data = [
[wrap(b("Test"), bold_body), wrap(b("Principle"), bold_body),
wrap(b("Significant Result"), bold_body), wrap(b("Notes"), bold_body)],
[wrap("1. Nerve Excitability Test (NET)", body),
wrap("Minimal current to produce visible facial twitch; compare both sides over stylomastoid foramen", body),
wrap(">3.5 mA difference = severe degeneration", body),
wrap("Useful first 2–3 weeks only; subjective endpoint", body)],
[wrap("2. Maximal Stimulation Test (MST)", body),
wrap("Uses maximal current; compares movement response (equal / reduced / absent)", body),
wrap("Absent = total degeneration", body),
wrap("More sensitive than NET; simple", body)],
[wrap("3. Electroneurography (ENoG / ENOG)", body),
wrap("Supramaximal stimulation at stylomastoid foramen; CMAP amplitude compared bilaterally", body),
wrap(">90% degeneration vs. normal side = poor prognosis → consider decompression", body),
wrap("Most objective test; begin 3 days after complete paralysis; repeat every 1–3 days", body)],
[wrap("4. Electromyography (EMG)", body),
wrap("Detects spontaneous electrical activity in facial muscles", body),
wrap("Fibrillation potentials = denervation (2–3 wks); Polyphasic potentials = early reinnervation", body),
wrap("Detects reinnervation before clinical movement returns; useful long-term", body)],
[wrap("5. Stapedial / Acoustic Reflex", body),
wrap("Tests stapedius branch integrity", body),
wrap("Absent = lesion at or proximal to stapedius branch", body),
wrap("Topodiagnostic significance; quick and non-invasive", body)],
]
story.append(tbl(ed_data, [38*mm, 46*mm, 46*mm, 40*mm]))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 7 – CAUSES
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 7 – CAUSES OF FACIAL NERVE PALSY", h1))
causes_data = [
[wrap(b("Category"), bold_body), wrap(b("Causes"), bold_body)],
[wrap("Idiopathic (~75%)", body),
wrap("Bell's palsy (HSV-1 reactivation most likely; diagnosis of exclusion)", body)],
[wrap("Infective", body),
wrap("Ramsay Hunt syndrome (VZV – vesicles in EAC, otalgia, SNHL); Acute/chronic otitis media; "
"Malignant otitis externa; Mastoiditis; Lyme disease (Borrelia); HIV; EBV; Mumps", body)],
[wrap("Traumatic", body),
wrap("Temporal bone fracture (transverse > longitudinal for palsy); Birth trauma (forceps); "
"Penetrating injuries; Iatrogenic (parotidectomy, mastoidectomy, middle ear surgery)", body)],
[wrap("Neoplastic", body),
wrap("Facial nerve schwannoma/neuroma; Parotid malignancy; Acoustic neuroma; "
"Glomus jugulare/tympanicum; Cholesteatoma; Metastatic disease", body)],
[wrap("Neurological", body),
wrap("Stroke (UMN – contralateral lower face); Multiple sclerosis; "
"Guillain-Barré (bilateral facial palsy); Möbius syndrome (congenital)", body)],
[wrap("Metabolic / Systemic", body),
wrap("Diabetes mellitus; Pregnancy + pre-eclampsia; "
"Sarcoidosis (Heerfordt syndrome – uveoparotid fever)", body)],
[wrap("Other", body),
wrap("Melkersson-Rosenthal syndrome (recurrent palsy + facial oedema + fissured tongue); "
"Amyloidosis; Wegener's granulomatosis", body)],
]
story.append(tbl(causes_data, [38*mm, 132*mm]))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 8 – TOPODIAGNOSTIC TESTS
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 8 – TOPODIAGNOSTIC TESTS FOR INTRATEMPORAL LESIONS", h1))
story.append(Paragraph(
"These tests localise the level of lesion along the intratemporal facial nerve by sequentially testing "
"branches given off at specific anatomical levels.", body))
story.append(Spacer(1, 3*mm))
topo_data = [
[wrap(b("Test"), bold_body), wrap(b("Branch Tested"), bold_body),
wrap(b("Level Assessed"), bold_body), wrap(b("Method"), bold_body)],
[wrap("Schirmer's Test (Lacrimation)", body),
wrap("Greater Superficial Petrosal Nerve (GSPN)", body),
wrap("Proximal to / at geniculate ganglion (labyrinthine segment)", body),
wrap("Filter paper under eyelid at medial canthus × 5 min. Normal: >25 mm wetting. "
"Abnormal: <25 mm or >50% asymmetry", body)],
[wrap("Stapedial Reflex Testing", body),
wrap("Nerve to stapedius", body),
wrap("At / proximal to pyramidal eminence (tympanic-mastoid junction)", body),
wrap("Acoustic immittance testing; absent reflex = affected", body)],
[wrap("Taste Testing", body),
wrap("Chorda tympani", body),
wrap("At / proximal to mid-mastoid segment", body),
wrap("Electrogustometry or filter paper strips with sweet/sour/salty solutions on anterior 2/3 tongue", body)],
[wrap("Salivary Flow Test (Saxon test)", body),
wrap("Chorda tympani → submandibular ganglion", body),
wrap("At / proximal to chorda tympani origin", body),
wrap("Submandibular flow comparison bilaterally; <25% of normal side = significant", body)],
]
story.append(tbl(topo_data, [38*mm, 38*mm, 42*mm, 52*mm]))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(b("Interpretation Ladder:"), h2))
interp_data = [
[wrap(b("All tests abnormal"), bold_body),
wrap("Lesion at or proximal to geniculate ganglion (labyrinthine/intracranial)", body)],
[wrap(b("Schirmer normal; stapedial, taste abnormal"), bold_body),
wrap("Lesion between GSPN and stapedius branch (tympanic segment)", body)],
[wrap(b("Schirmer + Stapedial normal; taste abnormal"), bold_body),
wrap("Lesion between stapedius branch and chorda tympani origin (upper mastoid)", body)],
[wrap(b("All normal; only motor palsy"), bold_body),
wrap("Lesion at or distal to stylomastoid foramen (extratemporal / parotid)", body)],
]
story.append(tbl(interp_data, [68*mm, 102*mm], hdr_rows=0, hdr_bg=TEAL))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(
"<i>Note: Topodiagnostic tests have limitations due to variability in results. MRI with gadolinium "
"enhancement provides superior anatomical localisation.</i>", note_style))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 9 – MANAGEMENT
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 9 – MANAGEMENT PLAN FOR FACIAL NERVE PALSY", h1))
story.append(Paragraph(b("1. Medical Treatment (Bell's Palsy – Acute Phase):"), h2))
med_data = [
[wrap(b("Drug"), bold_body), wrap(b("Dose & Duration"), bold_body), wrap(b("Notes"), bold_body)],
[wrap("Prednisolone (corticosteroid)", body),
wrap("1 mg/kg/day (60–80 mg/day orally) × 10 days, then taper over 4–5 days", body),
wrap("Must start within 72 hours (definitely within 2 weeks). Monitor blood sugar (DM) and BP.", body)],
[wrap("Valacyclovir (antiviral)", body),
wrap("500 mg TDS × 10 days (or Acyclovir 400 mg 5×/day)", body),
wrap("Combined with steroids may be superior. Prodrug of acyclovir – better absorption.", body)],
[wrap("Gastroprotection", body),
wrap("PPI or H2 blocker throughout steroid course", body),
wrap("Prevents GI ulceration from corticosteroids", body)],
]
story.append(tbl(med_data, [42*mm, 62*mm, 66*mm]))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(b("2. Eye Care (Critical – Prevents Corneal Damage):"), h2))
for f in [
"Lubricating eye drops (artificial tears) during the day",
"Lubricating eye ointment at night",
"Moisture chamber / taping of eyelid at night (if incomplete closure)",
"Protective glasses outdoors",
"Regular ophthalmological review if incomplete closure persists",
]:
story.append(Paragraph(f"• {f}", bullet))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(b("3. Physiotherapy:"), h2))
story.append(Paragraph("• Facial exercises with mirror biofeedback", bullet))
story.append(Paragraph("• Gentle massage of facial muscles", bullet))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(b("4. Monitoring and Electrodiagnostic-Guided Decisions:"), h2))
story.append(Paragraph(
"• If progresses to <b>complete paralysis</b> → obtain ENoG at <b>day 3</b> of complete palsy", bullet))
story.append(Paragraph(
"• Repeat ENoG every 1–3 days until degeneration reaches >90% or voluntary EMG activity seen", bullet))
story.append(Paragraph(
"• <b>ENoG <90% degeneration</b>: continue medical treatment, good prognosis", bullet))
story.append(Paragraph(
"• <b>ENoG >90% degeneration</b> + no voluntary EMG (within 2 weeks of onset) → consider surgical decompression", bullet))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(b("5. Surgical Decompression (Selected Cases):"), h2))
story.append(Paragraph(
"• Criteria: complete paralysis + >90% degeneration on ENoG + within 2 weeks of onset + no EMG activity", bullet))
story.append(Paragraph(
"• Approach: <b>Middle cranial fossa</b> (decompresses labyrinthine segment and meatal foramen – the narrowest point, 0.68 mm)", bullet))
story.append(Paragraph("• Remains controversial; evidence base still debated", bullet))
story.append(Spacer(1, 3*mm))
story.append(Paragraph(b("6. Management of Sequelae:"), h2))
seq_data = [
[wrap(b("Complication"), bold_body), wrap(b("Management"), bold_body)],
[wrap("Synkinesis (aberrant reinnervation)", body), wrap("Botulinum toxin injections; biofeedback physiotherapy", body)],
[wrap("Persistent lagophthalmos", body), wrap("Gold weight implant in upper eyelid; lateral tarsorrhaphy", body)],
[wrap("Persistent complete paralysis", body), wrap("Facial reanimation surgery: nerve grafting (greater auricular / sural nerve), muscle transfer (temporalis/masseter transposition), free gracilis transfer", body)],
[wrap("Crocodile tears", body), wrap("Botulinum toxin to lacrimal gland (if disabling)", body)],
[wrap("Ectropion", body), wrap("Lateral canthopexy or surgical correction", body)],
]
story.append(tbl(seq_data, [55*mm, 115*mm]))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# LO 10 – COMPLICATIONS
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("LO 10 – COMPLICATIONS FOLLOWING FACIAL PARALYSIS", h1))
comp_data = [
[wrap(b("Complication"), bold_body), wrap(b("Mechanism"), bold_body),
wrap(b("Clinical Features"), bold_body), wrap(b("Management"), bold_body)],
[wrap("Exposure Keratitis / Corneal Ulceration", body),
wrap("Lagophthalmos → corneal drying, abrasion, secondary infection", body),
wrap("Eye pain, redness, photophobia, reduced vision", body),
wrap("Lubricants, tarsorrhaphy, ophthalmology referral", body)],
[wrap("Synkinesis", body),
wrap("Aberrant reinnervation – axons regrow to incorrect muscles (e.g., eye closes when smiling)", body),
wrap("Involuntary co-contraction of facial muscles", body),
wrap("Botulinum toxin; physiotherapy; selective neurolysis", body)],
[wrap("Hemifacial Spasm", body),
wrap("Ephaptic transmission after nerve regeneration; vascular compression of facial nerve at REZ", body),
wrap("Involuntary unilateral facial muscle twitching", body),
wrap("Botulinum toxin; microvascular decompression (MVD)", body)],
[wrap("Crocodile Tears (Gustatory Lacrimation)", body),
wrap("Aberrant regeneration of salivary parasympathetic fibres → lacrimal gland", body),
wrap("Tearing while eating (instead of salivation)", body),
wrap("Botulinum toxin to lacrimal gland; often tolerated", body)],
[wrap("Facial Contracture", body),
wrap("Fibrosis and shortening of chronically denervated facial muscles", body),
wrap("Persistent facial asymmetry, stiffness, drawn appearance", body),
wrap("Physiotherapy; surgical correction in severe cases", body)],
[wrap("Ectropion", body),
wrap("Lower eyelid sagging due to orbicularis weakness", body),
wrap("Epiphora, eyelid drooping, exposure", body),
wrap("Lateral canthopexy; surgical repair", body)],
[wrap("Psychological Complications", body),
wrap("Disfigurement, communication difficulty, social withdrawal", body),
wrap("Depression, anxiety, reduced quality of life", body),
wrap("Counselling; support groups; early rehabilitation", body)],
]
story.append(tbl(comp_data, [38*mm, 44*mm, 44*mm, 44*mm]))
story.append(Spacer(1, 6*mm))
# ═══════════════════════════════════════════════════════════════
# PROGNOSIS (Bell's Palsy)
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("PROGNOSIS – BELL'S PALSY", h1))
prog_data = [
[wrap(b("Outcome"), bold_body), wrap(b("Proportion"), bold_body), wrap(b("Notes"), bold_body)],
[wrap("Complete recovery", body), wrap("~70–85%", body),
wrap("Usually within 3 weeks to 6 months; better with early steroid treatment", body)],
[wrap("Asymmetric movement / synkinesis", body), wrap("~15%", body),
wrap("Aberrant reinnervation; may require botulinum toxin", body)],
[wrap("Severe deformity, minimal recovery", body), wrap("~15%", body),
wrap("Risk factors: age >60, complete palsy, >90% ENoG degeneration, DM, hypertension", body)],
[wrap("Recurrence", body), wrap("7–12%", body),
wrap("Recurrence should raise suspicion for tumour or Melkersson-Rosenthal syndrome", body)],
]
story.append(tbl(prog_data, [55*mm, 25*mm, 90*mm]))
story.append(Spacer(1, 4*mm))
# SOURCES
story.append(HRFlowable(width="100%", thickness=1, color=colors.HexColor("#cccccc")))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
"<i>Sources: Shambaugh Surgery of the Ear (anatomy, Bell's palsy); "
"Cummings Otolaryngology Head and Neck Surgery (electrodiagnostic tests, surgical landmarks, management); "
"Bradley and Daroff's Neurology in Clinical Practice (UMN vs LMN, clinical features); "
"Scott-Brown's Otorhinolaryngology Head & Neck Surgery (surgical anatomy)</i>",
style("src", fontName="Helvetica-Oblique", fontSize=8, textColor=colors.grey,
leading=11, spaceAfter=2)))
# BUILD
doc.build(story)
print(f"PDF saved to: {OUTPUT}")
python3 /home/daytona/workspace/facial-nerve-palsy/generate_pdf.py 2>&1
~/facial-nerve-palsy/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/facial-nerve-palsy/generate_pdf.py'
python3 /home/daytona/workspace/facial-nerve-palsy/generate_pdf.py 2>&1
Facial Nerve Palsy ENT
PDF Document · PDF