Describe the pupillary pathway Describe the clinical features of the various pupillary abnormalities Make a ppt for this topic regarding ophthalmology taking reference book ak khurana ophthalmology For 4th year Mbbs student
pupillary light reflex pathway diagram afferent efferent Edinger-Westphal
relative afferent pupillary defect swinging flashlight test Marcus Gunn pupil
Argyll Robertson pupil
Horner syndrome ptosis miosis anhidrosis face
third nerve palsy ptosis dilated pupil down and out eye
mkdir -p /tmp/workspace/pupillary-pathway-ppt/output && ls -la /tmp/workspace/
~/pupillary-pathway-ppt/build_ppt.py
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.oxml.ns import qn
# ---------- Theme ----------
NAVY = RGBColor(0x0B, 0x2E, 0x4E)
TEAL = RGBColor(0x0E, 0x7C, 0x86)
LIGHT_TEAL = RGBColor(0xE6, 0xF3, 0xF3)
ACCENT = RGBColor(0xE1, 0x8A, 0x2E)
DARK = RGBColor(0x22, 0x22, 0x22)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
GREY = RGBColor(0x5A, 0x5A, 0x5A)
RED = RGBColor(0xB0, 0x2A, 0x2A)
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
BLANK = prs.slide_layouts[6]
def add_slide():
return prs.slides.add_slide(BLANK)
def set_bg(slide, color=WHITE):
bg = slide.background
bg.fill.solid()
bg.fill.fore_color.rgb = color
def add_rect(slide, x, y, w, h, color, line=False):
sh = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, x, y, w, h)
sh.fill.solid()
sh.fill.fore_color.rgb = color
if not line:
sh.line.fill.background()
else:
sh.line.color.rgb = color
sh.shadow.inherit = False
return sh
def add_text(slide, x, y, w, h, text, size=18, color=DARK, bold=False, italic=False,
align=PP_ALIGN.LEFT, font="Calibri", anchor=None, line_spacing=1.0):
tb = slide.shapes.add_textbox(x, y, w, h)
tf = tb.text_frame
tf.word_wrap = True
if anchor:
tf.vertical_anchor = anchor
lines = text.split("\n")
for i, line in enumerate(lines):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
p.text = line
p.alignment = align
p.line_spacing = line_spacing
for r in p.runs:
r.font.size = Pt(size)
r.font.color.rgb = color
r.font.bold = bold
r.font.italic = italic
r.font.name = font
return tb
def add_bullets(slide, x, y, w, h, items, size=16, color=DARK, font="Calibri",
space_after=8, bullet_color=TEAL, line_spacing=1.05):
"""items: list of (text, level) or plain strings (level 0)."""
tb = slide.shapes.add_textbox(x, y, w, h)
tf = tb.text_frame
tf.word_wrap = True
first = True
for item in items:
if isinstance(item, tuple):
text, level = item
else:
text, level = item, 0
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False
marker = {0: "\u25AA ", 1: "- ", 2: "\u2022 "}.get(level, "\u25AA ")
p.text = marker + text
p.level = 0
p.space_after = Pt(space_after)
p.line_spacing = line_spacing
indent = Inches(0.0 + level * 0.35)
pPr = p._pPr
for r in p.runs:
r.font.size = Pt(size - level * 1.5)
r.font.color.rgb = color
r.font.name = font
r.font.bold = (level == 0)
# manual indent via paragraph_format-like margin
tb.left = x
return tb
def indent_paragraph(p, level):
p._pPr.set('marL', str(int(Inches(0.28 * level))))
def add_bullets_indented(slide, x, y, w, h, items, size=16, color=DARK, font="Calibri",
space_after=6, line_spacing=1.05):
tb = slide.shapes.add_textbox(x, y, w, h)
tf = tb.text_frame
tf.word_wrap = True
first = True
for item in items:
if isinstance(item, tuple):
text, level = item
else:
text, level = item, 0
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False
marker = {0: "\u25AA ", 1: "\u2013 ", 2: "\u2022 "}.get(level, "\u25AA ")
p.text = marker + text
p.space_after = Pt(space_after)
p.line_spacing = line_spacing
try:
indent_paragraph(p, level)
except Exception:
pass
for r in p.runs:
r.font.size = Pt(size - level * 1.5)
r.font.color.rgb = color
r.font.name = font
r.font.bold = (level == 0)
return tb
def slide_header(slide, kicker, title, num=None, total=None):
add_rect(slide, 0, 0, SW, Inches(1.15), NAVY)
add_rect(slide, 0, Inches(1.15), SW, Inches(0.06), ACCENT)
add_text(slide, Inches(0.5), Inches(0.10), Inches(11), Inches(0.35), kicker.upper(),
size=13, color=ACCENT, bold=True, font="Calibri")
add_text(slide, Inches(0.5), Inches(0.42), Inches(12), Inches(0.7), title,
size=28, color=WHITE, bold=True, font="Calibri")
if num:
add_text(slide, SW - Inches(1.0), Inches(7.05), Inches(0.7), Inches(0.35), f"{num}",
size=12, color=GREY, align=PP_ALIGN.RIGHT)
def footer(slide, text="Pupillary Pathway & Abnormalities | Ophthalmology | 4th Year MBBS"):
add_text(slide, Inches(0.5), Inches(7.08), Inches(9), Inches(0.3), text, size=10, color=GREY)
def content_slide(kicker, title, num):
s = add_slide()
set_bg(s)
slide_header(s, kicker, title, num)
footer(s)
return s
def add_arrow_box(slide, x, y, w, h, text, color=TEAL, text_color=WHITE, size=13, shape=MSO_SHAPE.CHEVRON):
sh = slide.shapes.add_shape(shape, x, y, w, h)
sh.fill.solid()
sh.fill.fore_color.rgb = color
sh.line.color.rgb = WHITE
sh.line.width = Pt(1)
sh.shadow.inherit = False
tf = sh.text_frame
tf.word_wrap = True
tf.margin_left = Inches(0.05)
tf.margin_right = Inches(0.05)
p = tf.paragraphs[0]
p.text = text
p.alignment = PP_ALIGN.CENTER
for r in p.runs:
r.font.size = Pt(size)
r.font.color.rgb = text_color
r.font.bold = True
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
return sh
def add_box(slide, x, y, w, h, text, color=LIGHT_TEAL, text_color=NAVY, size=13, shape=MSO_SHAPE.ROUNDED_RECTANGLE, bold=True, line_color=TEAL):
sh = slide.shapes.add_shape(shape, x, y, w, h)
sh.fill.solid()
sh.fill.fore_color.rgb = color
sh.line.color.rgb = line_color
sh.line.width = Pt(1.25)
sh.shadow.inherit = False
tf = sh.text_frame
tf.word_wrap = True
tf.margin_left = Inches(0.06)
tf.margin_right = Inches(0.06)
p = tf.paragraphs[0]
p.text = text
p.alignment = PP_ALIGN.CENTER
for r in p.runs:
r.font.size = Pt(size)
r.font.color.rgb = text_color
r.font.bold = bold
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
return sh
def add_connector(slide, x1, y1, x2, y2, color=GREY, width=1.5, dash=None):
conn = slide.shapes.add_connector(1, x1, y1, x2, y2) # 1 = straight
conn.line.color.rgb = color
conn.line.width = Pt(width)
return conn
TOTAL = 21
# ================= SLIDE 1: TITLE =================
s = add_slide(); set_bg(s, NAVY)
add_rect(s, 0, Inches(6.6), SW, Inches(0.9), ACCENT)
add_text(s, Inches(0.9), Inches(2.2), Inches(11.5), Inches(0.6), "OPHTHALMOLOGY | 4th YEAR MBBS",
size=18, color=ACCENT, bold=True)
add_text(s, Inches(0.9), Inches(2.75), Inches(11.5), Inches(1.6), "The Pupillary Pathway\n& Pupillary Abnormalities",
size=40, color=WHITE, bold=True, line_spacing=1.05)
add_text(s, Inches(0.9), Inches(4.4), Inches(11), Inches(0.6),
"Anatomy of the light & near reflex pathways, sympathetic pupillodilator supply,\nand clinical features of the common pupillary disorders",
size=16, color=RGBColor(0xCF,0xE3,0xE6), italic=True, line_spacing=1.2)
add_text(s, Inches(0.9), Inches(6.75), Inches(9), Inches(0.5),
"Reference: A.K. Khurana - Comprehensive Ophthalmology (with Kanski's Clinical Ophthalmology cross-reference)",
size=13, color=NAVY, bold=True)
# ================= SLIDE 2: OBJECTIVES =================
s = content_slide("Learning Outcomes", "Objectives of This Session", 2)
add_bullets_indented(s, Inches(0.7), Inches(1.6), Inches(11.8), Inches(5),
[
"Describe the normal anatomy of the iris and its two muscles - sphincter and dilator pupillae",
"Trace the afferent and efferent limbs of the pupillary light reflex pathway",
"Outline the near reflex (accommodation) pathway and how it differs from the light reflex",
"Describe the three-neuron sympathetic (pupillodilator) pathway",
"Explain the swinging flash-light test and relative afferent pupillary defect (RAPD)",
"Describe the clinical features, causes and pharmacological confirmation of:",
("Argyll Robertson pupil", 1),
("Adie's tonic pupil", 1),
("Horner's syndrome", 1),
("Third (oculomotor) nerve palsy pupil", 1),
"Approach a patient presenting with anisocoria (unequal pupils)",
], size=18, space_after=12)
# ================= SLIDE 3: ANATOMY BASICS =================
s = content_slide("Anatomical Basis", "Iris Muscles Controlling Pupil Size", 3)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(6.0), Inches(5.3),
[
"Pupil size is a balance between two smooth muscles of the iris:",
"Sphincter pupillae", 1,
("Circular fibres around pupillary margin", 2),
("Constricts pupil (miosis)", 2),
("Supplied by parasympathetic fibres of CN III", 2),
"Dilator pupillae", 1,
("Radial fibres from collarette to iris root", 2),
("Dilates pupil (mydriasis)", 2),
("Supplied by sympathetic fibres", 2),
"Normal pupil size: 2-4 mm in daylight, 4-8 mm in dark",
"Normal pupils are equal, round, and react briskly to light and near - 'PERRLA'",
], size=16, space_after=8)
# simple diagram
add_box(s, Inches(7.1), Inches(1.7), Inches(5.4), Inches(1.3), "SPHINCTER PUPILLAE\nParasympathetic (CN III) -> Miosis", color=RGBColor(0xDD,0xEE,0xE4), text_color=NAVY, size=15)
add_box(s, Inches(7.1), Inches(3.3), Inches(5.4), Inches(1.3), "DILATOR PUPILLAE\nSympathetic -> Mydriasis", color=RGBColor(0xF7,0xE3,0xD3), text_color=NAVY, size=15)
add_text(s, Inches(7.1), Inches(4.9), Inches(5.4), Inches(1.6),
"Pupil size at any moment reflects the net balance of\nparasympathetic (constrictor) and sympathetic (dilator)\ntone acting on these two muscles.",
size=14, color=GREY, italic=True, line_spacing=1.3)
# ================= SLIDE 4: LIGHT REFLEX - AFFERENT =================
s = content_slide("Pupillary Light Reflex", "Afferent (Sensory) Pathway", 4)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(5.6), Inches(5.2),
[
"Stimulus: light falling on the retina",
"Pathway (afferent limb):",
("Retina (rods & cones -> ganglion cells)", 1),
("Optic nerve", 1),
("Optic chiasma (partial decussation of nasal fibres)", 1),
("Optic tract", 1),
("Fibres LEAVE the optic tract before the lateral geniculate body", 1),
("Synapse in the pretectal nucleus (midbrain, at superior colliculus level)", 1),
"Key point: pupillary fibres bypass the LGB and visual cortex - so a pupil can react to light even in cortical blindness",
"Each pretectal nucleus sends fibres to BOTH Edinger-Westphal nuclei - the basis of the consensual reflex",
], size=16.5, space_after=9)
add_box(s, Inches(6.6), Inches(1.7), Inches(5.9), Inches(0.7), "RETINA", color=LIGHT_TEAL, text_color=NAVY)
add_connector(s, Inches(9.55), Inches(2.4), Inches(9.55), Inches(2.75), TEAL, 2)
add_box(s, Inches(6.6), Inches(2.75), Inches(5.9), Inches(0.7), "OPTIC NERVE (CN II)", color=LIGHT_TEAL, text_color=NAVY)
add_connector(s, Inches(9.55), Inches(3.45), Inches(9.55), Inches(3.8), TEAL, 2)
add_box(s, Inches(6.6), Inches(3.8), Inches(5.9), Inches(0.7), "OPTIC CHIASMA", color=LIGHT_TEAL, text_color=NAVY)
add_connector(s, Inches(9.55), Inches(4.5), Inches(9.55), Inches(4.85), TEAL, 2)
add_box(s, Inches(6.6), Inches(4.85), Inches(5.9), Inches(0.7), "OPTIC TRACT", color=LIGHT_TEAL, text_color=NAVY)
add_connector(s, Inches(9.55), Inches(5.55), Inches(9.55), Inches(5.9), TEAL, 2)
add_box(s, Inches(6.6), Inches(5.9), Inches(5.9), Inches(0.75), "PRETECTAL NUCLEUS (midbrain)", color=RGBColor(0xFC,0xE9,0xD0), text_color=NAVY)
# ================= SLIDE 5: LIGHT REFLEX - EFFERENT =================
s = content_slide("Pupillary Light Reflex", "Efferent (Motor) Pathway", 5)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(5.6), Inches(5.2),
[
"From the pretectal nucleus, fibres pass to BOTH Edinger-Westphal (EW) nuclei",
"Pathway (efferent limb):",
("Edinger-Westphal nucleus (accessory nucleus of CN III)", 1),
("Oculomotor nerve (CN III) - travels with somatic fibres", 1),
("Ciliary ganglion (in orbit, behind globe) - relay station", 1),
("Short ciliary nerves", 1),
("Sphincter pupillae muscle -> constriction (miosis)", 1),
"Because each pretectal nucleus projects to both EW nuclei:",
("Direct light reflex - constriction of the illuminated eye", 1),
("Consensual light reflex - simultaneous constriction of the other eye", 1),
"This bilateral wiring is why a swinging flashlight test can detect an afferent (not efferent) defect",
], size=16, space_after=8)
add_box(s, Inches(6.6), Inches(1.7), Inches(5.9), Inches(0.7), "EDINGER-WESTPHAL NUCLEUS (both sides)", color=RGBColor(0xFC,0xE9,0xD0), text_color=NAVY, size=14)
add_connector(s, Inches(9.55), Inches(2.4), Inches(9.55), Inches(2.75), TEAL, 2)
add_box(s, Inches(6.6), Inches(2.75), Inches(5.9), Inches(0.7), "OCULOMOTOR NERVE (CN III)", color=LIGHT_TEAL, text_color=NAVY)
add_connector(s, Inches(9.55), Inches(3.45), Inches(9.55), Inches(3.8), TEAL, 2)
add_box(s, Inches(6.6), Inches(3.8), Inches(5.9), Inches(0.7), "CILIARY GANGLION", color=LIGHT_TEAL, text_color=NAVY)
add_connector(s, Inches(9.55), Inches(4.5), Inches(9.55), Inches(4.85), TEAL, 2)
add_box(s, Inches(6.6), Inches(4.85), Inches(5.9), Inches(0.7), "SHORT CILIARY NERVES", color=LIGHT_TEAL, text_color=NAVY)
add_connector(s, Inches(9.55), Inches(5.55), Inches(9.55), Inches(5.9), TEAL, 2)
add_box(s, Inches(6.6), Inches(5.9), Inches(5.9), Inches(0.75), "SPHINCTER PUPILLAE -> MIOSIS", color=RGBColor(0xDD,0xEE,0xE4), text_color=NAVY)
# ================= SLIDE 6: NEAR REFLEX =================
s = content_slide("Near Reflex", "Accommodation-Convergence Reflex (Near Reflex)", 6)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(6.0), Inches(5.3),
[
"Elicited by voluntarily fixating on a near object",
"Consists of a triad (synkinesis):",
("Accommodation - increased convexity of lens (ciliary muscle contraction)", 1),
("Convergence - both eyes turn inward (medial recti)", 1),
("Miosis - pupillary constriction (sphincter pupillae)", 1),
"Pathway: visual cortex -> corticotectal fibres -> travel directly to the Edinger-Westphal nucleus (NOT via the pretectal nucleus)",
"Clinical importance - Light-Near Dissociation:",
("A lesion affecting the dorsal midbrain / pretectal region can abolish the light reflex while sparing the near reflex, because the near-reflex fibres run more ventrally", 1),
("Seen classically in Argyll Robertson pupil and dorsal midbrain (Parinaud) syndrome", 1),
], size=17, space_after=10)
add_box(s, Inches(7.0), Inches(1.7), Inches(5.5), Inches(1.0), "ACCOMMODATION", color=LIGHT_TEAL, text_color=NAVY, size=15)
add_box(s, Inches(7.0), Inches(2.9), Inches(5.5), Inches(1.0), "CONVERGENCE", color=LIGHT_TEAL, text_color=NAVY, size=15)
add_box(s, Inches(7.0), Inches(4.1), Inches(5.5), Inches(1.0), "MIOSIS", color=LIGHT_TEAL, text_color=NAVY, size=15)
add_text(s, Inches(7.0), Inches(5.3), Inches(5.5), Inches(1.4), "Near-reflex triad occurs together whenever the eyes fixate on a near target.", size=13, color=GREY, italic=True, line_spacing=1.3)
# ================= SLIDE 7: SYMPATHETIC PATHWAY =================
s = content_slide("Pupillodilator Supply", "Sympathetic Pathway (3-Neuron Chain)", 7)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(5.7), Inches(5.3),
[
"Responsible for pupillary dilatation (mydriasis) - relevant to Horner's syndrome",
"First (central) neuron:", 1,
("Posterior hypothalamus -> descends through brainstem to ciliospinal centre of Budge (C8-T2)", 2),
"Second (preganglionic) neuron:", 1,
("Ciliospinal centre -> exits spinal cord -> over apex of lung -> superior cervical ganglion", 2),
"Third (postganglionic) neuron:", 1,
("Superior cervical ganglion -> along internal carotid artery -> cavernous sinus -> nasociliary & long ciliary nerves -> dilator pupillae (also supplies Muller's muscle of the lid & facial sweat glands)", 2),
"A lesion anywhere along this 3-neuron chain produces Horner's syndrome",
], size=15.5, space_after=8)
add_box(s, Inches(6.7), Inches(1.7), Inches(5.8), Inches(0.85), "1st Neuron: Hypothalamus -> Ciliospinal centre (C8-T2)", color=RGBColor(0xE7,0xEF,0xFA), text_color=NAVY, size=13.5)
add_connector(s, Inches(9.6), Inches(2.55), Inches(9.6), Inches(2.85), TEAL, 2)
add_box(s, Inches(6.7), Inches(2.85), Inches(5.8), Inches(0.85), "2nd Neuron: Ciliospinal centre -> apex of lung -> Superior cervical ganglion", color=RGBColor(0xE7,0xEF,0xFA), text_color=NAVY, size=13.5)
add_connector(s, Inches(9.6), Inches(3.7), Inches(9.6), Inches(4.0), TEAL, 2)
add_box(s, Inches(6.7), Inches(4.0), Inches(5.8), Inches(0.85), "3rd Neuron: SCG -> along ICA -> long ciliary nerves", color=RGBColor(0xE7,0xEF,0xFA), text_color=NAVY, size=13.5)
add_connector(s, Inches(9.6), Inches(4.85), Inches(9.6), Inches(5.15), TEAL, 2)
add_box(s, Inches(6.7), Inches(5.15), Inches(5.8), Inches(0.75), "DILATOR PUPILLAE -> MYDRIASIS", color=RGBColor(0xF7,0xE3,0xD3), text_color=NAVY, size=14)
# ================= SLIDE 8: CLINICAL TESTING =================
s = content_slide("Clinical Examination", "Testing the Pupillary Reflexes", 8)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(11.8), Inches(2.6),
[
"Direct light reflex: shine light into one eye -> observe constriction of the SAME eye",
"Consensual light reflex: shine light into one eye -> observe constriction of the OTHER (unlit) eye",
"Near reflex: ask patient to look at a distant object then a near target -> observe miosis + convergence",
"Swinging flashlight test: light is moved rapidly from one eye to the other, comparing the briskness/degree of constriction - the key bedside test for an afferent pupillary defect (RAPD)",
], size=17, space_after=10)
add_rect(s, Inches(0.6), Inches(4.3), Inches(11.8), Inches(2.4), RGBColor(0xF4,0xF7,0xF7))
add_text(s, Inches(0.85), Inches(4.45), Inches(11.2), Inches(0.4), "Normal response on swinging flashlight test:", size=15, bold=True, color=NAVY)
add_bullets_indented(s, Inches(0.85), Inches(4.85), Inches(11), Inches(1.7),
[
"Both pupils constrict equally and promptly when light is swung to either eye",
"In RAPD, swinging the light INTO the affected eye causes paradoxical DILATATION instead of constriction (Marcus Gunn pupil)",
], size=15, space_after=6)
# ================= SLIDE 9: CLASSIFICATION OVERVIEW =================
s = content_slide("Overview", "Classification of Pupillary Abnormalities", 9)
add_text(s, Inches(0.6), Inches(1.5), Inches(12), Inches(0.5), "Pupillary disorders can be grouped by the site of the lesion along the pathway:", size=17, color=DARK, bold=True)
rows = [
("Afferent pathway lesion", "Relative Afferent Pupillary Defect (RAPD / Marcus Gunn pupil)", RGBColor(0xDD,0xEE,0xE4)),
("Efferent parasympathetic lesion", "Third nerve palsy pupil, Tonic pupil (Adie's)", RGBColor(0xFC,0xE9,0xD0)),
("Efferent sympathetic lesion", "Horner's syndrome", RGBColor(0xE7,0xEF,0xFA)),
("Midbrain (light-near dissociation)", "Argyll Robertson pupil, Parinaud (dorsal midbrain) syndrome", RGBColor(0xF3,0xDD,0xDD)),
("Physiological / miscellaneous", "Simple (essential) anisocoria, Hippus, Amaurotic pupil, Wernicke's hemianopic pupil", RGBColor(0xEC,0xEC,0xEC)),
]
y = Inches(2.15)
for site, entities, color in rows:
add_box(s, Inches(0.6), y, Inches(4.0), Inches(0.85), site, color=color, text_color=NAVY, size=13.5)
add_text(s, Inches(4.85), y+Inches(0.08), Inches(7.6), Inches(0.75), entities, size=14, color=DARK, anchor=MSO_ANCHOR.MIDDLE)
y += Inches(0.98)
# ================= SLIDE 10: RAPD =================
s = content_slide("Afferent Defect", "Relative Afferent Pupillary Defect (Marcus Gunn Pupil)", 10)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(6.1), Inches(5.3),
[
"Definition: relatively weaker pupillary constriction to light in one eye compared to the other, due to a unilateral or asymmetric lesion of the afferent pathway (retina or optic nerve)",
"Causes:", 1,
("Optic neuritis, optic nerve compression/tumour, optic atrophy", 2),
("Ischaemic optic neuropathy, traumatic optic nerve injury", 2),
("Extensive retinal detachment or central retinal artery/vein occlusion", 2),
"Clinical features:", 1,
("Direct reflex in the affected eye is sluggish/reduced", 2),
("Consensual reflex in the normal eye (from stimulating the abnormal eye) is also reduced", 2),
("On swinging flashlight test, light directed into the affected eye causes the pupil to DILATE instead of constrict (Marcus Gunn/RAPD sign)", 2),
("Visual acuity and colour vision often reduced on the affected side; no anisocoria at rest (both pupils equal in size, since efferent pathway is intact)", 2),
], size=15, space_after=7)
add_rect(s, Inches(7.0), Inches(1.7), Inches(5.4), Inches(4.9), RGBColor(0xF4,0xF7,0xF7))
add_text(s, Inches(7.2), Inches(1.85), Inches(5.0), Inches(0.4), "Swinging Flashlight Test", size=15, bold=True, color=NAVY)
add_box(s, Inches(7.2), Inches(2.35), Inches(5.0), Inches(0.8), "Light on NORMAL eye\n-> brisk constriction (both eyes)", color=RGBColor(0xDD,0xEE,0xE4), text_color=NAVY, size=13)
add_box(s, Inches(7.2), Inches(3.35), Inches(5.0), Inches(0.9), "Swing light to AFFECTED eye\n-> paradoxical DILATATION\n(RAPD / Marcus Gunn pupil)", color=RGBColor(0xF3,0xDD,0xDD), text_color=RED, size=13)
add_text(s, Inches(7.2), Inches(4.5), Inches(5.0), Inches(1.9),
"Key teaching point: RAPD indicates optic nerve/retinal disease, NOT a third nerve or iris problem. Pupil sizes are equal at rest because both efferent pathways are normal - only the reaction to light differs.",
size=13.5, color=GREY, italic=True, line_spacing=1.3)
# ================= SLIDE 11: ARGYLL ROBERTSON =================
s = content_slide("Light-Near Dissociation", "Argyll Robertson Pupil", 11)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(6.3), Inches(5.3),
[
"Site of lesion: pretectal region of midbrain (interrupts light reflex fibres, spares near reflex fibres which run more ventrally)",
"Classic causes:", 1,
("Neurosyphilis (tabes dorsalis) - classic association", 2),
("Diabetes mellitus", 2),
("Occasionally chronic alcoholism, multiple sclerosis, encephalitis", 2),
"Clinical features - mnemonic 'AR pupil - accommodation reflex present, pupil light reflex absent':", 1,
("Small, irregular pupils (miosis)", 2),
("Bilateral, but often asymmetrical", 2),
("Light-near dissociation: light reflex ABSENT, near/accommodation reflex PRESENT", 2),
("Poor pupillary dilatation with mydriatics (due to iris atrophy)", 2),
("Normal vision", 2),
], size=15.5, space_after=7)
add_rect(s, Inches(7.15), Inches(1.7), Inches(5.3), Inches(4.9), RGBColor(0xF4,0xF7,0xF7))
add_text(s, Inches(7.35), Inches(1.85), Inches(4.9), Inches(0.4), "Key Feature", size=15, bold=True, color=NAVY)
add_box(s, Inches(7.35), Inches(2.35), Inches(4.9), Inches(1.0), "Light reflex: ABSENT", color=RGBColor(0xF3,0xDD,0xDD), text_color=RED, size=15)
add_box(s, Inches(7.35), Inches(3.5), Inches(4.9), Inches(1.0), "Near/accommodation reflex: PRESENT", color=RGBColor(0xDD,0xEE,0xE4), text_color=NAVY, size=15)
add_text(s, Inches(7.35), Inches(4.75), Inches(4.9), Inches(1.7),
"= Light-Near Dissociation\n\nAlways investigate with VDRL/TPHA (syphilis serology) and blood glucose.",
size=14, color=GREY, italic=True, line_spacing=1.4)
# ================= SLIDE 12: ADIE'S TONIC PUPIL =================
s = content_slide("Efferent Parasympathetic Defect", "Adie's (Holmes-Adie) Tonic Pupil", 12)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(6.3), Inches(5.3),
[
"Site of lesion: ciliary ganglion or short ciliary nerves (postganglionic parasympathetic denervation)",
"Often idiopathic / post-viral; typically affects young women, usually unilateral (may become bilateral over years)",
"Clinical features:", 1,
("Unilateral, moderately dilated (mydriatic) pupil", 2),
("Direct and consensual light reflex - absent or markedly sluggish", 2),
("Near reflex - present but slow (tonic): slow constriction to near, slow re-dilatation after - light-near dissociation of a different type", 2),
("Vermiform (worm-like) movements of pupillary margin on slit-lamp", 2),
("Sector palsy of sphincter pupillae may be seen", 2),
("Associated with diminished deep tendon reflexes = Holmes-Adie syndrome", 2),
"Pharmacological confirmation:", 1,
("Dilute pilocarpine 0.1-0.125% causes constriction of the Adie pupil (denervation/cholinergic supersensitivity) but NOT the normal pupil", 2),
], size=14.5, space_after=6)
add_rect(s, Inches(7.15), Inches(1.7), Inches(5.3), Inches(4.9), RGBColor(0xF4,0xF7,0xF7))
add_text(s, Inches(7.35), Inches(1.85), Inches(4.9), Inches(0.4), "Pilocarpine 0.1% Test", size=15, bold=True, color=NAVY)
add_box(s, Inches(7.35), Inches(2.35), Inches(4.9), Inches(0.9), "Normal pupil\n-> NO significant change", color=RGBColor(0xEC,0xEC,0xEC), text_color=NAVY, size=13.5)
add_box(s, Inches(7.35), Inches(3.4), Inches(4.9), Inches(0.9), "Adie pupil\n-> constricts (denervation hypersensitivity)", color=RGBColor(0xDD,0xEE,0xE4), text_color=NAVY, size=13.5)
add_text(s, Inches(7.35), Inches(4.55), Inches(4.9), Inches(1.9),
"'Little old Adie' - in longstanding cases the pupil eventually becomes small.\nCheck syphilis serology if bilateral.",
size=13.5, color=GREY, italic=True, line_spacing=1.35)
# ================= SLIDE 13: HORNER'S SYNDROME =================
s = content_slide("Sympathetic Pathway Defect", "Horner's Syndrome (Oculosympathetic Palsy)", 13)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(6.3), Inches(5.3),
[
"Site of lesion: anywhere along the 3-neuron sympathetic pathway (central, preganglionic or postganglionic)",
"Causes:", 1,
("Central: brainstem stroke, syringomyelia, MS", 2),
("Preganglionic: Pancoast tumour (lung apex), thyroid/neck surgery, trauma", 2),
("Postganglionic: carotid artery dissection, cluster headache, cavernous sinus lesion", 2),
"Classic triad:", 1,
("Miosis (mild, unopposed sphincter action)", 2),
("Partial Ptosis (Muller's muscle paralysis)", 2),
("Anhidrosis of ipsilateral face (if lesion proximal to carotid bifurcation)", 2),
"Other features: apparent enophthalmos, mild conjunctival hyperaemia, heterochromia iridis (if congenital)", 1,
("Anisocoria increases in DIM light (affected pupil dilates poorly/slowly - 'dilation lag')", 2),
], size=14.5, space_after=6)
add_rect(s, Inches(7.15), Inches(1.7), Inches(5.3), Inches(4.9), RGBColor(0xF4,0xF7,0xF7))
add_text(s, Inches(7.35), Inches(1.85), Inches(4.9), Inches(0.4), "Pharmacological Localisation", size=15, bold=True, color=NAVY)
add_bullets_indented(s, Inches(7.35), Inches(2.3), Inches(4.9), Inches(4.1),
[
"Cocaine 4% - confirms Horner's: Horner pupil fails to dilate (normal pupil dilates)",
"Apraclonidine 0.5-1% - reverses anisocoria (dilates Horner pupil via denervation supersensitivity; may also relieve ptosis)",
"Hydroxyamphetamine 1% - localises lesion:",
("Dilates in central/preganglionic (1st/2nd neuron) lesion", 1),
("Fails to dilate in postganglionic (3rd neuron) lesion", 1),
], size=13.5, space_after=8)
# ================= SLIDE 14: THIRD NERVE PALSY =================
s = content_slide("Efferent Parasympathetic Defect", "Pupil in Third (Oculomotor) Nerve Palsy", 14)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(6.3), Inches(5.3),
[
"Pupillomotor (parasympathetic) fibres run superficially on the outer surface of CN III - vulnerable to compression",
"Somatic motor fibres run centrally - more vulnerable to ischaemia (e.g. diabetic microvascular infarct)",
"Complete (surgical) third nerve palsy:", 1,
("Compressive lesion - e.g. posterior communicating artery aneurysm, uncal herniation", 2),
("Pupil: dilated and fixed (mydriasis), unreactive to light and near", 2),
("With ptosis + eye deviated 'down and out' (unopposed lateral rectus & superior oblique)", 2),
("A dilated pupil with ophthalmoplegia is a NEUROSURGICAL EMERGENCY - exclude aneurysm", 2),
"Pupil-sparing third nerve palsy:", 1,
("Typically ischaemic/microvascular (diabetes, hypertension)", 2),
("Pupil is normal/spared because peripheral pupillomotor fibres are less affected by ischaemia of the vasa nervorum", 2),
], size=15, space_after=7)
add_rect(s, Inches(7.15), Inches(1.7), Inches(5.3), Inches(4.9), RGBColor(0xF3,0xDD,0xDD))
add_text(s, Inches(7.35), Inches(1.85), Inches(4.9), Inches(0.4), "Red Flag", size=16, bold=True, color=RED)
add_text(s, Inches(7.35), Inches(2.3), Inches(4.9), Inches(2.2),
"New dilated pupil + ptosis + ophthalmoplegia\n= possible expanding intracranial aneurysm\n(posterior communicating artery)\n\nRequires urgent neuroimaging (CT/MR angiography).",
size=15, color=RED, bold=True, line_spacing=1.4)
add_text(s, Inches(7.35), Inches(4.7), Inches(4.9), Inches(1.7),
"Pupil sparing + painless + risk factors for vascular disease -> favours an ischaemic (medical) third nerve palsy, usually resolves in weeks.",
size=13.5, color=GREY, italic=True, line_spacing=1.3)
# ================= SLIDE 15: OTHER ABNORMALITIES =================
s = content_slide("Other Pupillary Abnormalities", "Miscellaneous Pupillary Signs", 15)
add_bullets_indented(s, Inches(0.6), Inches(1.55), Inches(11.8), Inches(5.3),
[
"Simple (essential/physiological) anisocoria:", 1,
("Mild difference in pupil size (usually <1 mm), both react normally to light; seen in ~20% of normal people", 2),
"Hippus (pupillary unrest):", 1,
("Rhythmic, spontaneous small oscillations in pupil size independent of illumination; a normal phenomenon", 2),
"Amaurotic pupil (total afferent blindness, e.g. complete optic nerve transection):", 1,
("No direct reflex in the blind eye; but normal eye still shows a consensual response when the SEEING eye is illuminated; blind eye shows no direct reflex but does show consensual reflex when the other (seeing) eye is lit", 2),
"Wernicke's hemianopic pupillary reaction:", 1,
("Seen in tract lesions causing homonymous hemianopia; light directed at the 'blind' retinal hemifield fails to produce a reflex, while light on the 'seeing' hemifield does (rarely demonstrable clinically)", 2),
"Cortical/apparent light-near dissociation can also occur in severe bilateral afferent visual pathway disease", 1,
], size=16, space_after=9)
# ================= SLIDE 16: SUMMARY TABLE =================
s = content_slide("Quick Revision", "Summary: Comparing Pupillary Abnormalities", 16)
headers = ["Condition", "Pupil size", "Light reflex", "Near reflex", "Key clue"]
data = [
["RAPD (Marcus Gunn)", "Equal", "Reduced (affected eye)", "Normal", "Optic nerve/retinal disease"],
["Argyll Robertson", "Small, irregular", "Absent", "Present", "Neurosyphilis, light-near dissociation"],
["Adie's tonic pupil", "Large (early)", "Absent/sluggish", "Slow, tonic", "Pilocarpine 0.1% constricts"],
["Horner's syndrome", "Small (miosis)", "Present", "Present", "Ptosis + anhidrosis; dilation lag"],
["3rd nerve palsy", "Large, fixed", "Absent", "Absent", "Ptosis + eye 'down and out'"],
]
col_w = [Inches(2.6), Inches(1.9), Inches(2.5), Inches(2.0), Inches(2.8)]
x0 = Inches(0.6); y0 = Inches(1.55); row_h = Inches(0.85)
x = x0
for i, htext in enumerate(headers):
add_box(s, x, y0, col_w[i], Inches(0.55), htext, color=NAVY, text_color=WHITE, size=13, shape=MSO_SHAPE.RECTANGLE)
x += col_w[i]
y = y0 + Inches(0.55)
for r, row in enumerate(data):
x = x0
rowcolor = LIGHT_TEAL if r % 2 == 0 else WHITE
for i, cell in enumerate(row):
add_box(s, x, y, col_w[i], row_h, cell, color=rowcolor, text_color=DARK, size=11.5, shape=MSO_SHAPE.RECTANGLE, bold=(i==0), line_color=RGBColor(0xC9,0xD9,0xD9))
x += col_w[i]
y += row_h
# ================= SLIDE 17: APPROACH TO ANISOCORIA =================
s = content_slide("Clinical Approach", "Approach to a Patient with Anisocoria", 17)
add_text(s, Inches(0.6), Inches(1.5), Inches(12), Inches(0.4), "Step 1: Determine which pupil is abnormal", size=16, bold=True, color=NAVY)
add_box(s, Inches(0.6), Inches(2.0), Inches(5.8), Inches(1.0), "Anisocoria WORSE in DIM light\n-> smaller pupil is abnormal\n(fails to dilate)", color=RGBColor(0xE7,0xEF,0xFA), text_color=NAVY, size=14)
add_box(s, Inches(6.7), Inches(2.0), Inches(5.8), Inches(1.0), "Anisocoria WORSE in BRIGHT light\n-> larger pupil is abnormal\n(fails to constrict)", color=RGBColor(0xFC,0xE9,0xD0), text_color=NAVY, size=14)
add_text(s, Inches(0.6), Inches(3.15), Inches(12), Inches(0.4), "Step 2: Consider likely causes", size=16, bold=True, color=NAVY)
add_box(s, Inches(0.6), Inches(3.6), Inches(5.8), Inches(1.35), "Smaller pupil abnormal:\nHorner's syndrome\n(check ptosis, anhidrosis; confirm with cocaine/ apraclonidine test)", color=RGBColor(0xE7,0xEF,0xFA), text_color=NAVY, size=13.5)
add_box(s, Inches(6.7), Inches(3.6), Inches(5.8), Inches(1.35), "Larger pupil abnormal:\nAdie's tonic pupil / 3rd nerve palsy / pharmacological mydriasis\n(check reflexes, ptosis, ocular motility, pilocarpine test)", color=RGBColor(0xFC,0xE9,0xD0), text_color=NAVY, size=13.5)
add_text(s, Inches(0.6), Inches(5.15), Inches(12), Inches(0.4), "Step 3: Always assess -", size=16, bold=True, color=NAVY)
add_bullets_indented(s, Inches(0.6), Inches(5.6), Inches(11.8), Inches(1.5),
[
"Extraocular movements and lid position (ptosis) - suggests 3rd nerve or Horner's",
"Response to direct/consensual light and near reflex, and old photographs for pre-existing anisocoria",
"Pharmacological testing to confirm and localise the lesion when indicated",
], size=14.5, space_after=6)
# ================= SLIDE 18: KEY POINTS =================
s = content_slide("Summary", "Key Take-Home Points", 18)
add_bullets_indented(s, Inches(0.6), Inches(1.6), Inches(11.8), Inches(5.3),
[
"The light reflex pathway synapses in the pretectal nucleus, NOT the LGB or visual cortex - it bypasses conscious vision",
"The near reflex pathway does not pass through the pretectal nucleus - this explains light-near dissociation",
"A relative afferent pupillary defect (RAPD) signals optic nerve/retinal disease and does not cause anisocoria at rest",
"Light-near dissociation classically occurs in Argyll Robertson pupil (small, irregular, bilateral) and Adie's tonic pupil (large, tonic)",
"Horner's syndrome = miosis + ptosis + anhidrosis, from a lesion anywhere in the 3-neuron sympathetic chain",
"A new dilated, fixed pupil with ptosis and ophthalmoplegia is a neurosurgical emergency until an aneurysm is excluded",
"Pharmacological pupil testing (pilocarpine, cocaine, apraclonidine, hydroxyamphetamine) helps confirm and localise the lesion",
], size=17, space_after=12)
# ================= SLIDE 19: REFERENCES =================
s = content_slide("References", "Suggested Reading", 19)
add_bullets_indented(s, Inches(0.6), Inches(1.7), Inches(11.8), Inches(4.5),
[
"Khurana AK. Comprehensive Ophthalmology - Chapter on Neuro-ophthalmology / Pupil and its disorders (latest edition)",
"Kanski JJ, Bowling B. Kanski's Clinical Ophthalmology: A Systematic Approach, 10th edition - Chapter 19, Neuro-ophthalmology (Pupillary abnormalities)",
"Standard MBBS ophthalmology and clinical neurology texts for cross-reference on the anatomy of CN III and the sympathetic pathway",
], size=17, space_after=14)
add_text(s, Inches(0.6), Inches(5.6), Inches(11.8), Inches(1.0),
"Note: this deck was prepared using A.K. Khurana's Comprehensive Ophthalmology as the primary reference framework, cross-checked against Kanski's Clinical Ophthalmology (10th ed.) for clinical detail and pharmacological testing protocols.",
size=13, color=GREY, italic=True, line_spacing=1.3)
# ================= SLIDE 20: THANK YOU =================
s = add_slide(); set_bg(s, NAVY)
add_rect(s, 0, Inches(3.5), SW, Inches(0.06), ACCENT)
add_text(s, Inches(1), Inches(2.8), Inches(11), Inches(0.7), "Thank You", size=40, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
add_text(s, Inches(1), Inches(3.7), Inches(11), Inches(0.6), "Questions & Discussion", size=20, color=ACCENT, align=PP_ALIGN.CENTER)
out_path = "/tmp/workspace/pupillary-pathway-ppt/output/Pupillary_Pathway_and_Abnormalities.pptx"
prs.save(out_path)
print("Saved:", out_path)
print("Total slides:", len(prs.slides.__iter__.__self__._sldIdLst))
cd /tmp/workspace/pupillary-pathway-ppt && python build_ppt.py
"",$" in ~/pupillary-pathway-ppt/build_ppt.py
"", 1," in ~/pupillary-pathway-ppt/build_ppt.py
"", 2," in ~/pupillary-pathway-ppt/build_ppt.py
cd /tmp/workspace/pupillary-pathway-ppt && python3 -c " import re with open('build_ppt.py') as f: content = f.read() pattern = re.compile(r'^(\s*)\"(.*)\", 1,\s*$', re.MULTILINE) def repl(m): indent, text = m.group(1), m.group(2) return f'{indent}(\"{text}\", 1),' new_content, n = pattern.subn(repl, content) print('replacements:', n) with open('build_ppt.py', 'w') as f: f.write(new_content) "
cd /tmp/workspace/pupillary-pathway-ppt && python build_ppt.py
ls -la /tmp/workspace/pupillary-pathway-ppt/output/
| Condition | Pupil size | Light reflex | Near reflex | Key clue |
|---|---|---|---|---|
| RAPD (Marcus Gunn pupil) | Equal | Reduced in affected eye | Normal | Optic nerve/retinal disease; paradoxical dilatation on swinging flashlight test |
| Argyll Robertson pupil | Small, irregular, bilateral | Absent | Present | Neurosyphilis/diabetes; light-near dissociation; poor mydriatic dilatation |
| Adie's (tonic) pupil | Large (early), small later ("little old Adie") | Absent/sluggish | Slow, tonic | Dilute pilocarpine 0.1% constricts it; vermiform iris movements; Holmes-Adie syndrome with absent knee/ankle jerks |
| Horner's syndrome | Small (miosis) | Present | Present | Ptosis + anhidrosis; worse anisocoria in dim light; localised with cocaine/apraclonidine/hydroxyamphetamine tests |
| 3rd nerve palsy | Large, fixed | Absent | Absent | Ptosis + eye "down and out"; compressive (e.g. PCOM aneurysm) usually involves the pupil, ischaemic (diabetic) usually spares it |
| Physiological anisocoria / Hippus | Mild difference / oscillating | Normal | Normal | Benign, seen in ~20% of normal people |
Pupillary Pathway and Abnormalities
Presentation · PPTX