Prepare a ppt topic diplopia subheading etiology types investigation treatment
mkdir -p /tmp/workspace/diplopia-ppt
~/diplopia-ppt/make_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.util import Inches, Pt
import copy
# ── Palette ──────────────────────────────────────────────────────────────────
DARK_BLUE = RGBColor(0x0D, 0x2B, 0x55) # slide bg / title bar
MID_BLUE = RGBColor(0x1A, 0x5F, 0x9C) # accent bar
TEAL = RGBColor(0x00, 0xA8, 0xCC) # highlight / bullets
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
LIGHT_GREY = RGBColor(0xF2, 0xF5, 0xF9)
DARK_GREY = RGBColor(0x22, 0x22, 0x33)
GOLD = RGBColor(0xF5, 0xC5, 0x18)
W = Inches(13.333)
H = Inches(7.5)
prs = Presentation()
prs.slide_width = W
prs.slide_height = H
blank = prs.slide_layouts[6] # fully blank layout
# ─────────────────────────────────────────────────────────────────────────────
# Helper functions
# ─────────────────────────────────────────────────────────────────────────────
def add_rect(slide, x, y, w, h, fill_rgb, transparency=0):
from pptx.oxml.ns import qn
shape = slide.shapes.add_shape(1, x, y, w, h) # MSO_SHAPE_TYPE.RECTANGLE = 1
shape.line.fill.background() # no border
fill = shape.fill
fill.solid()
fill.fore_color.rgb = fill_rgb
if transparency:
fill.fore_color._xClr.getparent().attrib.pop('lumMod', None)
return shape
def add_textbox(slide, x, y, w, h, text, size, bold=False, color=WHITE,
align=PP_ALIGN.LEFT, italic=False, wrap=True):
tb = slide.shapes.add_textbox(x, y, w, h)
tf = tb.text_frame
tf.word_wrap = wrap
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
p.alignment = align
run = p.add_run()
run.text = text
run.font.size = Pt(size)
run.font.bold = bold
run.font.italic = italic
run.font.color.rgb = color
run.font.name = "Calibri"
return tb
def add_para(tf, text, size, bold=False, color=DARK_GREY,
align=PP_ALIGN.LEFT, italic=False, space_before=0):
from pptx.util import Pt as P
p = tf.add_paragraph()
p.alignment = align
p.space_before = P(space_before)
run = p.add_run()
run.text = text
run.font.size = P(size)
run.font.bold = bold
run.font.italic = italic
run.font.color.rgb = color
run.font.name = "Calibri"
return p
def add_bullet_box(slide, x, y, w, h, items, title=None,
title_size=17, bullet_size=14,
title_color=TEAL, bullet_color=DARK_GREY,
bg_color=None, indent=True):
if bg_color:
add_rect(slide, x, y, w, h, bg_color)
tb = slide.shapes.add_textbox(x + Inches(0.12), y + Inches(0.08),
w - Inches(0.24), h - Inches(0.16))
tf = tb.text_frame
tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
first = True
if title:
p = tf.paragraphs[0]
p.alignment = PP_ALIGN.LEFT
r = p.add_run()
r.text = title
r.font.size = Pt(title_size)
r.font.bold = True
r.font.color.rgb = title_color
r.font.name = "Calibri"
first = False
for item in items:
if first:
p = tf.paragraphs[0]; first = False
else:
p = tf.add_paragraph()
p.alignment = PP_ALIGN.LEFT
p.space_before = Pt(2)
run = p.add_run()
prefix = " \u2022 " if indent else "\u2022 "
run.text = prefix + item
run.font.size = Pt(bullet_size)
run.font.color.rgb = bullet_color
run.font.name = "Calibri"
return tb
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 1 – TITLE SLIDE
# ─────────────────────────────────────────────────────────────────────────────
def slide_title(prs):
s = prs.slides.add_slide(blank)
# Full dark-blue background
add_rect(s, 0, 0, W, H, DARK_BLUE)
# Decorative teal bar left
add_rect(s, 0, 0, Inches(0.5), H, TEAL)
# Gold accent line
add_rect(s, Inches(0.5), Inches(3.6), W - Inches(0.5), Inches(0.06), GOLD)
add_textbox(s, Inches(1.0), Inches(1.4), Inches(11), Inches(1.5),
"DIPLOPIA", 72, bold=True, color=WHITE, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(1.0), Inches(3.0), Inches(11), Inches(0.55),
"Double Vision – Etiology | Types | Investigations | Treatment",
22, color=TEAL, align=PP_ALIGN.LEFT)
add_textbox(s, Inches(1.0), Inches(3.8), Inches(11), Inches(0.45),
"A Comprehensive Clinical Overview",
18, italic=True, color=LIGHT_GREY, align=PP_ALIGN.LEFT)
# Bottom credit
add_textbox(s, Inches(1.0), Inches(6.8), Inches(11), Inches(0.4),
"Sources: Rosen's Emergency Medicine | Bradley & Daroff's Neurology | Adams & Victor's Neurology",
11, color=TEAL, align=PP_ALIGN.LEFT)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 2 – DEFINITION & OVERVIEW
# ─────────────────────────────────────────────────────────────────────────────
def slide_definition(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_GREY)
add_rect(s, 0, 0, W, Inches(1.2), DARK_BLUE)
add_rect(s, 0, Inches(1.2), Inches(0.08), H - Inches(1.2), TEAL)
add_textbox(s, Inches(0.3), Inches(0.2), Inches(12), Inches(0.8),
"DIPLOPIA – Definition & Overview", 28, bold=True, color=WHITE)
# Definition card
add_rect(s, Inches(0.4), Inches(1.4), Inches(12.5), Inches(1.3), WHITE)
tb = s.shapes.add_textbox(Inches(0.55), Inches(1.5), Inches(12.2), Inches(1.1))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
r = p.add_run()
r.text = "Diplopia"
r.font.bold = True; r.font.size = Pt(16); r.font.color.rgb = TEAL; r.font.name = "Calibri"
r2 = p.add_run()
r2.text = (" is the perception of two images from a single object (double vision). "
"It arises when the visual axes of the two eyes fail to converge on the same point "
"in space, causing non-corresponding retinal regions to be stimulated simultaneously.")
r2.font.size = Pt(15); r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
# Two columns
cols = [
("Monocular Diplopia",
["Persists when ONE eye is covered",
"Problem within the eye itself",
"Corneal / lenticular / retinal origin",
"Ophthalmic referral indicated"]),
("Binocular Diplopia",
["Resolves when EITHER eye is covered",
"Misalignment of visual axes",
"Neurological / orbital / NMJ origin",
"Urgent neuro/ophthalmic evaluation"]),
]
xs = [Inches(0.4), Inches(6.8)]
for i, (title, bullets) in enumerate(cols):
add_rect(s, xs[i], Inches(2.9), Inches(6.1), Inches(3.9), MID_BLUE)
add_rect(s, xs[i], Inches(2.9), Inches(6.1), Inches(0.55), TEAL)
add_textbox(s, xs[i] + Inches(0.15), Inches(2.93), Inches(5.8), Inches(0.5),
title, 17, bold=True, color=WHITE)
add_bullet_box(s, xs[i] + Inches(0.15), Inches(3.5), Inches(5.8), Inches(3.1),
bullets, bullet_size=14, bullet_color=WHITE)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 3 – TYPES
# ─────────────────────────────────────────────────────────────────────────────
def slide_types(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_GREY)
add_rect(s, 0, 0, W, Inches(1.2), DARK_BLUE)
add_rect(s, 0, Inches(1.2), Inches(0.08), H - Inches(1.2), TEAL)
add_textbox(s, Inches(0.3), Inches(0.2), Inches(12), Inches(0.8),
"TYPES OF DIPLOPIA", 28, bold=True, color=WHITE)
types = [
("Horizontal Diplopia",
"Images side by side",
["CN VI (lateral rectus) palsy", "CN III palsy (medial rectus weakness)", "Divergence insufficiency"]),
("Vertical Diplopia",
"Images stacked vertically",
["CN IV (superior oblique) palsy", "CN III palsy (elevator weakness)", "Skew deviation"]),
("Torsional Diplopia",
"Images tilted / rotated",
["CN IV palsy (classic)", "Orbital myositis", "Utricular dysfunction"]),
("Monocular Diplopia",
"Persists with one eye closed",
["Astigmatism", "Corneal irregularity", "Cataract / lens dislocation", "Macular disease"]),
("Binocular Diplopia",
"Resolves on covering one eye",
["Ocular motor nerve palsies", "Thyroid eye disease", "Myasthenia gravis", "Orbital trauma"]),
("Comitant / Incomitant",
"Deviation angle constant / variable",
["Comitant: childhood strabismus", "Incomitant: nerve palsy / restrictive"]),
]
cols = 3
box_w = Inches(4.1)
box_h = Inches(2.5)
xs = [Inches(0.25), Inches(4.6), Inches(8.95)]
ys = [Inches(1.35), Inches(4.0)]
for idx, (title, subtitle, bullets) in enumerate(types):
col = idx % cols
row = idx // cols
x, y = xs[col], ys[row]
add_rect(s, x, y, box_w, box_h, WHITE)
add_rect(s, x, y, box_w, Inches(0.6), MID_BLUE)
add_textbox(s, x + Inches(0.1), y + Inches(0.07), box_w - Inches(0.2), Inches(0.45),
title, 14, bold=True, color=WHITE)
add_textbox(s, x + Inches(0.1), y + Inches(0.62), box_w - Inches(0.2), Inches(0.35),
subtitle, 11, italic=True, color=TEAL)
add_bullet_box(s, x + Inches(0.1), y + Inches(1.0), box_w - Inches(0.2), Inches(1.35),
bullets, bullet_size=11, bullet_color=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 4 – ETIOLOGY (MONOCULAR)
# ─────────────────────────────────────────────────────────────────────────────
def slide_etiology_monocular(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_GREY)
add_rect(s, 0, 0, W, Inches(1.2), DARK_BLUE)
add_rect(s, 0, Inches(1.2), Inches(0.08), H - Inches(1.2), TEAL)
add_textbox(s, Inches(0.3), Inches(0.1), Inches(12), Inches(0.55),
"ETIOLOGY", 28, bold=True, color=WHITE)
add_textbox(s, Inches(0.3), Inches(0.65), Inches(12), Inches(0.45),
"Monocular Diplopia", 18, color=TEAL)
categories = [
("Corneal Causes", ["Astigmatism (irregular)", "Keratoconus", "Corneal scar / opacity",
"Dry eye syndrome", "Pterygium"]),
("Lenticular Causes", ["Cataract (nuclear, posterior subcapsular)", "Lens dislocation (subluxation)",
"Posterior capsule opacification", "Lens coloboma"]),
("Retinal Causes", ["Macular disease (epiretinal membrane)", "Macular degeneration",
"Macular hole", "Retinal detachment"]),
("Other / Neurological", ["Functional / conversion disorder (diagnosis of exclusion)",
"Occipital cortex lesion (cerebral diplopia)",
"Pharmacological agents", "Refractive error"]),
]
box_w = Inches(5.9)
box_h = Inches(2.55)
xs = [Inches(0.4), Inches(6.85)]
ys = [Inches(1.3), Inches(4.0)]
for idx, (cat, items) in enumerate(categories):
col = idx % 2
row = idx // 2
x, y = xs[col], ys[row]
add_rect(s, x, y, box_w, box_h, WHITE)
add_rect(s, x, y, box_w, Inches(0.5), MID_BLUE)
add_textbox(s, x + Inches(0.12), y + Inches(0.06), box_w - Inches(0.2), Inches(0.4),
cat, 15, bold=True, color=WHITE)
add_bullet_box(s, x + Inches(0.12), y + Inches(0.55), box_w - Inches(0.2), Inches(1.85),
items, bullet_size=13, bullet_color=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 5 – ETIOLOGY (BINOCULAR) – part 1
# ─────────────────────────────────────────────────────────────────────────────
def slide_etiology_binocular(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_GREY)
add_rect(s, 0, 0, W, Inches(1.2), DARK_BLUE)
add_rect(s, 0, Inches(1.2), Inches(0.08), H - Inches(1.2), TEAL)
add_textbox(s, Inches(0.3), Inches(0.1), Inches(12), Inches(0.55),
"ETIOLOGY", 28, bold=True, color=WHITE)
add_textbox(s, Inches(0.3), Inches(0.65), Inches(12), Inches(0.45),
"Binocular Diplopia – Differential Diagnosis", 18, color=TEAL)
rows = [
("Structural Orbitopathy",
"Trauma, Orbital infection/abscess, Craniofacial masses, Orbital blow-out fracture"),
("Orbital Myositis",
"Thyroid eye disease (Graves), Wegener granulomatosis, Giant cell arteritis, SLE, Dermatomyositis, Sarcoidosis, Rheumatoid arthritis, Idiopathic orbital pseudotumor"),
("CN III Palsy",
"Hypertensive / diabetic vasculopathy, Posterior communicating artery aneurysm, Compression, Multiple sclerosis, Idiopathic intracranial hypertension, Trauma"),
("CN IV Palsy",
"Microvascular ischemia (most common), Head trauma (most common traumatic CN palsy), Hydrocephalus, Mass lesion"),
("CN VI Palsy",
"Microvascular ischemia, Raised ICP (false localising sign), Cavernous sinus lesion, Pontine tumor, Trauma"),
("Multiple CN Palsies",
"Cavernous sinus syndrome, Orbital apex syndrome, Meningitis, Miller-Fisher syndrome"),
("Brainstem / Neuroaxial",
"Stroke / TIA, MS (internuclear ophthalmoplegia – INO), Basilar artery thrombosis, Wernicke encephalopathy, Tumour, Haemorrhage"),
("Neuromuscular",
"Myasthenia gravis, Botulism, Lambert-Eaton syndrome"),
]
y_start = Inches(1.32)
row_h = Inches(0.62)
col1_w = Inches(3.5)
col2_w = Inches(9.3)
for i, (label, detail) in enumerate(rows):
y = y_start + i * row_h
bg = WHITE if i % 2 == 0 else LIGHT_GREY
add_rect(s, Inches(0.25), y, col1_w, row_h, MID_BLUE if i == 0 else (TEAL if i % 2 == 0 else RGBColor(0xE8, 0xF4, 0xF8)))
add_rect(s, Inches(0.25) + col1_w, y, col2_w, row_h, bg)
label_color = WHITE if i == 0 else (DARK_BLUE if i % 2 == 0 else MID_BLUE)
add_textbox(s, Inches(0.35), y + Inches(0.1), col1_w - Inches(0.15), row_h - Inches(0.15),
label, 12, bold=True, color=label_color)
add_textbox(s, Inches(0.25) + col1_w + Inches(0.1), y + Inches(0.1),
col2_w - Inches(0.2), row_h - Inches(0.15),
detail, 12, color=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 6 – CLINICAL APPROACH / HISTORY
# ─────────────────────────────────────────────────────────────────────────────
def slide_clinical_approach(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_GREY)
add_rect(s, 0, 0, W, Inches(1.2), DARK_BLUE)
add_rect(s, 0, Inches(1.2), Inches(0.08), H - Inches(1.2), TEAL)
add_textbox(s, Inches(0.3), Inches(0.2), Inches(12), Inches(0.8),
"CLINICAL APPROACH – History & Examination", 26, bold=True, color=WHITE)
history_items = [
"Monocular vs. binocular? (cover test – the key first step)",
"Onset: sudden (ischaemic/vascular) vs. gradual (mechanical/neoplastic)",
"Timing: constant vs. intermittent (MG fluctuates, worsens with fatigue)",
"Direction: horizontal (CN VI) | vertical (CN IV/III) | torsional (CN IV)",
"Associated pain: CN III aneurysm, GCA, orbital pseudotumor",
"Ptosis: CN III palsy, Myasthenia gravis, Horner syndrome",
"Headache, fever, neck stiffness → meningoencephalitis",
"Systemic symptoms: thyroid, DM, HTN, autoimmune disease",
"History of trauma, malignancy, multiple sclerosis",
]
exam_items = [
"Visual acuity and confrontation fields",
"Pupil assessment (dilated pupil → CN III / aneurysm)",
"Extraocular movements – direction of gaze worsening diplopia",
"Cover-uncover test and alternate cover test",
"Proptosis, lid retraction, chemosis (thyroid/orbital)",
"Ptosis and fatigability on sustained upgaze (MG)",
"Facial sensation, hearing (cavernous sinus)",
"Ice pack test: improvement of ptosis → Myasthenia gravis",
]
# History column
add_rect(s, Inches(0.25), Inches(1.3), Inches(6.2), Inches(5.9), WHITE)
add_rect(s, Inches(0.25), Inches(1.3), Inches(6.2), Inches(0.5), MID_BLUE)
add_textbox(s, Inches(0.4), Inches(1.35), Inches(6.0), Inches(0.4),
"History", 16, bold=True, color=WHITE)
add_bullet_box(s, Inches(0.35), Inches(1.85), Inches(6.0), Inches(5.2),
history_items, bullet_size=13, bullet_color=DARK_GREY)
# Exam column
add_rect(s, Inches(6.8), Inches(1.3), Inches(6.2), Inches(5.9), WHITE)
add_rect(s, Inches(6.8), Inches(1.3), Inches(6.2), Inches(0.5), MID_BLUE)
add_textbox(s, Inches(6.95), Inches(1.35), Inches(6.0), Inches(0.4),
"Examination", 16, bold=True, color=WHITE)
add_bullet_box(s, Inches(6.9), Inches(1.85), Inches(6.0), Inches(5.2),
exam_items, bullet_size=13, bullet_color=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 7 – INVESTIGATIONS
# ─────────────────────────────────────────────────────────────────────────────
def slide_investigations(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_GREY)
add_rect(s, 0, 0, W, Inches(1.2), DARK_BLUE)
add_rect(s, 0, Inches(1.2), Inches(0.08), H - Inches(1.2), TEAL)
add_textbox(s, Inches(0.3), Inches(0.2), Inches(12), Inches(0.8),
"INVESTIGATIONS", 28, bold=True, color=WHITE)
sections = [
("Bedside / Clinical Tests",
["Cover-uncover & alternate cover test",
"Ice pack test (sensitivity 80%) – improvement of ptosis suggests MG",
"Sustained upgaze fatigability (sensitivity 80%, specificity 63%)",
"Maddox rod test – quantifies vertical & torsional deviations",
"Prism cover test – measures angle of deviation"]),
("Laboratory Studies",
["FBC, RFT, LFT, glucose (vascular risk factor screen)",
"HbA1c, fasting glucose (diabetes – CN VI/IV/III palsy)",
"Thyroid function tests (T3, T4, TSH) – thyroid eye disease",
"ESR + CRP – if >50 yrs: rule out Giant Cell Arteritis (ESR >50, CRP >20)",
"Temporal artery biopsy – if vasculitis / GCA strongly suspected",
"AChR antibodies (acetylcholine receptor Ab) – Myasthenia gravis",
"Anti-MuSK antibodies – seronegative MG"]),
("Neuroimaging",
["MRI brain + orbits with gadolinium – study of choice for most diplopia",
"Fat-suppressed orbital MRI – CN III/IV/VI neuropathy workup",
"MRI/MRA – rule out aneurysm in incomplete CN III palsy",
"CT orbits (contrast) – orbital infection / abscess, trauma",
"CT head – if MRI unavailable; trauma (blow-out fracture)"]),
("Special Investigations",
["Lumbar puncture – CNS infection, idiopathic intracranial hypertension",
"CT venogram / MR venogram – cavernous sinus thrombosis",
"Tensilon test – historical (edrophonium no longer available)",
"Repetitive nerve stimulation / Single-fibre EMG – Myasthenia gravis",
"Hess chart – maps extraocular muscle restriction pattern",
"B-scan ultrasound – extraocular muscle thickness (thyroid eye disease)"]),
]
box_w = Inches(5.9)
box_h = Inches(2.65)
xs = [Inches(0.4), Inches(6.85)]
ys = [Inches(1.3), Inches(4.1)]
for idx, (title, items) in enumerate(sections):
col = idx % 2
row = idx // 2
x, y = xs[col], ys[row]
add_rect(s, x, y, box_w, box_h, WHITE)
add_rect(s, x, y, box_w, Inches(0.5), MID_BLUE)
add_textbox(s, x + Inches(0.12), y + Inches(0.07), box_w - Inches(0.2), Inches(0.42),
title, 15, bold=True, color=WHITE)
add_bullet_box(s, x + Inches(0.12), y + Inches(0.55), box_w - Inches(0.2), Inches(2.0),
items, bullet_size=12, bullet_color=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 8 – CN PALSY SUMMARY TABLE
# ─────────────────────────────────────────────────────────────────────────────
def slide_cn_palsy(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_GREY)
add_rect(s, 0, 0, W, Inches(1.2), DARK_BLUE)
add_rect(s, 0, Inches(1.2), Inches(0.08), H - Inches(1.2), TEAL)
add_textbox(s, Inches(0.3), Inches(0.2), Inches(12), Inches(0.8),
"CRANIAL NERVE PALSY – Summary", 26, bold=True, color=WHITE)
headers = ["CN Palsy", "Muscle Affected", "Eye Position", "Diplopia Direction", "Classic Features"]
rows_data = [
["CN III (Oculomotor)", "SR, IR, MR, IO, Levator palpebrae, pupillary sphincter",
"Down & Out", "All directions except lateral gaze to affected side",
"Ptosis, dilated pupil (surgical CN III); pupil sparing (medical/diabetic)"],
["CN IV (Trochlear)", "Superior oblique",
"Slightly elevated & extorted", "Vertical / torsional; worse on contralateral gaze",
"Head tilt to opposite shoulder; 3-step test positive; most common traumatic CN palsy"],
["CN VI (Abducens)", "Lateral rectus",
"Convergent (esotropia)", "Horizontal; worse on ipsilateral gaze",
"Most common ocular motor palsy; raised ICP = false localising sign"],
]
col_widths = [Inches(1.8), Inches(2.8), Inches(1.7), Inches(3.1), Inches(3.6)]
header_h = Inches(0.5)
row_h = Inches(1.8)
table_x = Inches(0.25)
table_y = Inches(1.3)
# Header
x = table_x
for ci, hdr in enumerate(headers):
add_rect(s, x, table_y, col_widths[ci], header_h, DARK_BLUE)
add_textbox(s, x + Inches(0.05), table_y + Inches(0.08),
col_widths[ci] - Inches(0.1), header_h - Inches(0.1),
hdr, 13, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
x += col_widths[ci]
for ri, row in enumerate(rows_data):
y = table_y + header_h + ri * row_h
x = table_x
bg = WHITE if ri % 2 == 0 else RGBColor(0xE8, 0xF4, 0xF8)
first_col_color = TEAL if ri % 2 == 0 else MID_BLUE
for ci, cell in enumerate(row):
add_rect(s, x, y, col_widths[ci], row_h, first_col_color if ci == 0 else bg)
fc = WHITE if ci == 0 else DARK_GREY
add_textbox(s, x + Inches(0.05), y + Inches(0.1),
col_widths[ci] - Inches(0.1), row_h - Inches(0.15),
cell, 11, bold=(ci == 0), color=fc, wrap=True)
x += col_widths[ci]
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 9 – TREATMENT
# ─────────────────────────────────────────────────────────────────────────────
def slide_treatment(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_GREY)
add_rect(s, 0, 0, W, Inches(1.2), DARK_BLUE)
add_rect(s, 0, Inches(1.2), Inches(0.08), H - Inches(1.2), TEAL)
add_textbox(s, Inches(0.3), Inches(0.2), Inches(12), Inches(0.8),
"TREATMENT OF DIPLOPIA", 28, bold=True, color=WHITE)
treatments = [
("1. Occlusion / Patching",
["Eliminates one image – acute phase management",
"Patch either eye (adult); alternate patch each eye in children <6 yrs to prevent amblyopia",
"Frosted tape / clip-on occluder on one spectacle lens",
"Partial occlusion useful (e.g., reading-only diplopia: occlude lower bifocal)"]),
("2. Prismatic Correction",
["Fresnel prisms (temporary / trial) or ground-in prisms in spectacles",
"Effective when deviation is not too large and no significant cyclodeviation",
"Allows binocular single vision in useful field of gaze",
"Reassess once alignment is stable (6 months)"]),
("3. Botulinum Toxin",
["Injected into antagonist muscle to reduce deviation",
"Useful in acute abducens palsies (bilateral / traumatic)",
"Mixed success in both comitant and incomitant strabismus",
"Effects transient: 3–4 months; risks – ptosis, dry eye, worsening diplopia"]),
("4. Strabismus Surgery",
["For long-standing stable strabismus (comitant or incomitant)",
"Requires ≥6 months of stable ocular alignment measurements",
"Recession / resection of extraocular muscles",
"Adjustable suture techniques allow fine-tuning post-op"]),
("5. Orthoptic Exercises",
["Primarily for convergence insufficiency",
"Pencil push-ups, base-out prism exercises",
"Effective for fusional vergence insufficiency"]),
("6. Treat Underlying Cause",
["Thyroid eye disease: orbital decompression, steroids, selenium",
"MG: pyridostigmine, immunosuppression, thymectomy",
"GCA: high-dose systemic corticosteroids urgently",
"Aneurysm: neurosurgical / endovascular clipping / coiling",
"MS: high-dose IV methylprednisolone for acute demyelination"]),
]
box_w = Inches(3.9)
box_h = Inches(2.5)
xs = [Inches(0.25), Inches(4.6), Inches(8.95)]
ys = [Inches(1.3), Inches(4.0)]
for idx, (title, items) in enumerate(treatments):
col = idx % 3
row = idx // 3
x, y = xs[col], ys[row]
add_rect(s, x, y, box_w, box_h, WHITE)
add_rect(s, x, y, box_w, Inches(0.52), MID_BLUE)
add_textbox(s, x + Inches(0.1), y + Inches(0.07), box_w - Inches(0.2), Inches(0.42),
title, 13, bold=True, color=WHITE)
add_bullet_box(s, x + Inches(0.1), y + Inches(0.57), box_w - Inches(0.2), Inches(1.85),
items, bullet_size=11, bullet_color=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 10 – SPECIAL CONDITIONS
# ─────────────────────────────────────────────────────────────────────────────
def slide_special(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_GREY)
add_rect(s, 0, 0, W, Inches(1.2), DARK_BLUE)
add_rect(s, 0, Inches(1.2), Inches(0.08), H - Inches(1.2), TEAL)
add_textbox(s, Inches(0.3), Inches(0.2), Inches(12), Inches(0.8),
"SPECIAL CONDITIONS CAUSING DIPLOPIA", 26, bold=True, color=WHITE)
conditions = [
("Myasthenia Gravis",
["Diplopia: variable, fatigable, worse in the evening",
"Ptosis + weakness on forced eye closure",
"Ice pack test positive (ptosis improves)",
"Rx: Pyridostigmine, steroids, azathioprine, thymectomy"]),
("Thyroid Eye Disease (Graves)",
["Inferior & medial recti fibrosis → restricted elevation & abduction",
"Proptosis, lid retraction, chemosis",
"CT/MRI: bilateral muscle enlargement (sparing tendons)",
"Rx: Selenium, steroids, orbital decompression, prisms/surgery"]),
("Internuclear Ophthalmoplegia (INO)",
["MLF lesion → failure of ipsilateral adduction on lateral gaze",
"Nystagmus in abducting eye",
"Bilateral INO strongly suggests MS",
"Rx: Treat underlying cause (usually MS)"]),
("Wernicke Encephalopathy",
["Triad: Ophthalmoplegia + Ataxia + Confusion",
"Bilateral CN VI palsy + nystagmus typical",
"Caused by thiamine (Vit B1) deficiency",
"Rx: IV thiamine URGENTLY (before glucose)"]),
("Miller-Fisher Syndrome",
["Triad: Ophthalmoplegia + Ataxia + Areflexia",
"GQ1b antibody positive (~90%)",
"Variant of Guillain-Barré syndrome",
"Rx: IVIG or plasmapheresis"]),
("Cavernous Sinus Syndrome",
["Multiple CN palsies: III, IV, V1/V2, VI + Horner",
"Causes: thrombosis, aneurysm, tumor, infection, fistula",
"MRI/MRV/CT venogram diagnostic",
"Rx: Anticoagulation (thrombosis), treat underlying cause"]),
]
box_w = Inches(3.9)
box_h = Inches(2.5)
xs = [Inches(0.25), Inches(4.6), Inches(8.95)]
ys = [Inches(1.3), Inches(4.0)]
for idx, (title, items) in enumerate(conditions):
col = idx % 3
row = idx // 3
x, y = xs[col], ys[row]
add_rect(s, x, y, box_w, box_h, WHITE)
add_rect(s, x, y, box_w, Inches(0.52), TEAL)
add_textbox(s, x + Inches(0.1), y + Inches(0.07), box_w - Inches(0.2), Inches(0.42),
title, 13, bold=True, color=WHITE)
add_bullet_box(s, x + Inches(0.1), y + Inches(0.57), box_w - Inches(0.2), Inches(1.85),
items, bullet_size=11, bullet_color=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 11 – SUMMARY / KEY POINTS
# ─────────────────────────────────────────────────────────────────────────────
def slide_summary(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, DARK_BLUE)
add_rect(s, 0, 0, Inches(0.5), H, TEAL)
add_rect(s, Inches(0.5), Inches(1.45), W - Inches(0.5), Inches(0.05), GOLD)
add_textbox(s, Inches(0.8), Inches(0.25), Inches(12), Inches(1.0),
"KEY TAKEAWAYS", 32, bold=True, color=WHITE)
points = [
"Always perform the COVER TEST first – this separates monocular from binocular diplopia.",
"Sudden-onset painless binocular diplopia in a vascular-risk patient suggests microvascular CN palsy – CN VI > CN IV > CN III.",
"A dilated pupil with CN III palsy = posterior communicating artery aneurysm until proven otherwise – emergent imaging required.",
"Complete CN III palsy with pupil-sparing in a diabetic patient suggests microvascular aetiology (medical CN III).",
"Bilateral INO in a young patient is multiple sclerosis until proven otherwise.",
"Fluctuating, fatigable diplopia worse in the evening = Myasthenia Gravis – ice pack test and AChR antibodies.",
"GCA must be excluded with ESR/CRP in any patient >50 with new-onset diplopia and headache.",
"MRI brain + orbits with gadolinium is the imaging modality of choice for most binocular diplopia.",
"Treatment is cause-directed: patch/prisms for acute relief, then definitive surgery/systemic therapy once stable.",
]
tb = s.shapes.add_textbox(Inches(0.8), Inches(1.6), Inches(12.1), Inches(5.6))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
first = True
for i, pt in enumerate(points):
if first: p = tf.paragraphs[0]; first = False
else: p = tf.add_paragraph()
p.space_before = Pt(4)
r = p.add_run()
r.text = f" {i+1}. " + pt
r.font.size = Pt(14)
r.font.color.rgb = WHITE if i % 2 == 0 else TEAL
r.font.name = "Calibri"
# ─────────────────────────────────────────────────────────────────────────────
# BUILD
# ─────────────────────────────────────────────────────────────────────────────
slide_title(prs)
slide_definition(prs)
slide_types(prs)
slide_etiology_monocular(prs)
slide_etiology_binocular(prs)
slide_clinical_approach(prs)
slide_investigations(prs)
slide_cn_palsy(prs)
slide_treatment(prs)
slide_special(prs)
slide_summary(prs)
out = "/tmp/workspace/diplopia-ppt/Diplopia_Presentation.pptx"
prs.save(out)
print(f"Saved: {out} ({len(prs.slides)} slides)")
cd /tmp/workspace/diplopia-ppt && python make_ppt.py
Diplopia Presentation
Presentation · PPTX
| Slide | Content |
|---|---|
| 1 | Title slide |
| 2 | Definition & Overview - monocular vs. binocular diplopia |
| 3 | Types - Horizontal, Vertical, Torsional, Monocular, Binocular, Comitant/Incomitant |
| 4 | Etiology - Monocular (corneal, lenticular, retinal, functional) |
| 5 | Etiology - Binocular (full differential table: orbitopathy, orbital myositis, CN III/IV/VI palsies, brainstem, neuromuscular) |
| 6 | Clinical Approach - History & Examination (two-column layout) |
| 7 | Investigations - Bedside tests, Labs, Neuroimaging, Special tests |
| 8 | CN Palsy Summary Table - CN III, IV, VI with eye position, diplopia direction, features |
| 9 | Treatment - Occlusion, Prisms, Botulinum toxin, Surgery, Orthoptics, Treat cause |
| 10 | Special Conditions - MG, Thyroid eye disease, INO, Wernicke, Miller-Fisher, Cavernous sinus |
| 11 | Key Takeaways (9 clinical pearls) |
Prepare a ppt pink colour background topic is status epilepticus. Subheading etiology pathology investigation and treatment for adults and children
~/diplopia-ppt/make_se_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
# ── Pink Palette ──────────────────────────────────────────────────────────────
DEEP_PINK = RGBColor(0xC2, 0x18, 0x5B) # header bars, title bg
MID_PINK = RGBColor(0xE9, 0x3E, 0x7E) # accent
SOFT_PINK = RGBColor(0xF8, 0xBB, 0xD0) # slide background
LIGHT_PINK = RGBColor(0xFF, 0xE4, 0xEF) # card / box bg
PALE_PINK = RGBColor(0xFF, 0xF0, 0xF5) # alternating table rows
DARK_BERRY = RGBColor(0x6A, 0x00, 0x35) # dark text on pink
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
DARK_GREY = RGBColor(0x22, 0x22, 0x33)
GOLD = RGBColor(0xFF, 0xD7, 0x00)
W = Inches(13.333)
H = Inches(7.5)
prs = Presentation()
prs.slide_width = W
prs.slide_height = H
blank = prs.slide_layouts[6]
# ─────────────────────────────────────────────────────────────────────────────
# Helpers
# ─────────────────────────────────────────────────────────────────────────────
def add_rect(slide, x, y, w, h, fill_rgb):
shape = slide.shapes.add_shape(1, x, y, w, h)
shape.line.fill.background()
fill = shape.fill; fill.solid(); fill.fore_color.rgb = fill_rgb
return shape
def add_tb(slide, x, y, w, h, text, size, bold=False, color=WHITE,
align=PP_ALIGN.LEFT, italic=False, wrap=True):
tb = slide.shapes.add_textbox(x, y, w, h)
tf = tb.text_frame; tf.word_wrap = wrap
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run()
r.text = text; r.font.size = Pt(size); r.font.bold = bold
r.font.italic = italic; r.font.color.rgb = color; r.font.name = "Calibri"
return tb
def add_para(tf, text, size, bold=False, color=DARK_GREY,
align=PP_ALIGN.LEFT, italic=False, sp=2):
p = tf.add_paragraph(); p.alignment = align; p.space_before = Pt(sp)
r = p.add_run(); r.text = text
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.color.rgb = color; r.font.name = "Calibri"; return p
def bullet_box(slide, x, y, w, h, items, title=None,
tsz=15, bsz=12, tc=MID_PINK, bc=DARK_GREY, bg=None, indent=True):
if bg: add_rect(slide, x, y, w, h, bg)
tb = slide.shapes.add_textbox(x + Inches(0.1), y + Inches(0.07),
w - Inches(0.2), h - Inches(0.14))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
first = True
if title:
p = tf.paragraphs[0]; r = p.add_run()
r.text = title; r.font.size = Pt(tsz); r.font.bold = True
r.font.color.rgb = tc; r.font.name = "Calibri"; first = False
for item in items:
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False
p.space_before = Pt(2)
r = p.add_run()
r.text = (" \u2022 " if indent else "\u2022 ") + item
r.font.size = Pt(bsz); r.font.color.rgb = bc; r.font.name = "Calibri"
def slide_header(s, title, subtitle=None):
add_rect(s, 0, 0, W, H, SOFT_PINK)
add_rect(s, 0, 0, W, Inches(1.15), DEEP_PINK)
add_rect(s, 0, Inches(1.15), Inches(0.09), H - Inches(1.15), MID_PINK)
add_tb(s, Inches(0.28), Inches(0.15), Inches(12.5), Inches(0.7),
title, 28, bold=True, color=WHITE)
if subtitle:
add_tb(s, Inches(0.28), Inches(0.75), Inches(12.5), Inches(0.38),
subtitle, 16, color=SOFT_PINK)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 1 – TITLE
# ─────────────────────────────────────────────────────────────────────────────
def s1_title(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, SOFT_PINK)
add_rect(s, 0, 0, Inches(0.55), H, DEEP_PINK)
add_rect(s, Inches(0.55), Inches(3.5), W - Inches(0.55), Inches(0.06), GOLD)
add_tb(s, Inches(0.9), Inches(1.2), Inches(11.5), Inches(1.6),
"STATUS EPILEPTICUS", 66, bold=True, color=DEEP_PINK)
add_tb(s, Inches(0.9), Inches(2.85), Inches(11.5), Inches(0.6),
"Etiology | Pathophysiology | Investigations | Treatment",
22, color=MID_PINK)
add_tb(s, Inches(0.9), Inches(3.6), Inches(11.5), Inches(0.5),
"Adults & Children – A Comprehensive Clinical Overview",
18, italic=True, color=DARK_BERRY)
add_tb(s, Inches(0.9), Inches(4.3), Inches(11.5), Inches(0.85),
"\"Status epilepticus is a single seizure \u22655 minutes or two or more seizures\n"
"without recovery of consciousness between seizures – a true neurological emergency.\"",
14, italic=True, color=DARK_GREY)
add_tb(s, Inches(0.9), Inches(6.8), Inches(11.5), Inches(0.4),
"Sources: Tintinalli's Emergency Medicine | Rosen's Emergency Medicine | "
"Harrison's Principles | Adams & Victor | Harriet Lane Handbook",
11, color=MID_PINK)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 2 – DEFINITION & CLASSIFICATION
# ─────────────────────────────────────────────────────────────────────────────
def s2_definition(prs):
s = prs.slides.add_slide(blank)
slide_header(s, "DEFINITION & CLASSIFICATION")
# Definition card
add_rect(s, Inches(0.25), Inches(1.25), Inches(12.8), Inches(1.3), LIGHT_PINK)
tb = s.shapes.add_textbox(Inches(0.4), Inches(1.32), Inches(12.5), Inches(1.1))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
r = p.add_run(); r.text = "Definition: "
r.font.bold = True; r.font.size = Pt(15); r.font.color.rgb = DEEP_PINK; r.font.name = "Calibri"
r2 = p.add_run()
r2.text = ("Status epilepticus (SE) is defined as a single seizure \u22655 minutes in duration "
"OR two or more discrete seizures without full recovery of consciousness between them. "
"After 5 min, seizures are unlikely to terminate spontaneously and more likely to cause "
"irreversible neuronal damage.")
r2.font.size = Pt(14); r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
# ILAE Time Domains table
add_rect(s, Inches(0.25), Inches(2.65), Inches(12.8), Inches(0.45), DEEP_PINK)
add_tb(s, Inches(0.35), Inches(2.7), Inches(12.5), Inches(0.38),
"ILAE Time Domains for SE (Operational Definition)", 13, bold=True, color=WHITE)
rows = [
("SE Type", "Likely ongoing seizure (t1)", "Long-term sequelae (t2)"),
("Tonic-clonic (convulsive)", "5 minutes", "30 minutes"),
("Focal with impaired consciousness", "10 minutes", ">60 minutes"),
("Absence SE", "10–15 minutes", "Unknown"),
]
col_ws = [Inches(5.0), Inches(3.8), Inches(3.8)]
for ri, row in enumerate(rows):
y = Inches(3.1) + ri * Inches(0.55)
bg = DEEP_PINK if ri == 0 else (LIGHT_PINK if ri % 2 == 1 else PALE_PINK)
fc = WHITE if ri == 0 else DARK_GREY
x = Inches(0.25)
for ci, cell in enumerate(row):
add_rect(s, x, y, col_ws[ci], Inches(0.52), bg)
add_tb(s, x + Inches(0.05), y + Inches(0.07), col_ws[ci] - Inches(0.1), Inches(0.4),
cell, 13, bold=(ri == 0), color=fc)
x += col_ws[ci]
# Classification boxes
types = [
("Convulsive SE (CSE)",
["Generalized tonic-clonic movements", "Most common; highest morbidity",
"Obvious clinical presentation"]),
("Nonconvulsive SE (NCSE)",
["Coma or fluctuating consciousness", "No overt convulsions",
"Diagnosis requires EEG", "Subtle signs: twitching, eye deviation"]),
("Refractory SE",
["Persists despite 2 adequate AED trials", "Usually >60 minutes",
"Requires ICU & continuous EEG monitoring"]),
]
xs = [Inches(0.25), Inches(4.6), Inches(8.95)]
for i, (t, b) in enumerate(types):
add_rect(s, xs[i], Inches(5.55), Inches(4.1), Inches(1.7), LIGHT_PINK)
add_rect(s, xs[i], Inches(5.55), Inches(4.1), Inches(0.45), MID_PINK)
add_tb(s, xs[i] + Inches(0.1), Inches(5.57), Inches(3.9), Inches(0.4),
t, 13, bold=True, color=WHITE)
bullet_box(s, xs[i] + Inches(0.1), Inches(6.05), Inches(3.9), Inches(1.1),
b, bsz=11, bc=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 3 – ETIOLOGY
# ─────────────────────────────────────────────────────────────────────────────
def s3_etiology(prs):
s = prs.slides.add_slide(blank)
slide_header(s, "ETIOLOGY OF STATUS EPILEPTICUS")
# Adults column
adult_cats = [
("Medication-Related", ["AED withdrawal / non-compliance (most common)", "Sub-therapeutic AED levels",
"Drug toxicity (TCA, isoniazid, theophylline)"]),
("Structural / CNS", ["Acute stroke / haemorrhage", "CNS tumour (primary or metastatic)",
"Head trauma", "Prior CNS injury (old stroke, TBI)"]),
("Infectious / Inflammatory", ["Meningitis / encephalitis (bacterial, viral, TB)",
"Autoimmune encephalitis (anti-NMDAR, LGI1, CASPR2)",
"HIV-related CNS disease"]),
("Metabolic", ["Hypoglycaemia / hyperglycaemia", "Hyponatraemia / hypernatraemia",
"Hypocalcaemia / hypomagnesaemia", "Hepatic / uraemic encephalopathy",
"Thiamine deficiency (Wernicke)"]),
("Toxic", ["Alcohol withdrawal", "Drug intoxication / overdose",
"Cocaine, amphetamines, organophosphates"]),
("Vascular / Other", ["Hypoxia / anoxia (post-cardiac arrest)",
"Hypertensive encephalopathy / PRES",
"Refractory / cryptogenic epilepsy"]),
]
child_cats = [
("Febrile SE", ["Most common cause in children <5 yrs",
"Prolonged febrile seizure (>30 min)", "Usually benign prognosis"]),
("Structural", ["Cortical dysplasia / malformations",
"Perinatal brain injury (HIE)", "Tuberous sclerosis"]),
("Infectious", ["Bacterial meningitis", "Viral encephalitis (HSV, EV)",
"Cerebral malaria (endemic regions)"]),
("Metabolic / Genetic", ["Inborn errors of metabolism", "Pyridoxine (B6) deficiency (neonates)",
"Mitochondrial disorders", "Dravet syndrome (SCN1A)"]),
("AED-Related", ["AED withdrawal / non-compliance",
"Sub-therapeutic levels in known epilepsy"]),
("Immune / Other", ["FIRES (Febrile Infection-Related Epilepsy Syndrome)",
"Anti-NMDAR encephalitis", "Unknown / cryptogenic (~50%)"]),
]
box_w = Inches(6.0); box_h = Inches(1.3)
ys = [Inches(1.25), Inches(2.67), Inches(4.09), Inches(5.51),
Inches(1.25), Inches(2.67), Inches(4.09), Inches(5.51)]
# Header strips
add_rect(s, Inches(0.2), Inches(1.18), Inches(6.1), Inches(0.45), MID_PINK)
add_tb(s, Inches(0.3), Inches(1.21), Inches(6.0), Inches(0.38),
"ADULTS", 15, bold=True, color=WHITE)
add_rect(s, Inches(6.7), Inches(1.18), Inches(6.4), Inches(0.45), MID_PINK)
add_tb(s, Inches(6.8), Inches(1.21), Inches(6.2), Inches(0.38),
"CHILDREN", 15, bold=True, color=WHITE)
for idx, (cat, items) in enumerate(adult_cats):
ri = idx % 4; ci = idx // 4
y = Inches(1.63) + ri * Inches(1.46)
x = Inches(0.2) + ci * Inches(3.05)
bw = Inches(2.95)
add_rect(s, x, y, bw, Inches(1.38), LIGHT_PINK)
add_rect(s, x, y, bw, Inches(0.4), DEEP_PINK)
add_tb(s, x + Inches(0.08), y + Inches(0.06), bw - Inches(0.15), Inches(0.35),
cat, 12, bold=True, color=WHITE)
bullet_box(s, x + Inches(0.08), y + Inches(0.44), bw - Inches(0.15), Inches(0.9),
items, bsz=10, bc=DARK_GREY)
for idx, (cat, items) in enumerate(child_cats):
ri = idx % 4; ci = idx // 4
y = Inches(1.63) + ri * Inches(1.46)
x = Inches(6.7) + ci * Inches(3.2)
bw = Inches(3.1)
add_rect(s, x, y, bw, Inches(1.38), LIGHT_PINK)
add_rect(s, x, y, bw, Inches(0.4), DEEP_PINK)
add_tb(s, x + Inches(0.08), y + Inches(0.06), bw - Inches(0.15), Inches(0.35),
cat, 12, bold=True, color=WHITE)
bullet_box(s, x + Inches(0.08), y + Inches(0.44), bw - Inches(0.15), Inches(0.9),
items, bsz=10, bc=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 4 – PATHOPHYSIOLOGY
# ─────────────────────────────────────────────────────────────────────────────
def s4_patho(prs):
s = prs.slides.add_slide(blank)
slide_header(s, "PATHOPHYSIOLOGY")
# Phase timeline
phases = [
("Normal Seizure\n(<5 min)",
["Increased neuronal excitation", "GABA-mediated inhibition intact",
"Self-limited; spontaneous termination"]),
("Early SE\n(5–30 min)",
["GABA\u2090 receptor internalisation \u2193", "NMDA receptor up-regulation \u2191",
"Reduced benzodiazepine efficacy", "BBB disruption begins"]),
("Established SE\n(30–60 min)",
["Hyperthermia, metabolic acidosis", "Hypotension, hypoxia develop",
"Cardiac dysrhythmias possible", "Neuronal excitotoxicity begins"]),
("Refractory SE\n(>60 min)",
["Severe excitotoxic neuronal death", "Hippocampal injury / sclerosis",
"Pulmonary oedema, rhabdomyolysis", "High risk of permanent sequelae"]),
]
xs = [Inches(0.2), Inches(3.45), Inches(6.7), Inches(9.95)]
bw = Inches(3.2); bh = Inches(2.9)
arrow_y = Inches(2.7)
# Draw connecting arrows
for i in range(3):
add_rect(s, xs[i] + bw, arrow_y, Inches(0.25), Inches(0.12), MID_PINK)
colors = [MID_PINK, DEEP_PINK, RGBColor(0xAD, 0x14, 0x57), RGBColor(0x7B, 0x00, 0x2E)]
for i, (phase, items) in enumerate(phases):
add_rect(s, xs[i], Inches(1.25), bw, bh, LIGHT_PINK)
add_rect(s, xs[i], Inches(1.25), bw, Inches(0.7), colors[i])
add_tb(s, xs[i] + Inches(0.1), Inches(1.28), bw - Inches(0.2), Inches(0.65),
phase, 13, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
bullet_box(s, xs[i] + Inches(0.1), Inches(1.98), bw - Inches(0.2), Inches(2.1),
items, bsz=11, bc=DARK_GREY)
# Mechanisms section
add_rect(s, Inches(0.2), Inches(4.28), Inches(12.9), Inches(0.42), DEEP_PINK)
add_tb(s, Inches(0.3), Inches(4.31), Inches(12.7), Inches(0.38),
"Cellular Mechanisms", 14, bold=True, color=WHITE)
mech_cols = [
("Inhibitory Failure",
["GABA\u2090 receptor \u2193 surface expression", "Receptor internalisation (>5–10 min)",
"Benzodiazepine resistance develops", "GABA\u2082 receptor remains effective longer"]),
("Excitatory Excess",
["NMDA receptor up-regulation \u2191", "Glutamate accumulation (excitotoxic)",
"Intracellular Ca\u00b2\u207a overload", "Mitochondrial dysfunction"]),
("Systemic Consequences",
["Hyperthermia \u2192 further neuronal injury", "Metabolic acidosis (lactic)",
"Hypoxia \u2192 secondary brain injury", "Rhabdomyolysis \u2192 renal failure"]),
("Blood-Brain Barrier",
["Albumin & K\u207a CNS penetration (hyperexcitatory)", "Neuroinflammation mediates BBB breach",
"Oedema contributes to ICP rise", "Perpetuates seizure activity"]),
]
mxs = [Inches(0.2), Inches(3.45), Inches(6.7), Inches(9.95)]
for i, (t, b) in enumerate(mech_cols):
add_rect(s, mxs[i], Inches(4.72), bw, Inches(2.55), LIGHT_PINK)
add_rect(s, mxs[i], Inches(4.72), bw, Inches(0.42), MID_PINK)
add_tb(s, mxs[i] + Inches(0.1), Inches(4.74), bw - Inches(0.2), Inches(0.38),
t, 12, bold=True, color=WHITE)
bullet_box(s, mxs[i] + Inches(0.1), Inches(5.16), bw - Inches(0.2), Inches(2.05),
b, bsz=10, bc=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 5 – INVESTIGATIONS
# ─────────────────────────────────────────────────────────────────────────────
def s5_investigations(prs):
s = prs.slides.add_slide(blank)
slide_header(s, "INVESTIGATIONS")
invs = [
("Immediate Bedside",
["Bedside glucose – STAT (exclude hypoglycaemia)",
"Pulse oximetry, ECG monitoring, ETCO\u2082",
"Temperature (treat hyperthermia actively)",
"GCS / neurological status"]),
("Blood Tests",
["FBC (infection, thrombocytopenia)",
"Electrolytes: Na\u207a, K\u207a, Ca\u00b2\u207a, Mg\u00b2\u207a",
"Blood glucose + HbA1c",
"Renal function, LFT",
"Lactate, arterial blood gas",
"AED drug levels (if on treatment)",
"Toxicology screen (blood + urine)",
"Pregnancy test (women of childbearing age)"]),
("Inflammatory / Immune Panel",
["ESR, CRP (infection / vasculitis)",
"Autoimmune encephalitis panel:",
" – Anti-NMDAR, LGI1, CASPR2, AMPA, GABA\u2082",
" – Paraneoplastic antibodies (Hu, Yo, VGCC)",
"Lumbar puncture (after seizures controlled):",
" – CSF: cells, protein, glucose, culture, PCR",
" – HSV PCR (urgent if encephalitis suspected)"]),
("Neuroimaging",
["CT head (non-contrast) – immediate:",
" – Haemorrhage, mass lesion, hydrocephalus",
"MRI brain (after stabilisation) – preferred:",
" – DWI: cytotoxic oedema in focal SE",
" – T2/FLAIR: hippocampal signal change",
" – Post-ictal changes: transient T2 hyperintensity",
" – Gadolinium: meningitis, encephalitis, tumour"]),
("EEG – Essential Investigation",
["Continuous EEG monitoring (cEEG) – gold standard",
"Indications: unexplained coma; post-paralysis;",
" any suspected NCSE",
"Portable headband EEG – rapid bedside use",
"Patterns: generalised rhythmic, focal discharges,",
" periodic lateralised epileptiform discharges (PLEDs)",
"Monitor treatment response in ICU",
"Cease AED titration guided by burst-suppression"]),
("Paediatric-Specific",
["Neonates: metabolic screen (ammonia, lactate, amino acids)",
"Pyridoxine trial (neonates – B6-dependent epilepsy)",
"TORCH screen (congenital infections)",
"Genetic / metabolic testing: inborn errors",
"Chromosomal microarray (epileptic encephalopathy)",
"CSF neurotransmitters (GLUT1 deficiency)",
"EEG – hypsarrhythmia (infantile spasms)"]),
]
box_w = Inches(5.9); box_h = Inches(2.65)
xs = [Inches(0.25), Inches(6.75)]
ys = [Inches(1.25), Inches(4.03)]
for idx, (t, b) in enumerate(invs[:4]):
col = idx % 2; row = idx // 2
x, y = xs[col], ys[row]
add_rect(s, x, y, box_w, box_h, LIGHT_PINK)
add_rect(s, x, y, box_w, Inches(0.45), DEEP_PINK)
add_tb(s, x + Inches(0.1), y + Inches(0.07), box_w - Inches(0.2), Inches(0.38),
t, 14, bold=True, color=WHITE)
bullet_box(s, x + Inches(0.1), y + Inches(0.5), box_w - Inches(0.2), Inches(2.1),
b, bsz=11, bc=DARK_GREY)
# Row 3 – EEG + Paediatric specific (full width / side by side)
ys2 = [Inches(6.8), Inches(6.8)]
# These won't fit in row 3 in standard layout; append as note strip
add_rect(s, Inches(0.25), Inches(6.73), Inches(12.9), Inches(0.06), MID_PINK)
add_tb(s, Inches(0.3), Inches(6.78), Inches(12.6), Inches(0.35),
"EEG: gold standard for NCSE diagnosis – continuous monitoring mandatory in all intubated/paralysed patients | "
"Paediatric extras: metabolic screen, pyridoxine trial, TORCH, genetic panel",
11, italic=True, color=DARK_BERRY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 6 – INVESTIGATIONS (EEG + Paeds)
# ─────────────────────────────────────────────────────────────────────────────
def s6_inv2(prs):
s = prs.slides.add_slide(blank)
slide_header(s, "INVESTIGATIONS (continued) – EEG & Paediatric Workup")
eeg_items = [
"Continuous EEG (cEEG) – gold standard for NCSE diagnosis and treatment monitoring",
"Indications: unexplained coma | post-paralysis | patients with risk of ongoing seizures | any NCSE suspicion",
"EEG patterns: generalised rhythmic delta activity, focal periodic discharges, PLEDs (periodic lateralised epileptiform discharges)",
"Portable 4/6-channel headband EEG – bedside, no technician needed; rules out NCSE rapidly",
"After neuromuscular blockade for intubation: EEG is the ONLY way to detect ongoing seizure activity",
"Burst-suppression pattern on EEG = target endpoint for refractory SE treatment with propofol/barbiturates",
"Ongoing EEG monitoring for 24–48 hours after seizure cessation recommended in high-risk patients",
]
paed_items = [
"Neonatal SE: blood/urine metabolic screen (ammonia, lactate, organic acids, amino acids)",
"Pyridoxine (B6) trial IV – neonates with unexplained refractory SE (B6-dependent epilepsy / ALDH7A1 mutations)",
"TORCH screen – congenital infections (toxoplasma, rubella, CMV, HSV)",
"Cerebrospinal fluid (CSF): cell count, protein, glucose, culture, HSV/EV PCR, ADEM markers",
"Autoimmune panel: Anti-NMDAR most common in children; FIRES (Febrile Infection-Related Epilepsy Syndrome)",
"Genetic testing: chromosomal microarray, gene panel (SCN1A for Dravet syndrome, KCNQ2, CDKL5)",
"EEG: hypsarrhythmia pattern suggests infantile spasms (West syndrome)",
"Neuroimaging: MRI preferred over CT to minimise radiation; sedation often required",
]
add_rect(s, Inches(0.25), Inches(1.25), Inches(12.8), Inches(0.45), MID_PINK)
add_tb(s, Inches(0.35), Inches(1.28), Inches(12.6), Inches(0.38),
"EEG Monitoring", 14, bold=True, color=WHITE)
bullet_box(s, Inches(0.35), Inches(1.74), Inches(12.6), Inches(2.3),
eeg_items, bsz=13, bc=DARK_GREY)
add_rect(s, Inches(0.25), Inches(4.14), Inches(12.8), Inches(0.45), MID_PINK)
add_tb(s, Inches(0.35), Inches(4.17), Inches(12.6), Inches(0.38),
"Paediatric-Specific Investigations", 14, bold=True, color=WHITE)
bullet_box(s, Inches(0.35), Inches(4.63), Inches(12.6), Inches(2.6),
paed_items, bsz=13, bc=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 7 – TREATMENT ADULTS (Step-wise)
# ─────────────────────────────────────────────────────────────────────────────
def s7_tx_adults(prs):
s = prs.slides.add_slide(blank)
slide_header(s, "TREATMENT – ADULTS", "Stepwise Protocol (0 → Refractory)")
steps = [
("PHASE 1 | 0–5 min",
"Immediate stabilisation",
["Airway, Breathing, Circulation – position patient, O\u2082 by face mask",
"IV/IO access + blood samples: glucose, electrolytes, AED levels, toxicology",
"IV normal saline; do NOT use glucose-containing fluids (incompatible with phenytoin)",
"Bedside glucose: give IV 50% dextrose if hypoglycaemic",
"IV thiamine 100 mg (BEFORE glucose if alcoholism / malnutrition suspected)",
"Monitor: cardiac, BP, SpO\u2082, temperature; treat hyperthermia actively"]),
("PHASE 2 | 5–20 min",
"1st-Line: Benzodiazepines",
["IV lorazepam 0.1 mg/kg (max 4 mg/dose) – preferred if IV access",
" Repeat once after 5 min if seizure persists",
"NO IV: IM midazolam 10 mg (>40 kg) or 5 mg (13–40 kg) – PARAMEDIC-safe",
" Rectal diazepam 0.2–0.5 mg/kg (max 20 mg) – if no other access",
" Buccal/intranasal midazolam 0.5 mg/kg (max 10 mg)",
"Benzodiazepines terminate SE in ~70% of cases"]),
("PHASE 3 | 20–40 min",
"2nd-Line: Established SE – ONE of the following:",
["Fosphenytoin 20 PE/kg IV @ 150 PE/min (preferred – fewer infusion reactions)",
"Levetiracetam 60 mg/kg IV (max 4,500 mg) @ 2–5 mg/kg/min",
"Valproate 40 mg/kg IV @ 3–6 mg/kg/min (avoid: liver disease, pregnancy)",
"Lacosamide 200–400 mg IV over 15 min (2nd choice if others unavailable)",
"Begin ONE agent within 20 min of diagnosis",
"No strong evidence favouring one agent over another (ECLIPSE, ConSEPT trials)"]),
("PHASE 4 | >60 min",
"Refractory SE – ICU + Continuous EEG (target: burst-suppression)",
["Propofol infusion 2–10 mg/kg/h IV (1st choice – short half-life)",
" Risk: propofol infusion syndrome at >4–5 mg/kg/h (>48 h)",
"Midazolam infusion 0.05–0.4 mg/kg/h IV (2nd choice)",
"Phenobarbital 15–20 mg/kg IV @ 50–100 mg/min (3rd line)",
"Pentobarbital infusion (coma induction) – severe refractory SE",
"Ketamine 0.5–4.5 mg/kg bolus OR infusion 1–5 mg/kg/h (NMDA antagonist; 3rd line)"]),
]
colors_h = [MID_PINK, DEEP_PINK, RGBColor(0xAD, 0x14, 0x57), RGBColor(0x7B, 0x00, 0x2E)]
bw = Inches(12.8); step_h = Inches(1.38)
for i, (phase, sub, items) in enumerate(steps):
y = Inches(1.22) + i * (step_h + Inches(0.04))
add_rect(s, Inches(0.25), y, bw, step_h, LIGHT_PINK)
add_rect(s, Inches(0.25), y, Inches(2.3), step_h, colors_h[i])
add_tb(s, Inches(0.32), y + Inches(0.12), Inches(2.18), Inches(0.55),
phase, 11, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
add_tb(s, Inches(0.32), y + Inches(0.68), Inches(2.18), Inches(0.55),
sub, 9, italic=True, color=WHITE, align=PP_ALIGN.CENTER)
# Bullet items
tb = s.shapes.add_textbox(Inches(2.65), y + Inches(0.08), Inches(10.3), step_h - Inches(0.12))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
first = True
for item in items:
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False; p.space_before = Pt(1)
r = p.add_run(); r.text = " \u2022 " + item
r.font.size = Pt(10.5); r.font.color.rgb = DARK_GREY; r.font.name = "Calibri"
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 8 – TREATMENT CHILDREN (Step-wise)
# ─────────────────────────────────────────────────────────────────────────────
def s8_tx_children(prs):
s = prs.slides.add_slide(blank)
slide_header(s, "TREATMENT – CHILDREN", "Stepwise Protocol | Harriet Lane / AES Guidelines")
steps = [
("PHASE 1\n0–5 min",
"ABCs + Monitoring",
["Airway: positioning, suction, NPA for airway obstruction (avoid OPA – may trigger vomiting)",
"O\u2082 by face mask; bag-valve-mask if inadequate ventilation",
"IV/IO access: blood glucose STAT, electrolytes, calcium, magnesium",
"Bedside glucose: give IV dextrose if hypoglycaemic (2 mL/kg D10W neonates; D25W older children)",
"Treat fever with antipyretics (paracetamol PR/IV) + cooling blanket"]),
("PHASE 2\n5–20 min",
"1st-Line: Benzodiazepines",
["IV lorazepam: 0.1 mg/kg (max 4 mg/dose); repeat once after 5 min",
"IV diazepam: Infant/child <5 yr: 0.2–0.5 mg/dose Q2–5 min (max 5 mg)",
" Child \u22655 yr: 1 mg/dose Q2–5 min (max 10 mg)",
"NO IV: IM/intranasal/buccal midazolam 0.2–0.3 mg/kg (max 10 mg)",
" Nasal midazolam: weight-based dosing (see Harriet Lane table)",
" Rectal diazepam: 0.5 mg/kg/dose (> 2 yr: 0.3 mg/kg)"]),
("PHASE 3\n20–40 min",
"2nd-Line: ONE agent",
["Fosphenytoin 20 PE/kg IV at 2–3 mg PE/kg/min (max 150 PE/min)",
"Levetiracetam 60 mg/kg IV (max 3,000 mg) – preferred in many centres",
"Valproate 40 mg/kg IV (avoid <2 yr / suspected metabolic disease / liver disease)",
"Phenobarbital 20 mg/kg IV @ 1 mg/kg/min – particularly neonates & infants",
" Additional 5–10 mg/kg if needed after 20 min",
"Pyridoxine 100 mg IV (neonates) if B6-dependent epilepsy suspected"]),
("PHASE 4\n>60 min",
"Refractory SE – PICU + continuous EEG",
["Midazolam infusion 0.1–0.4 mg/kg/h (titrate to burst-suppression on EEG)",
"Propofol infusion: CAUTION – risk of propofol infusion syndrome in children",
" Use only short-term; alternative: barbiturate coma",
"Pentobarbital infusion – coma induction (PICU)",
"Ketamine 1–2 mg/kg IV bolus then 0.5–3 mg/kg/h (NMDA antagonist; emerging evidence)",
"ACTH or steroids: consider in FIRES or autoimmune SE",
"IVIG / plasmapheresis: autoimmune encephalitis-associated SE"]),
]
colors_h = [MID_PINK, DEEP_PINK, RGBColor(0xAD, 0x14, 0x57), RGBColor(0x7B, 0x00, 0x2E)]
bw = Inches(12.8); step_h = Inches(1.38)
for i, (phase, sub, items) in enumerate(steps):
y = Inches(1.22) + i * (step_h + Inches(0.04))
add_rect(s, Inches(0.25), y, bw, step_h, LIGHT_PINK)
add_rect(s, Inches(0.25), y, Inches(2.3), step_h, colors_h[i])
add_tb(s, Inches(0.32), y + Inches(0.12), Inches(2.18), Inches(0.55),
phase, 12, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
add_tb(s, Inches(0.32), y + Inches(0.68), Inches(2.18), Inches(0.55),
sub, 9, italic=True, color=WHITE, align=PP_ALIGN.CENTER)
tb = s.shapes.add_textbox(Inches(2.65), y + Inches(0.08), Inches(10.3), step_h - Inches(0.12))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
first = True
for item in items:
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False; p.space_before = Pt(1)
r = p.add_run(); r.text = " \u2022 " + item
r.font.size = Pt(10.5); r.font.color.rgb = DARK_GREY; r.font.name = "Calibri"
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 9 – DRUG DOSES COMPARISON TABLE
# ─────────────────────────────────────────────────────────────────────────────
def s9_doses(prs):
s = prs.slides.add_slide(blank)
slide_header(s, "AED DOSING REFERENCE TABLE – Adults vs Children")
headers = ["Drug", "Phase", "Adult Dose", "Paediatric Dose", "Route", "Key Notes"]
rows = [
["Lorazepam", "1st-line", "0.1 mg/kg IV (max 4 mg); repeat ×1",
"0.1 mg/kg IV (max 4 mg); repeat ×1", "IV", "Preferred 1st-line if IV access; onset 2–3 min"],
["Midazolam", "1st-line\n(no IV)", "IM 10 mg (>40 kg) / 5 mg (13–40 kg)",
"IN/buccal/IM 0.2–0.3 mg/kg (max 10 mg)", "IM/IN/buccal", "Preferred when no IV; non-inferior to IV lorazepam"],
["Diazepam", "1st-line\n(alt)", "IV 5–10 mg Q10–15 min (max 30 mg)",
"IV 0.2–0.5 mg/dose (<5 yr, max 5 mg)\n\u22655 yr: 1 mg/dose (max 10 mg)", "IV/PR",
"Rectal for prehospital; shorter action than lorazepam"],
["Fosphenytoin", "2nd-line", "20 PE/kg IV @ 150 PE/min",
"20 PE/kg IV @ 2–3 mg PE/kg/min", "IV/IM", "Preferred over phenytoin – can give IM; cardiac monitor"],
["Levetiracetam", "2nd-line", "60 mg/kg IV (max 4,500 mg) @ 2–5 mg/kg/min",
"60 mg/kg IV (max 3,000 mg)", "IV", "Minimal drug interactions; safe in liver disease"],
["Valproate", "2nd-line", "40 mg/kg IV @ 3–6 mg/kg/min",
"40 mg/kg IV (avoid <2 yr)", "IV", "Avoid: liver disease, thrombocytopenia, pregnancy"],
["Phenobarbital", "2nd/3rd-line", "15–20 mg/kg IV @ 50–100 mg/min",
"20 mg/kg IV @ 1 mg/kg/min (neonates: 1st-line)", "IV", "1st-line in neonates; resp. depression risk"],
["Propofol", "Refractory", "2–10 mg/kg/h infusion",
"Use with caution: short-term only", "IV infusion", "Propofol infusion syndrome risk >48 h"],
["Midazolam infusion", "Refractory", "0.05–0.4 mg/kg/h",
"0.1–0.4 mg/kg/h", "IV infusion", "2nd-line refractory; accumulates in renal failure"],
["Ketamine", "Refractory", "0.5–4.5 mg/kg bolus; 1–5 mg/kg/h infusion",
"1–2 mg/kg bolus; 0.5–3 mg/kg/h", "IV", "NMDA antagonist; maintains haemodynamics"],
]
col_ws = [Inches(1.7), Inches(1.0), Inches(2.35), Inches(2.35), Inches(1.0), Inches(4.6)]
y = Inches(1.25); row_h = Inches(0.6)
x_start = Inches(0.15)
# Header row
x = x_start
for ci, h in enumerate(headers):
add_rect(s, x, y, col_ws[ci], Inches(0.5), DEEP_PINK)
add_tb(s, x + Inches(0.04), y + Inches(0.07), col_ws[ci] - Inches(0.08), Inches(0.38),
h, 12, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
x += col_ws[ci]
for ri, row in enumerate(rows):
y_r = y + Inches(0.5) + ri * row_h
bg = LIGHT_PINK if ri % 2 == 0 else PALE_PINK
x = x_start
for ci, cell in enumerate(row):
add_rect(s, x, y_r, col_ws[ci], row_h, MID_PINK if ci == 0 else bg)
fc = WHITE if ci == 0 else DARK_GREY
add_tb(s, x + Inches(0.04), y_r + Inches(0.06), col_ws[ci] - Inches(0.08), row_h - Inches(0.1),
cell, 9.5, bold=(ci == 0), color=fc, wrap=True)
x += col_ws[ci]
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 10 – COMPLICATIONS & OUTCOMES
# ─────────────────────────────────────────────────────────────────────────────
def s10_complications(prs):
s = prs.slides.add_slide(blank)
slide_header(s, "COMPLICATIONS & OUTCOMES")
neuro = [
"Epileptic encephalopathy (prolonged SE >30 min)",
"Hippocampal sclerosis \u2192 temporal lobe epilepsy (mesial TLE)",
"MRI: T2/DWI signal change (usually reversible; may be permanent)",
"Memory impairment (anterograde amnesia)",
"Permanent neurological deficit (motor, cognitive)",
"Cerebral oedema, raised ICP",
]
systemic = [
"Hyperthermia (neurogenic) \u2192 exacerbates neuronal injury",
"Metabolic acidosis (lactic)",
"Hypoxia / respiratory failure \u2192 intubation needed",
"Aspiration pneumonia",
"Rhabdomyolysis \u2192 acute renal failure / myoglobinuria",
"Neurogenic pulmonary oedema",
"Cardiac dysrhythmias / hypertension",
]
prognosis = [
"Overall mortality: historically 20–30% (lower in modern era)",
"Worse prognosis: age >60 yrs; delayed treatment; no prior seizure Hx",
"NCSE: higher mortality if untreated / delayed diagnosis",
"Refractory SE: highest mortality (up to 30–40%)",
"Children: generally better prognosis than adults",
"Febrile SE in children: usually benign; low recurrence risk",
"Outcome heavily depends on UNDERLYING aetiology",
]
for label, items, x in [("Neurological Complications", neuro, Inches(0.25)),
("Systemic Complications", systemic, Inches(4.65)),
("Prognosis & Outcomes", prognosis, Inches(9.05))]:
bw = Inches(4.15); bh = Inches(5.6)
add_rect(s, x, Inches(1.25), bw, bh, LIGHT_PINK)
add_rect(s, x, Inches(1.25), bw, Inches(0.48), DEEP_PINK)
add_tb(s, x + Inches(0.1), Inches(1.28), bw - Inches(0.2), Inches(0.42),
label, 14, bold=True, color=WHITE)
bullet_box(s, x + Inches(0.1), Inches(1.77), bw - Inches(0.2), Inches(4.98),
items, bsz=12, bc=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 11 – KEY TAKEAWAYS
# ─────────────────────────────────────────────────────────────────────────────
def s11_summary(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, DEEP_PINK)
add_rect(s, 0, 0, Inches(0.55), H, MID_PINK)
add_rect(s, Inches(0.55), Inches(1.5), W - Inches(0.55), Inches(0.06), GOLD)
add_tb(s, Inches(0.85), Inches(0.3), Inches(12), Inches(1.0),
"KEY CLINICAL TAKEAWAYS", 32, bold=True, color=WHITE)
points = [
"SE = seizure \u22655 min OR \u22652 seizures without recovery – a NEUROLOGICAL EMERGENCY requiring immediate treatment.",
"Treat at 5 minutes, not 30 – every minute of delay worsens outcome and increases drug resistance.",
"1st-line: Benzodiazepines (IV lorazepam or IM midazolam) – terminate SE in ~70% of cases.",
"2nd-line (20 min): Fosphenytoin / Levetiracetam / Valproate – no single agent is clearly superior.",
"Refractory SE (>60 min): Propofol or Midazolam infusion in ICU; target burst-suppression on EEG.",
"EEG is mandatory: diagnose NCSE, monitor treatment, guide AED titration in paralysed patients.",
"Investigations: glucose STAT, electrolytes, AED levels, MRI brain, LP (after seizures controlled).",
"Children: Phenobarbital is preferred in neonates; always consider pyridoxine trial; FIRES requires immunotherapy.",
"Always treat the underlying cause – SE is a symptom, not a diagnosis.",
]
tb = s.shapes.add_textbox(Inches(0.85), Inches(1.65), Inches(12.2), Inches(5.6))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
first = True
for i, pt in enumerate(points):
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False; p.space_before = Pt(5)
r = p.add_run()
r.text = f" {i+1}. " + pt
r.font.size = Pt(13.5)
r.font.color.rgb = WHITE if i % 2 == 0 else SOFT_PINK
r.font.name = "Calibri"
# ─────────────────────────────────────────────────────────────────────────────
# BUILD
# ─────────────────────────────────────────────────────────────────────────────
s1_title(prs)
s2_definition(prs)
s3_etiology(prs)
s4_patho(prs)
s5_investigations(prs)
s6_inv2(prs)
s7_tx_adults(prs)
s8_tx_children(prs)
s9_doses(prs)
s10_complications(prs)
s11_summary(prs)
out = "/tmp/workspace/diplopia-ppt/Status_Epilepticus.pptx"
prs.save(out)
print(f"Saved: {out} ({len(prs.slides)} slides)")
cd /tmp/workspace/diplopia-ppt && python make_se_ppt.py
Status Epilepticus
Presentation · PPTX
| Slide | Content |
|---|---|
| 1 | Title slide |
| 2 | Definition & Classification – ILAE time domains (t1/t2), CSE vs NCSE vs Refractory SE |
| 3 | Etiology – Adults vs Children (side-by-side columns: medication, structural, infectious, metabolic, toxic, vascular / febrile, genetic, FIRES) |
| 4 | Pathophysiology – 4-phase timeline + cellular mechanisms (GABA failure, NMDA excess, BBB breakdown, systemic consequences) |
| 5 | Investigations – Bedside, Blood Tests, Inflammatory/Immune Panel, Neuroimaging |
| 6 | Investigations (continued) – EEG monitoring (cEEG, burst-suppression, PLEDs) + Paediatric-specific workup |
| 7 | Treatment – Adults (4-phase stepwise: ABCs → Benzodiazepines → 2nd-line AEDs → Refractory ICU) |
| 8 | Treatment – Children (4-phase protocol with paediatric-specific doses, phenobarbital in neonates, FIRES immunotherapy) |
| 9 | AED Dosing Reference Table – Adult vs Paediatric doses for all agents side by side |
| 10 | Complications & Outcomes – Neurological, Systemic, Prognosis |
| 11 | Key Takeaways (9 clinical pearls on pink background) |
Prepare a ppt topic is difference between syringomyleia and bilateral brachial motor Neuron disease. Slide theme maple leaf and light orange colour
~/diplopia-ppt/make_syrinx_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.oxml.ns import qn
from lxml import etree
import math
# ── Maple Leaf / Autumn Orange Palette ───────────────────────────────────────
MAPLE_RED = RGBColor(0xC0, 0x39, 0x2B) # deep maple red
BURNT_ORANGE = RGBColor(0xD3, 0x54, 0x00) # header bars
WARM_ORANGE = RGBColor(0xF3, 0x7F, 0x20) # accent
LIGHT_ORANGE = RGBColor(0xFF, 0xE5, 0xCC) # slide background
PALE_AMBER = RGBColor(0xFF, 0xF3, 0xE0) # card bg
AMBER = RGBColor(0xFF, 0xB3, 0x00) # highlight
FOREST_GREEN = RGBColor(0x27, 0x5C, 0x27) # contrast (leaf vein)
DARK_BROWN = RGBColor(0x3E, 0x1C, 0x00) # dark text
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
CREAM = RGBColor(0xFF, 0xF8, 0xF0)
DARK_GREY = RGBColor(0x22, 0x22, 0x22)
SYR_COLOR = RGBColor(0xC0, 0x39, 0x2B) # Syringomyelia column
MND_COLOR = RGBColor(0x1A, 0x5C, 0x8C) # MND column
W = Inches(13.333)
H = Inches(7.5)
prs = Presentation()
prs.slide_width = W
prs.slide_height = H
blank = prs.slide_layouts[6]
# ─────────────────────────────────────────────────────────────────────────────
# SVG-like maple leaf polygon drawn using python-pptx freeform
# ─────────────────────────────────────────────────────────────────────────────
def add_maple_leaf(slide, cx, cy, size, color=MAPLE_RED, alpha=None):
"""Draw a simple 11-point maple leaf polygon."""
from pptx.util import Emu
# Maple leaf points (normalised –1..1), scaled & translated
pts_norm = [
(0, 1), # top-center
(-0.2, 0.4),
(-0.8, 0.6),
(-0.6, 0.15),
(-1, 0.1),
(-0.5, -0.2),
(-0.6, -0.6),
(0, -0.3),
(0.6, -0.6),
(0.5, -0.2),
(1, 0.1),
(0.6, 0.15),
(0.8, 0.6),
(0.2, 0.4),
]
# Convert to EMU
from pptx.util import Inches as IN
scale = size # already in Inches float
emu_pts = [(int((x * scale + cx) * 914400),
int((-y * scale + cy) * 914400)) for x, y in pts_norm]
# Add freeform shape
freeform = slide.shapes._spTree
sp_xml = f'''<p:sp xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<p:nvSpPr>
<p:cNvPr id="9999" name="MapleLeaf"/>
<p:cNvSpPr><a:spLocks noChangeArrowheads="1"/></p:cNvSpPr>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="{emu_pts[0][0]}" y="{emu_pts[0][1]}"/>
<a:ext cx="{int(size*914400*2)}" cy="{int(size*914400*2)}"/>
</a:xfrm>
<a:custGeom>
<a:avLst/>
<a:gdLst/>
<a:ahLst/>
<a:cxnLst/>
<a:rect l="0" t="0" r="0" b="0"/>
<a:pathLst>
<a:path w="{int(size*914400*2)}" h="{int(size*914400*2)}">
<a:moveTo><a:pt x="{emu_pts[0][0]}" y="{emu_pts[0][1]}"/></a:moveTo>
{''.join(f'<a:lnTo><a:pt x="{px}" y="{py}"/></a:lnTo>' for px,py in emu_pts[1:])}
<a:close/>
</a:path>
</a:pathLst>
</a:custGeom>
<a:solidFill><a:srgbClr val="{color.rgb}"/></a:solidFill>
<a:ln w="0"><a:noFill/></a:ln>
</p:spPr>
<p:txBody><a:bodyPr/><a:lstStyle/><a:p/></p:txBody>
</p:sp>'''
# We won't use complex SVG – just use diamond shapes as maple leaf proxies
pass # Will use styled rectangles with round corners for cleanliness
def add_rect(slide, x, y, w, h, fill_rgb, radius=0):
shape = slide.shapes.add_shape(1, x, y, w, h)
shape.line.fill.background()
fill = shape.fill; fill.solid(); fill.fore_color.rgb = fill_rgb
return shape
def add_rounded_rect(slide, x, y, w, h, fill_rgb, corner_pt=12):
"""Rounded rectangle via shape type 5 (rounded rectangle)."""
from pptx.oxml.ns import qn as qn2
shape = slide.shapes.add_shape(5, x, y, w, h) # 5 = rounded rectangle
shape.line.fill.background()
fill = shape.fill; fill.solid(); fill.fore_color.rgb = fill_rgb
# Set corner rounding
adj = shape.adjustments
try:
adj[0] = corner_pt / 200 # fraction of half the smaller dimension
except Exception:
pass
return shape
def add_tb(slide, x, y, w, h, text, size, bold=False, color=WHITE,
align=PP_ALIGN.LEFT, italic=False, wrap=True):
tb = slide.shapes.add_textbox(x, y, w, h)
tf = tb.text_frame; tf.word_wrap = wrap
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run()
r.text = text; r.font.size = Pt(size); r.font.bold = bold
r.font.italic = italic; r.font.color.rgb = color; r.font.name = "Calibri"
return tb
def leaf_icon(slide, x, y, size_in, color=MAPLE_RED):
"""Draw a simple maple-leaf-like star polygon with 5 lobes."""
cx = x + size_in / 2
cy = y + size_in / 2
r_outer = size_in / 2
r_inner = r_outer * 0.45
n = 5
pts = []
for i in range(n * 2):
angle = math.radians(-90 + i * 180 / n)
r = r_outer if i % 2 == 0 else r_inner
pts.append((cx + r * math.cos(angle), cy + r * math.sin(angle)))
# Approximation: draw as diamond
add_rect(slide, Inches(x - size_in/4), Inches(cy - size_in/2), Inches(size_in/2), Inches(size_in), color)
def bullet_box(slide, x, y, w, h, items, title=None,
tsz=14, bsz=12, tc=BURNT_ORANGE, bc=DARK_GREY, bg=None, sp=2):
if bg: add_rounded_rect(slide, x, y, w, h, bg)
tb = slide.shapes.add_textbox(x + Inches(0.1), y + Inches(0.08),
w - Inches(0.2), h - Inches(0.16))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
first = True
if title:
p = tf.paragraphs[0]; r = p.add_run()
r.text = title; r.font.size = Pt(tsz); r.font.bold = True
r.font.color.rgb = tc; r.font.name = "Calibri"; first = False
for item in items:
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False; p.space_before = Pt(sp)
r = p.add_run()
r.text = " \u2022 " + item
r.font.size = Pt(bsz); r.font.color.rgb = bc; r.font.name = "Calibri"
def slide_frame(s, title, subtitle=None):
"""Standard slide background with orange header."""
add_rect(s, 0, 0, W, H, LIGHT_ORANGE)
# Decorative maple-leaf watermarks (simple orange diamonds)
for rx, ry, rs, ra in [(11.5, 5.5, 1.2, AMBER), (0.3, 5.8, 0.9, AMBER),
(12.5, 0.5, 0.7, WARM_ORANGE)]:
add_rect(s, Inches(rx), Inches(ry), Inches(rs*0.6), Inches(rs*0.85), PALE_AMBER)
add_rect(s, 0, 0, W, Inches(1.18), BURNT_ORANGE)
add_rect(s, 0, Inches(1.18), Inches(0.1), H - Inches(1.18), WARM_ORANGE)
add_rect(s, 0, Inches(1.18), W, Inches(0.05), AMBER)
add_tb(s, Inches(0.28), Inches(0.18), Inches(12.5), Inches(0.75),
title, 26, bold=True, color=WHITE)
if subtitle:
add_tb(s, Inches(0.28), Inches(0.8), Inches(12.5), Inches(0.34),
subtitle, 14, italic=True, color=PALE_AMBER)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 1 – TITLE
# ─────────────────────────────────────────────────────────────────────────────
def s1_title(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, LIGHT_ORANGE)
add_rect(s, 0, 0, Inches(0.6), H, BURNT_ORANGE)
add_rect(s, Inches(0.6), Inches(3.55), W - Inches(0.6), Inches(0.07), AMBER)
# Maple leaf decorative shapes (stylised diamonds)
for cx, cy, sz, col in [(11.5, 1.0, 0.9, MAPLE_RED), (11.9, 5.5, 1.1, WARM_ORANGE),
(0.9, 6.5, 0.7, AMBER), (10.5, 6.5, 0.6, MAPLE_RED)]:
add_rounded_rect(s, Inches(cx), Inches(cy), Inches(sz), Inches(sz*1.2), col)
add_tb(s, Inches(0.95), Inches(0.9), Inches(11.5), Inches(0.7),
"SYRINGOMYELIA", 36, bold=True, color=SYR_COLOR)
add_tb(s, Inches(0.95), Inches(1.65), Inches(11.5), Inches(0.55),
"vs.", 28, bold=True, color=BURNT_ORANGE, align=PP_ALIGN.LEFT)
add_tb(s, Inches(0.95), Inches(2.25), Inches(11.5), Inches(0.7),
"BILATERAL BRACHIAL MOTOR NEURON DISEASE (ALS / MND)", 30, bold=True, color=MND_COLOR)
add_tb(s, Inches(0.95), Inches(3.1), Inches(11.5), Inches(0.5),
"A Comparative Clinical Analysis", 20, italic=True, color=DARK_BROWN)
add_tb(s, Inches(0.95), Inches(3.75), Inches(11.5), Inches(1.2),
"Comparison of Definition \u2022 Etiology \u2022 Pathology \u2022 Clinical Features\n"
"Investigations \u2022 Treatment \u2022 Key Differentiating Points",
15, color=DARK_BROWN)
add_tb(s, Inches(0.95), Inches(6.8), Inches(11.5), Inches(0.4),
"Sources: Rosen's Emergency Medicine \u2022 Bradley & Daroff's Neurology \u2022 "
"Goldman-Cecil Medicine \u2022 Kandel's Principles of Neural Science",
11, italic=True, color=BURNT_ORANGE)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 2 – DEFINITION
# ─────────────────────────────────────────────────────────────────────────────
def s2_definition(prs):
s = prs.slides.add_slide(blank)
slide_frame(s, "DEFINITION", "What are these conditions?")
# Syringomyelia
add_rounded_rect(s, Inches(0.2), Inches(1.3), Inches(6.15), Inches(5.9), PALE_AMBER)
add_rect(s, Inches(0.2), Inches(1.3), Inches(6.15), Inches(0.52), SYR_COLOR)
add_tb(s, Inches(0.32), Inches(1.33), Inches(6.0), Inches(0.45),
"SYRINGOMYELIA", 16, bold=True, color=WHITE)
paras_syr = [
("Definition:", "A fluid-filled tubular cystic cavitation (syrinx) within the central spinal cord parenchyma, extending over several segments."),
("Alternate term:", "Hydromyelia = dilatation of the central canal (vs. true intramedullary cavity in syringomyelia)."),
("Location:", "Most commonly cervical cord; may extend to medullary region (syringobulbia) or lower segments."),
("Prevalence:", "8 per 100,000 population; female = male; onset typically late adolescence / early adulthood."),
("Nature:", "Chronic, slowly progressive with intermittent stable periods; typically non-fatal but causes significant morbidity."),
]
y = Inches(1.9)
for label, detail in paras_syr:
tb = s.shapes.add_textbox(Inches(0.35), y, Inches(5.9), Inches(0.55))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
r1 = p.add_run(); r1.text = label + " "
r1.font.bold = True; r1.font.size = Pt(12.5); r1.font.color.rgb = SYR_COLOR; r1.font.name = "Calibri"
r2 = p.add_run(); r2.text = detail
r2.font.size = Pt(12.5); r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
y += Inches(0.68)
# MND / ALS
add_rounded_rect(s, Inches(6.7), Inches(1.3), Inches(6.4), Inches(5.9), PALE_AMBER)
add_rect(s, Inches(6.7), Inches(1.3), Inches(6.4), Inches(0.52), MND_COLOR)
add_tb(s, Inches(6.82), Inches(1.33), Inches(6.2), Inches(0.45),
"BILATERAL BRACHIAL MOTOR NEURON DISEASE (ALS/MND)", 14, bold=True, color=WHITE)
paras_mnd = [
("Definition:", "Progressive degeneration of BOTH upper (UMN) and lower (LMN) motor neurons affecting the anterior horn cells and corticospinal tracts."),
("Prototype:", "ALS (Amyotrophic Lateral Sclerosis / Lou Gehrig disease) – 'amyotrophy' = neurogenic muscle atrophy; 'lateral sclerosis' = corticospinal tract scarring."),
("Bilateral brachial:", "The presentation specifically involving both arms – an important clinical pattern mimicking syringomyelia due to hand wasting and weakness."),
("Prevalence:", "2–3 per 100,000/yr; onset typically 40s–50s (men > women 1.5:1); sporadic 90%, familial 10%."),
("Nature:", "Relentlessly progressive, fatal; median survival 2–5 years from onset (respiratory failure)."),
]
y = Inches(1.9)
for label, detail in paras_mnd:
tb = s.shapes.add_textbox(Inches(6.85), y, Inches(6.1), Inches(0.55))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
r1 = p.add_run(); r1.text = label + " "
r1.font.bold = True; r1.font.size = Pt(12.5); r1.font.color.rgb = MND_COLOR; r1.font.name = "Calibri"
r2 = p.add_run(); r2.text = detail
r2.font.size = Pt(12.5); r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
y += Inches(0.68)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 3 – ETIOLOGY
# ─────────────────────────────────────────────────────────────────────────────
def s3_etiology(prs):
s = prs.slides.add_slide(blank)
slide_frame(s, "ETIOLOGY")
# Headers
add_rect(s, Inches(0.2), Inches(1.3), Inches(6.15), Inches(0.48), SYR_COLOR)
add_tb(s, Inches(0.32), Inches(1.34), Inches(6.0), Inches(0.42), "SYRINGOMYELIA", 16, bold=True, color=WHITE)
add_rect(s, Inches(6.7), Inches(1.3), Inches(6.4), Inches(0.48), MND_COLOR)
add_tb(s, Inches(6.82), Inches(1.34), Inches(6.2), Inches(0.42), "BILATERAL BRACHIAL MND / ALS", 16, bold=True, color=WHITE)
syr_causes = [
("Chiari Malformation (Type I)", "Most common – 90% of cases. Tonsillar herniation blocks CSF flow at foramen magnum, generating pressure wave driving fluid into cord."),
("Post-traumatic", "Spinal cord trauma (months–years post-injury). Tethered cord, adhesive arachnoiditis disrupt CSF dynamics."),
("Spinal Cord Tumour", "Intramedullary tumours (ependymoma, astrocytoma) cause a reactive syrinx."),
("Post-infectious / Post-inflammatory", "Meningitis, transverse myelitis, multiple sclerosis – arachnoiditis impairs CSF resorption."),
("Idiopathic", "No underlying cause identified (~7%)."),
("Pathomechanism", "Abnormal CSF pulsations \u2192 pressure differential \u2192 fluid forced into perivascular spaces \u2192 syrinx formation."),
]
mnd_causes = [
("Sporadic ALS (90%)", "Unknown aetiology; likely multifactorial – oxidative stress, glutamate excitotoxicity, mitochondrial dysfunction, neuroinflammation."),
("Familial ALS (10%)", "SOD1 (Cu/Zn superoxide dismutase) mutations – 20% of familial; C9orf72 hexanucleotide expansion – >25% of familial in N. America."),
("Other genetic mutations", "TARDBP (TDP-43), FUS, OPTN, VCP, UBQLN2 gene mutations."),
("Risk factors", "Older age, male sex, military service, heavy metal exposure, vigorous physical activity (controversial)."),
("Pathomechanism", "Glutamate excitotoxicity \u2192 intracellular Ca\u00b2\u207a overload \u2192 UMN + LMN degeneration; corticospinal tracts scarred ('lateral sclerosis')."),
("No known cause", "Most sporadic cases remain idiopathic; viral, environmental, and prion-like protein spread theories proposed."),
]
bw = Inches(6.15); bhdr = Inches(0.4)
row_h = Inches(0.93)
for i, (label, detail) in enumerate(syr_causes):
y = Inches(1.82) + i * row_h
bg = PALE_AMBER if i % 2 == 0 else LIGHT_ORANGE
add_rect(s, Inches(0.2), y, bw, row_h, bg)
add_rect(s, Inches(0.2), y, Inches(0.06), row_h, SYR_COLOR)
tb = s.shapes.add_textbox(Inches(0.32), y + Inches(0.06), bw - Inches(0.18), row_h - Inches(0.1))
tf = tb.text_frame; tf.word_wrap = True; tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
r1 = p.add_run(); r1.text = label + ": "; r1.font.bold = True; r1.font.size = Pt(12); r1.font.color.rgb = SYR_COLOR; r1.font.name = "Calibri"
r2 = p.add_run(); r2.text = detail; r2.font.size = Pt(11.5); r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
bw2 = Inches(6.4)
for i, (label, detail) in enumerate(mnd_causes):
y = Inches(1.82) + i * row_h
bg = PALE_AMBER if i % 2 == 0 else LIGHT_ORANGE
add_rect(s, Inches(6.7), y, bw2, row_h, bg)
add_rect(s, Inches(6.7), y, Inches(0.06), row_h, MND_COLOR)
tb = s.shapes.add_textbox(Inches(6.82), y + Inches(0.06), bw2 - Inches(0.18), row_h - Inches(0.1))
tf = tb.text_frame; tf.word_wrap = True; tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
r1 = p.add_run(); r1.text = label + ": "; r1.font.bold = True; r1.font.size = Pt(12); r1.font.color.rgb = MND_COLOR; r1.font.name = "Calibri"
r2 = p.add_run(); r2.text = detail; r2.font.size = Pt(11.5); r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 4 – PATHOLOGY
# ─────────────────────────────────────────────────────────────────────────────
def s4_pathology(prs):
s = prs.slides.add_slide(blank)
slide_frame(s, "PATHOLOGY")
add_rect(s, Inches(0.2), Inches(1.3), Inches(6.15), Inches(0.48), SYR_COLOR)
add_tb(s, Inches(0.32), Inches(1.34), Inches(6.0), Inches(0.42), "SYRINGOMYELIA", 16, bold=True, color=WHITE)
add_rect(s, Inches(6.7), Inches(1.3), Inches(6.4), Inches(0.48), MND_COLOR)
add_tb(s, Inches(6.82), Inches(1.34), Inches(6.2), Inches(0.42), "BILATERAL BRACHIAL MND / ALS", 16, bold=True, color=WHITE)
syr_patho = [
("Gross Pathology", ["Fluid-filled cavity (syrinx) in central cord", "Usually cervical (C4–T1); may be eccentric",
"Chiari I: cerebellar tonsil descent >5 mm below foramen magnum"]),
("Micro-anatomy", ["CSF-like fluid within syrinx cavity", "Surrounding glial reaction (gliosis)",
"Anterior commissure fibres disrupted first (crossing spinothalamic fibres)"]),
("Tract Involvement", ["Spinothalamic (lateral): PAIN & TEMP fibres disrupted \u2192 dissociated sensory loss",
"Posterior columns (vibration, proprioception): SPARED until late",
"Corticospinal tract: involved with enlargement \u2192 UMN signs in legs",
"Anterior horn cells: involved \u2192 LMN signs in arms (hand wasting)"]),
("Spread Pattern", ["Expands centrifugally: central \u2192 peripheral", "Cape-like distribution = C4–T2 dermatomes",
"Progressive with Valsalva / coughing (increases intracranial pressure)"]),
]
mnd_patho = [
("Gross Pathology", ["Hardening/scarring of lateral columns (lateral sclerosis)", "Atrophy of anterior horn cells (LMN)",
"Frontal / motor cortex Betz cell loss (UMN)"]),
("Micro-anatomy", ["TDP-43 / FUS protein aggregates in motor neurons", "Astrocytic gliosis in lateral columns",
"Loss of large myelinated corticospinal axons", "Microglial activation (neuroinflammation)"]),
("Tract Involvement", ["Corticospinal tract (UMN): spasticity, hyperreflexia, Babinski",
"Anterior horn cells (LMN): fasciculations, wasting, flaccid weakness",
"Bulbar motor neurons (bulbar-onset ALS)", "SENSORY TRACTS AND POSTERIOR COLUMNS: SPARED"]),
("Spread Pattern", ["Focal onset (hand, arm, leg, or bulbar)", "Spreads contiguously along neural networks",
"Progressive over months to years; bilateral brachial = both arms involved",
"Eventually involves respiratory muscles (C3–C5, phrenic nerve)"]),
]
bw = Inches(6.05); row_h = Inches(1.42)
ys = [Inches(1.82), Inches(3.28), Inches(4.74), Inches(6.2)]
box_colors = [PALE_AMBER, LIGHT_ORANGE, PALE_AMBER, LIGHT_ORANGE]
for i, (section, items) in enumerate(syr_patho):
y = ys[i]
add_rect(s, Inches(0.2), y, bw, row_h, box_colors[i])
add_rect(s, Inches(0.2), y, Inches(0.06), row_h, SYR_COLOR)
add_tb(s, Inches(0.32), y + Inches(0.05), bw - Inches(0.18), Inches(0.35),
section, 12, bold=True, color=SYR_COLOR)
bullet_box(s, Inches(0.32), y + Inches(0.4), bw - Inches(0.18), row_h - Inches(0.48),
items, bsz=11, bc=DARK_GREY)
bw2 = Inches(6.3)
for i, (section, items) in enumerate(mnd_patho):
y = ys[i]
add_rect(s, Inches(6.7), y, bw2, row_h, box_colors[i])
add_rect(s, Inches(6.7), y, Inches(0.06), row_h, MND_COLOR)
add_tb(s, Inches(6.82), y + Inches(0.05), bw2 - Inches(0.18), Inches(0.35),
section, 12, bold=True, color=MND_COLOR)
bullet_box(s, Inches(6.82), y + Inches(0.4), bw2 - Inches(0.18), row_h - Inches(0.48),
items, bsz=11, bc=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 5 – CLINICAL FEATURES
# ─────────────────────────────────────────────────────────────────────────────
def s5_clinical(prs):
s = prs.slides.add_slide(blank)
slide_frame(s, "CLINICAL FEATURES")
headers = ["Feature", "SYRINGOMYELIA", "BILATERAL BRACHIAL MND / ALS"]
rows = [
["Age of onset", "Late adolescence / early adulthood (20s–40s)", "Middle-aged adults (40s–50s)"],
["Onset pattern", "Gradual, insidious; exacerbated by Valsalva / cough", "Focal asymmetric onset spreading to both arms"],
["Pain & Temp sensation (arms)", "LOST (dissociated loss – cape pattern, C4–T2)", "PRESERVED (sensory fully spared)"],
["Proprioception & Vibration", "PRESERVED (early); affected late", "PRESERVED throughout"],
["Touch & Pressure", "Preserved until late", "Preserved"],
["Hand / arm wasting", "Present (LMN from anterior horn involvement)", "Present (prominent LMN sign)"],
["Fasciculations", "Absent or rare", "PROMINENT (characteristic LMN sign)"],
["Deep tendon reflexes (arms)", "REDUCED / absent (LMN)", "INCREASED (UMN) + reduced (LMN) – mixed"],
["Reflexes (legs)", "INCREASED (UMN – corticospinal tract)", "INCREASED (UMN) – hyperreflexia"],
["Babinski sign", "Present (late, with cord enlargement)", "Present (UMN sign – characteristic)"],
["Spasticity / Tone", "Increased in legs (late)", "Spastic legs + flaccid arms (mixed)"],
["Bladder / bowel", "Usually spared (early); affected late", "SPARED throughout (characteristic)"],
["Pain / Headache", "Neck pain, headache (Chiari effect)", "Usually painless"],
["Bulbar symptoms", "Lower cranial nerve palsies (syringobulbia)", "Dysarthria, dysphagia (bulbar-onset ALS)"],
["Sensory level / cape", "Cape-like sensory loss over shoulders + arms", "None"],
["Trophic changes", "Charcot joints, painless burns/injuries", "None"],
["Respiration", "Not primarily affected (unless high cervical)", "Respiratory failure (terminal event)"],
["Course", "Slowly progressive; stable periods possible", "Relentlessly progressive; fatal in 2–5 years"],
]
col_ws = [Inches(3.1), Inches(4.85), Inches(5.25)]
y_start = Inches(1.28); hdr_h = Inches(0.48); row_h = Inches(0.48)
# Header
x = Inches(0.18)
hdr_cols = [WHITE, SYR_COLOR, MND_COLOR]
for ci, (h, wid, col) in enumerate(zip(headers, col_ws, hdr_cols)):
add_rect(s, x, y_start, wid, hdr_h, BURNT_ORANGE if ci == 0 else col)
add_tb(s, x + Inches(0.06), y_start + Inches(0.07), wid - Inches(0.1), Inches(0.36),
h, 13, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
x += wid
for ri, row in enumerate(rows):
y = y_start + hdr_h + ri * row_h
x = Inches(0.18)
for ci, (cell, wid) in enumerate(zip(row, col_ws)):
bg = PALE_AMBER if ri % 2 == 0 else LIGHT_ORANGE
add_rect(s, x, y, wid, row_h, CREAM if ci == 0 else bg)
fc = BURNT_ORANGE if ci == 0 else DARK_GREY
bold = ci == 0
add_tb(s, x + Inches(0.05), y + Inches(0.07), wid - Inches(0.08), row_h - Inches(0.1),
cell, 10.5, bold=bold, color=fc, wrap=True)
x += wid
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 6 – INVESTIGATIONS
# ─────────────────────────────────────────────────────────────────────────────
def s6_investigations(prs):
s = prs.slides.add_slide(blank)
slide_frame(s, "INVESTIGATIONS")
add_rect(s, Inches(0.2), Inches(1.3), Inches(6.15), Inches(0.48), SYR_COLOR)
add_tb(s, Inches(0.32), Inches(1.34), Inches(6.0), Inches(0.42), "SYRINGOMYELIA", 16, bold=True, color=WHITE)
add_rect(s, Inches(6.7), Inches(1.3), Inches(6.4), Inches(0.48), MND_COLOR)
add_tb(s, Inches(6.82), Inches(1.34), Inches(6.2), Inches(0.42), "BILATERAL BRACHIAL MND / ALS", 16, bold=True, color=WHITE)
syr_inv = [
("MRI Spine (GOLD STANDARD)", ["T1/T2: fluid-filled cavity (low T1, high T2)", "Sagittal view: extent of syrinx", "Gadolinium: associated tumour or inflammation",
"MRI brain: Chiari malformation assessment (tonsillar descent)"]),
("CT Myelogram", ["If MRI contraindicated", "Delayed CT after intrathecal contrast shows syrinx filling"]),
("CSF Analysis (LP)", ["Usually normal", "Done to exclude inflammatory / infectious cause", "High protein if associated tumour"]),
("Plain X-ray / CT Spine", ["Atlantoaxial instability (Chiari), scoliosis", "Vertebral anomalies (Klippel-Feil, basilar invagination)"]),
("Neurophysiology (EMG/NCS)", ["Denervation changes in upper limb (anterior horn)", "Normal sensory nerve action potentials (posterior columns spared)"]),
("Ophthalmology", ["Nystagmus (Chiari), Horner syndrome (syringobulbia)"]),
]
mnd_inv = [
("EMG / NCS (GOLD STANDARD)", ["Widespread denervation: fibrillations, positive sharp waves", "Fasciculation potentials in multiple limb + bulbar regions",
"Motor NCS: reduced CMAP amplitude; sensory NCS NORMAL", "Single-fibre EMG: increased jitter (NMJ remodelling)"]),
("MRI Brain + Spine", ["Rules out compressive myelopathy, structural causes", "T2 signal along corticospinal tract = UMN degeneration",
"Not diagnostic of ALS but essential to exclude mimics"]),
("Neuropsychology", ["Frontotemporal cognitive assessment (up to 50% have FTD features)", "ALS-FTD overlap"]),
("Blood tests", ["FBC, CMP, TFT, B12, folate, heavy metals", "Anti-GM1 antibodies (exclude multifocal motor neuropathy)", "SOD1 / C9orf72 genetic testing (familial ALS)"]),
("CSF Analysis", ["Normal cell count, mildly elevated protein sometimes", "Rules out inflammatory myelopathy"]),
("Respiratory function", ["FVC, FEV1, SNIP (sniff nasal inspiratory pressure)", "Baseline for ventilatory support planning"]),
]
bw = Inches(6.05); boxes_y = [Inches(1.82), Inches(2.97), Inches(3.88), Inches(4.72), Inches(5.63), Inches(6.4)]
heights = [Inches(1.08), Inches(0.85), Inches(0.78), Inches(0.85), Inches(0.72), Inches(0.65)]
for i, ((title, items), bh) in enumerate(zip(syr_inv, heights)):
y = boxes_y[i]; bg = PALE_AMBER if i % 2 == 0 else LIGHT_ORANGE
add_rect(s, Inches(0.2), y, bw, bh, bg)
add_rect(s, Inches(0.2), y, Inches(0.06), bh, SYR_COLOR)
add_tb(s, Inches(0.32), y + Inches(0.04), bw - Inches(0.18), Inches(0.32),
title, 11.5, bold=True, color=SYR_COLOR)
bullet_box(s, Inches(0.32), y + Inches(0.37), bw - Inches(0.18), bh - Inches(0.42),
items, bsz=10, bc=DARK_GREY)
bw2 = Inches(6.3)
for i, ((title, items), bh) in enumerate(zip(mnd_inv, heights)):
y = boxes_y[i]; bg = PALE_AMBER if i % 2 == 0 else LIGHT_ORANGE
add_rect(s, Inches(6.7), y, bw2, bh, bg)
add_rect(s, Inches(6.7), y, Inches(0.06), bh, MND_COLOR)
add_tb(s, Inches(6.82), y + Inches(0.04), bw2 - Inches(0.18), Inches(0.32),
title, 11.5, bold=True, color=MND_COLOR)
bullet_box(s, Inches(6.82), y + Inches(0.37), bw2 - Inches(0.18), bh - Inches(0.42),
items, bsz=10, bc=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 7 – TREATMENT
# ─────────────────────────────────────────────────────────────────────────────
def s7_treatment(prs):
s = prs.slides.add_slide(blank)
slide_frame(s, "TREATMENT")
add_rect(s, Inches(0.2), Inches(1.3), Inches(6.15), Inches(0.48), SYR_COLOR)
add_tb(s, Inches(0.32), Inches(1.34), Inches(6.0), Inches(0.42), "SYRINGOMYELIA", 16, bold=True, color=WHITE)
add_rect(s, Inches(6.7), Inches(1.3), Inches(6.4), Inches(0.48), MND_COLOR)
add_tb(s, Inches(6.82), Inches(1.34), Inches(6.2), Inches(0.42), "BILATERAL BRACHIAL MND / ALS", 16, bold=True, color=WHITE)
syr_tx = [
("Treat Underlying Cause",
["Chiari I malformation: POSTERIOR FOSSA DECOMPRESSION (suboccipital craniectomy + C1 laminectomy)",
"Tethered cord: surgical detethering",
"Spinal tumour: surgical excision / decompression"]),
("Surgical – Syrinx Drainage",
["Syringosubarachnoid / syringoperitoneal shunt (for large syrinx not responding to decompression)",
"Indicated for acute neurological deterioration",
"~2/3 of patients: slowly progressive (no emergency imaging needed if stable)"]),
("Conservative / Monitoring",
["Serial MRI (6–12 monthly) to monitor syrinx size",
"Avoid Valsalva-increasing activities (heavy lifting, contact sports)",
"Pain management: neuropathic pain agents (gabapentin, pregabalin)"]),
("Rehabilitation",
["Physiotherapy for gait / upper limb function",
"Occupational therapy (hand weakness, ADLs)",
"Neurosurgeon referral always indicated once diagnosis is made"]),
]
mnd_tx = [
("Disease-Modifying (neuroprotective)",
["Riluzole (glutamate blocker): prolongs survival by 2–3 months; 50 mg BD",
" \u2013 Most useful: FVC >60%, symptoms <5 yrs, no tracheostomy",
"Edaravone (IV): free radical scavenger; approved for early-stage ALS",
"AMX0035 (sodium phenylbutyrate + ursodoxicoltaurine): approved FDA 2022"]),
("Respiratory Support",
["Non-invasive ventilation (NIV / BiPAP): when FVC <50% or SNIP <40 cmH\u2082O",
"Tracheostomy + mechanical ventilation (patient choice in late disease)",
"Diaphragm pacing (selected patients)"]),
("Symptomatic / Supportive",
["Sialorrhoea: hyoscine, amitriptyline, botulinum toxin to salivary glands",
"Spasticity: baclofen, tizanidine",
"Cramps: quinine, mexiletine, magnesium",
"Pseudobulbar affect: dextromethorphan/quinidine (Nuedexta)"]),
("Multidisciplinary Team",
["Speech therapy (dysarthria, dysphagia), AAC devices",
"Nutritional support: PEG tube when BMI falling / dysphagia severe",
"Palliative care: advance directive, EOL planning",
"Psychological support for patient and family"]),
]
bw = Inches(6.05); row_h = Inches(1.5)
ys = [Inches(1.82), Inches(3.36), Inches(4.9), Inches(6.18)]
rhs = [Inches(1.48), Inches(1.48), Inches(1.48), Inches(1.12)]
for i, ((title, items), rh) in enumerate(zip(syr_tx, rhs)):
y = ys[i]; bg = PALE_AMBER if i % 2 == 0 else LIGHT_ORANGE
add_rect(s, Inches(0.2), y, bw, rh, bg)
add_rect(s, Inches(0.2), y, Inches(0.06), rh, SYR_COLOR)
add_tb(s, Inches(0.32), y + Inches(0.05), bw - Inches(0.18), Inches(0.35),
title, 12, bold=True, color=SYR_COLOR)
bullet_box(s, Inches(0.32), y + Inches(0.42), bw - Inches(0.18), rh - Inches(0.48),
items, bsz=11, bc=DARK_GREY)
bw2 = Inches(6.3)
for i, ((title, items), rh) in enumerate(zip(mnd_tx, rhs)):
y = ys[i]; bg = PALE_AMBER if i % 2 == 0 else LIGHT_ORANGE
add_rect(s, Inches(6.7), y, bw2, rh, bg)
add_rect(s, Inches(6.7), y, Inches(0.06), rh, MND_COLOR)
add_tb(s, Inches(6.82), y + Inches(0.05), bw2 - Inches(0.18), Inches(0.35),
title, 12, bold=True, color=MND_COLOR)
bullet_box(s, Inches(6.82), y + Inches(0.42), bw2 - Inches(0.18), rh - Inches(0.48),
items, bsz=11, bc=DARK_GREY)
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 8 – KEY DIFFERENTIATING POINTS
# ─────────────────────────────────────────────────────────────────────────────
def s8_diff(prs):
s = prs.slides.add_slide(blank)
slide_frame(s, "KEY DIFFERENTIATING POINTS", "Why they can mimic each other – and how to tell them apart")
# Why they mimic each other
add_rounded_rect(s, Inches(0.2), Inches(1.3), Inches(12.9), Inches(0.85), PALE_AMBER)
add_rect(s, Inches(0.2), Inches(1.3), Inches(0.08), Inches(0.85), AMBER)
tb = s.shapes.add_textbox(Inches(0.35), Inches(1.35), Inches(12.6), Inches(0.75))
tf = tb.text_frame; tf.word_wrap = True; tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
r1 = p.add_run(); r1.text = "Why they mimic each other: "
r1.font.bold = True; r1.font.size = Pt(13); r1.font.color.rgb = BURNT_ORANGE; r1.font.name = "Calibri"
r2 = p.add_run()
r2.text = ("Both present with bilateral arm wasting + weakness (hand muscle atrophy), "
"reduced reflexes in the arms, and can involve the corticospinal tract (UMN signs in legs). "
"The absence of sensory loss in ALS vs. the prominent cape-distribution dissociated sensory loss in syringomyelia is THE key differentiating sign.")
r2.font.size = Pt(13); r2.font.color.rgb = DARK_GREY; r2.font.name = "Calibri"
# Differentiating table
diff_rows = [
("Sensory loss", "Cape-like dissociated loss (pain & temp)\nPosterior columns preserved", "ABSENT – sensory fully spared", "\u2605\u2605\u2605 MOST IMPORTANT"),
("Fasciculations", "Absent or rare", "PROMINENT (widespread, multi-segment)", "\u2605\u2605\u2605"),
("Reflexes – arms", "Reduced (LMN)", "Mixed: UMN + LMN (brisk + absent)", "\u2605\u2605"),
("Reflexes – legs", "Brisk (corticospinal)", "Very brisk + Babinski", "\u2605\u2605"),
("Bladder / bowel", "Affected (late myelopathy)", "ALWAYS SPARED", "\u2605\u2605"),
("Sphincter sparing", "No", "YES – characteristic of MND", "\u2605\u2605"),
("Pain", "Neck pain, headache (Chiari)", "Painless (no pain in MND)", "\u2605"),
("MRI spine", "Syrinx cavity (T2 bright)", "Normal or corticospinal tract signal", "\u2605\u2605\u2605"),
("EMG / NCS", "Denervation in arms only; Sensory NCS normal", "Widespread denervation; Sensory NCS normal", "\u2605\u2605\u2605"),
("Prognosis", "Slowly progressive; treatable cause possible", "Fatal; progressive; no cure", "\u2605\u2605"),
]
headers2 = ["Feature", "Syringomyelia", "Bilateral Brachial MND/ALS", "Diagnostic Weight"]
col_ws2 = [Inches(2.15), Inches(4.05), Inches(4.55), Inches(2.35)]
y0 = Inches(2.25); hh = Inches(0.43); rh = Inches(0.46)
x = Inches(0.18)
hdr_c = [BURNT_ORANGE, SYR_COLOR, MND_COLOR, FOREST_GREEN]
for ci, (h, wid, col) in enumerate(zip(headers2, col_ws2, hdr_c)):
add_rect(s, x, y0, wid, hh, col)
add_tb(s, x + Inches(0.04), y0 + Inches(0.06), wid - Inches(0.08), Inches(0.34),
h, 12, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
x += wid
for ri, row in enumerate(diff_rows):
y = y0 + hh + ri * rh
x = Inches(0.18)
for ci, (cell, wid) in enumerate(zip(row, col_ws2)):
bg = PALE_AMBER if ri % 2 == 0 else LIGHT_ORANGE
add_rect(s, x, y, wid, rh, CREAM if ci == 0 else bg)
fc = BURNT_ORANGE if ci == 0 else (FOREST_GREEN if ci == 3 else DARK_GREY)
add_tb(s, x + Inches(0.04), y + Inches(0.06), wid - Inches(0.08), rh - Inches(0.1),
cell, 10.5, bold=(ci == 0), color=fc, wrap=True)
x += wid
# ─────────────────────────────────────────────────────────────────────────────
# SLIDE 9 – SUMMARY / KEY PEARLS
# ─────────────────────────────────────────────────────────────────────────────
def s9_summary(prs):
s = prs.slides.add_slide(blank)
add_rect(s, 0, 0, W, H, BURNT_ORANGE)
add_rect(s, 0, 0, Inches(0.6), H, MAPLE_RED)
add_rect(s, Inches(0.6), Inches(1.45), W - Inches(0.6), Inches(0.07), AMBER)
# Decorative maple shapes
for rx, ry, sz in [(11.2, 4.5, 1.3), (11.8, 1.5, 0.9), (0.8, 6.2, 0.7)]:
add_rounded_rect(s, Inches(rx), Inches(ry), Inches(sz), Inches(sz*1.2), WARM_ORANGE)
add_tb(s, Inches(0.9), Inches(0.3), Inches(12), Inches(1.0),
"CLINICAL PEARLS & SUMMARY", 30, bold=True, color=WHITE)
pearls = [
"The SINGLE MOST IMPORTANT differentiator: sensory loss is PRESENT (dissociated, cape-like) in syringomyelia and ABSENT in MND.",
"Fasciculations: prominent and widespread in MND; rare/absent in syringomyelia – look for them in multiple muscle groups.",
"Bladder/bowel always spared in MND; may be affected late in syringomyelia – sphincter involvement favours syringomyelia.",
"MRI spine is the gold standard for syringomyelia (T2 bright fluid cavity); EMG/NCS is the gold standard for ALS (widespread denervation, normal sensory NCS).",
"In syringomyelia, legs show UMN signs (brisk reflexes, spasticity) while arms show LMN signs – a classic dissociation.",
"In ALS/MND, BOTH UMN and LMN signs co-exist in the same region (e.g., fasciculations + hyperreflexia in same arm).",
"ALS is fatal (2–5 yr); syringomyelia is treatable if the underlying cause (Chiari malformation) is corrected surgically.",
"Chiari malformation + syrinx = posterior fossa decompression; ALS = riluzole + multidisciplinary supportive care.",
"Remember: ALS spares oculomotor neurons and sphincters – a neuroanatomical 'fingerprint' not seen in any structural myelopathy.",
]
tb = s.shapes.add_textbox(Inches(0.88), Inches(1.62), Inches(12.15), Inches(5.65))
tf = tb.text_frame; tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
first = True
for i, pt in enumerate(pearls):
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False; p.space_before = Pt(5)
r = p.add_run()
r.text = f" {i+1}. " + pt
r.font.size = Pt(13)
r.font.color.rgb = WHITE if i % 2 == 0 else PALE_AMBER
r.font.name = "Calibri"
# ─────────────────────────────────────────────────────────────────────────────
# BUILD
# ─────────────────────────────────────────────────────────────────────────────
s1_title(prs)
s2_definition(prs)
s3_etiology(prs)
s4_pathology(prs)
s5_clinical(prs)
s6_investigations(prs)
s7_treatment(prs)
s8_diff(prs)
s9_summary(prs)
out = "/tmp/workspace/diplopia-ppt/Syringomyelia_vs_MND.pptx"
prs.save(out)
print(f"Saved: {out} ({len(prs.slides)} slides)")
cd /tmp/workspace/diplopia-ppt && python make_syrinx_ppt.py 2>&1
Syringomyelia vs MND
Presentation · PPTX
| Slide | Content |
|---|---|
| 1 | Title slide - split title with colour-coded disease names |
| 2 | Definition - side-by-side cards for both conditions |
| 3 | Etiology - causes with pathomechanism for each (Chiari / C9orf72 etc.) |
| 4 | Pathology - gross, micro-anatomy, tract involvement, spread pattern |
| 5 | Clinical Features - full comparison table (18 rows including sensory loss, fasciculations, reflexes, bladder, bulbar, prognosis) |
| 6 | Investigations - MRI/EMG as gold standards, plus CSF, blood tests, respiratory function |
| 7 | Treatment - surgical for syringomyelia (posterior fossa decompression) vs. riluzole/MDT for MND |
| 8 | Key Differentiating Points - colour-coded table with "diagnostic weight" stars |
| 9 | Clinical Pearls - 9 high-yield differentiating points on burnt-orange background |