Make me ppt on toticolis
mkdir -p /tmp/workspace/torticollis-ppt && ls /tmp/workspace/torticollis-ppt/
~/torticollis-ppt/build_ppt.py
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.util import Inches, Pt
import json, subprocess, base64
from io import BytesIO
# ── Colour palette ──────────────────────────────────────────────────
DARK_BLUE = RGBColor(0x0A, 0x29, 0x4E) # deep navy
MED_BLUE = RGBColor(0x14, 0x5A, 0x9E) # medium blue
ACCENT = RGBColor(0x1F, 0x9E, 0xD5) # cyan-blue accent
LIGHT_BG = RGBColor(0xF0, 0xF6, 0xFF) # very pale blue
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
TEXT_DARK = RGBColor(0x1A, 0x1A, 0x2E)
GREY = RGBColor(0x55, 0x65, 0x78)
GREEN_ACC = RGBColor(0x0D, 0x9E, 0x6E)
ORANGE_ACC = RGBColor(0xE8, 0x7E, 0x1B)
W = Inches(13.333)
H = Inches(7.5)
prs = Presentation()
prs.slide_width = W
prs.slide_height = H
blank = prs.slide_layouts[6]
# ── helper: add_rect ─────────────────────────────────────────────────
def rect(slide, x, y, w, h, fill, alpha=None):
shape = slide.shapes.add_shape(1, Inches(x), Inches(y), Inches(w), Inches(h))
shape.line.fill.background()
shape.fill.solid()
shape.fill.fore_color.rgb = fill
return shape
def textbox(slide, x, y, w, h, text, size=18, bold=False, color=TEXT_DARK,
align=PP_ALIGN.LEFT, wrap=True, italic=False,
margin_l=0.08, margin_t=0.04):
tb = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = tb.text_frame
tf.word_wrap = wrap
tf.margin_left = Inches(margin_l)
tf.margin_top = Inches(margin_t)
tf.margin_right = Inches(0.04)
tf.margin_bottom= Inches(0.02)
p = tf.paragraphs[0]
p.alignment = align
run = p.add_run()
run.text = text
run.font.name = "Calibri"
run.font.size = Pt(size)
run.font.bold = bold
run.font.italic= italic
run.font.color.rgb = color
return tf
def add_bullet_tf(slide, x, y, w, h, items, size=16, color=TEXT_DARK,
title=None, title_size=18, title_color=DARK_BLUE,
bg=None, bullet_char="•"):
if bg:
rect(slide, x, y, w, h, bg)
tb = slide.shapes.add_textbox(Inches(x), Inches(y+0.05), Inches(w), Inches(h-0.05))
tf = tb.text_frame
tf.word_wrap = True
tf.margin_left = Inches(0.12)
tf.margin_top = Inches(0.05)
tf.margin_right = Inches(0.08)
tf.margin_bottom= Inches(0.05)
first = True
if title:
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False
p.alignment = PP_ALIGN.LEFT
run = p.add_run()
run.text = title
run.font.name = "Calibri"
run.font.size = Pt(title_size)
run.font.bold = True
run.font.color.rgb = title_color
for item in items:
p = tf.paragraphs[0] if (first and not title) else tf.add_paragraph()
first = False
p.alignment = PP_ALIGN.LEFT
run = p.add_run()
run.text = f"{bullet_char} {item}"
run.font.name = "Calibri"
run.font.size = Pt(size)
run.font.color.rgb = color
return tf
# ══════════════════════════════════════════════════════════════════════
# SLIDE 1 – Title Slide
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
# full-bleed gradient simulation with two rectangles
rect(slide, 0, 0, 13.333, 7.5, DARK_BLUE)
rect(slide, 0, 0, 13.333, 2.0, MED_BLUE)
# diagonal accent strip
shape = slide.shapes.add_shape(6, Inches(0), Inches(1.7), Inches(13.333), Inches(0.12))
shape.line.fill.background()
shape.fill.solid()
shape.fill.fore_color.rgb = ACCENT
# subtitle bar
rect(slide, 0, 5.5, 13.333, 2.0, RGBColor(0x0D, 0x1F, 0x3C))
# Title
textbox(slide, 1.0, 2.3, 11.0, 2.0,
"TORTICOLLIS", size=60, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
# Subtitle
textbox(slide, 1.0, 4.2, 11.0, 0.9,
"Wryneck — Classification, Pathophysiology, Diagnosis & Management",
size=22, color=ACCENT, align=PP_ALIGN.CENTER)
# Footer bar text
textbox(slide, 1.0, 5.7, 11.0, 0.6,
"A Detailed Academic Review | Medical Students & Clinicians",
size=16, italic=True, color=RGBColor(0xB0, 0xC8, 0xE8), align=PP_ALIGN.CENTER)
textbox(slide, 1.0, 6.4, 11.0, 0.5,
"Sources: Bailey & Love | Campbell's Orthopaedics | Adams & Victor's Neurology | S Das Surgery",
size=11, italic=True, color=RGBColor(0x7A, 0x98, 0xB8), align=PP_ALIGN.CENTER)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 2 – Definition & Overview
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
rect(slide, 0, 0, 13.333, 7.5, LIGHT_BG)
rect(slide, 0, 0, 13.333, 1.15, DARK_BLUE)
rect(slide, 0, 1.05, 13.333, 0.1, ACCENT)
textbox(slide, 0.4, 0.15, 12.5, 0.85,
"DEFINITION & OVERVIEW", size=28, bold=True, color=WHITE)
# Definition box
rect(slide, 0.4, 1.3, 12.5, 1.5, MED_BLUE)
textbox(slide, 0.55, 1.38, 12.1, 1.3,
'"Torticollis (Wryneck) is a deformity in which the head is tilted toward one side '
'while the chin points to the opposite side, due to shortening or spasm of the '
'sternocleidomastoid (SCM) muscle and posterior cervical muscles."',
size=17, italic=True, color=WHITE, wrap=True)
# Key facts 3-column
cols = [
("Muscle Involved", ["Sternocleidomastoid (SCM)", "Levator scapulae", "Trapezius", "Posterior cervical mm."]),
("Head Position", ["Head tilts TOWARD affected side", "Chin rotates AWAY from affected side", "Facial asymmetry in chronic cases"]),
("Peak Incidence", ["Congenital: Neonates", "Spasmodic: 4th–5th decade", "Slightly more common in women (spasmodic type)"]),
]
col_x = [0.4, 4.6, 8.8]
for i,(title,items) in enumerate(cols):
rect(slide, col_x[i], 3.05, 4.0, 3.9, WHITE)
rect(slide, col_x[i], 3.05, 4.0, 0.55, MED_BLUE)
textbox(slide, col_x[i]+0.1, 3.08, 3.8, 0.5,
title, size=16, bold=True, color=WHITE)
add_bullet_tf(slide, col_x[i]+0.1, 3.7, 3.8, 3.1, items,
size=15, color=TEXT_DARK)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 3 – Classification
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
rect(slide, 0, 0, 13.333, 7.5, LIGHT_BG)
rect(slide, 0, 0, 13.333, 1.15, DARK_BLUE)
rect(slide, 0, 1.05, 13.333, 0.1, ACCENT)
textbox(slide, 0.4, 0.15, 12.5, 0.85, "CLASSIFICATION OF TORTICOLLIS", size=28, bold=True, color=WHITE)
types = [
("(a) Congenital", GREEN_ACC,
["Intrauterine moulding / birth trauma",
"Palpable SCM 'tumour'/fibrous nodule",
"Most common type in neonates",
"Associated: DDH, plagiocephaly"]),
("(b) Muscular/Spasmodic", MED_BLUE,
["Idiopathic cervical dystonia",
"Sustained involuntary SCM contraction",
"4th–5th decade; women > men",
"Sensory tricks (gestes) relieve spasm"]),
("(c) Traumatic", ORANGE_ACC,
["Fracture-dislocation of cervical spine",
"Atlantoaxial rotatory subluxation",
"Grisel syndrome (post-infectious C1-C2 sublux)",
"Immediate immobilization needed"]),
("(d) Inflammatory", RGBColor(0xC0, 0x39, 0x2B),
["Inflamed cervical lymph nodes",
"Retropharyngeal abscess",
"Soft-tissue neck infections",
"Treat underlying infection"]),
("(e) Rheumatic/Postural", RGBColor(0x6C, 0x35, 0x91),
["Sudden onset after cold/draught exposure",
"Muscle spasm from minor strain",
"Usually self-limiting",
"NSAIDs + physiotherapy"]),
("(f) Compensatory/Other", GREY,
["Ocular torticollis (refractive errors, palsy)",
"Scoliosis compensation",
"Posterior fossa tumours",
"Pott's disease (TB) of cervical spine"]),
]
positions = [(0.35, 1.25),(4.55, 1.25),(8.75, 1.25),
(0.35, 4.2 ),(4.55, 4.2 ),(8.75, 4.2 )]
for i,(title, col, items) in enumerate(types):
x, y = positions[i]
rect(slide, x, y, 3.95, 2.9, WHITE)
rect(slide, x, y, 3.95, 0.5, col)
textbox(slide, x+0.1, y+0.04, 3.7, 0.44,
title, size=14, bold=True, color=WHITE)
add_bullet_tf(slide, x+0.1, y+0.55, 3.75, 2.25, items,
size=13, color=TEXT_DARK)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 4 – Congenital Muscular Torticollis: Aetiology & Pathophysiology
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
rect(slide, 0, 0, 13.333, 7.5, LIGHT_BG)
rect(slide, 0, 0, 13.333, 1.15, DARK_BLUE)
rect(slide, 0, 1.05, 13.333, 0.1, ACCENT)
textbox(slide, 0.4, 0.15, 12.5, 0.85,
"CONGENITAL MUSCULAR TORTICOLLIS (CMT) — AETIOLOGY & PATHOPHYSIOLOGY",
size=24, bold=True, color=WHITE)
# Left: aetiology
rect(slide, 0.35, 1.25, 6.0, 5.85, WHITE)
rect(slide, 0.35, 1.25, 6.0, 0.5, MED_BLUE)
textbox(slide, 0.5, 1.28, 5.7, 0.45, "Proposed Aetiologies", size=16, bold=True, color=WHITE)
aetio = [
"Malposition/moulding of fetus in utero",
"Intrauterine or perinatal compartment syndrome → ischaemia of SCM",
"Birth trauma during difficult delivery",
"Vascular injury to SCM",
"Intrauterine constraint",
"Infection",
"Perinatal SCM fibrosis leads to shortening and contracture",
]
add_bullet_tf(slide, 0.45, 1.85, 5.8, 5.1, aetio, size=14.5, color=TEXT_DARK)
# Right: pathophysiology chain
rect(slide, 6.7, 1.25, 6.3, 5.85, WHITE)
rect(slide, 6.7, 1.25, 6.3, 0.5, GREEN_ACC)
textbox(slide, 6.85, 1.28, 6.0, 0.45, "Pathophysiology Chain", size=16, bold=True, color=WHITE)
steps = [
("Birth / Intrauterine Insult", MED_BLUE),
("SCM Ischaemia / Compartment Syndrome", RGBColor(0x0D,0x77,0xB5)),
("Fibrosis & Contracture of SCM", RGBColor(0x0D,0x9E,0x6E)),
("Head Tilt (ipsilateral) + Chin Rotation (contralateral)", ORANGE_ACC),
("Facial Asymmetry / Plagiocephaly if untreated", RGBColor(0xC0,0x39,0x2B)),
("Associated: DDH in 2–3% of CMT cases", GREY),
]
sy = 1.85
for text, col in steps:
rect(slide, 6.85, sy, 5.9, 0.62, col)
textbox(slide, 6.97, sy+0.05, 5.6, 0.55, text, size=13.5, bold=True, color=WHITE, wrap=True)
if col != GREY:
# arrow
arr = slide.shapes.add_shape(13, Inches(9.2), Inches(sy+0.62), Inches(0.25), Inches(0.2))
arr.line.fill.background()
arr.fill.solid()
arr.fill.fore_color.rgb = ACCENT
sy += 0.88
# ══════════════════════════════════════════════════════════════════════
# SLIDE 5 – Clinical Features & Diagnosis
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
rect(slide, 0, 0, 13.333, 7.5, LIGHT_BG)
rect(slide, 0, 0, 13.333, 1.15, DARK_BLUE)
rect(slide, 0, 1.05, 13.333, 0.1, ACCENT)
textbox(slide, 0.4, 0.15, 12.5, 0.85, "CLINICAL FEATURES & DIAGNOSIS", size=28, bold=True, color=WHITE)
# Left panel
rect(slide, 0.35, 1.25, 6.1, 5.9, WHITE)
rect(slide, 0.35, 1.25, 6.1, 0.5, MED_BLUE)
textbox(slide, 0.5, 1.28, 5.8, 0.45, "Clinical Features", size=16, bold=True, color=WHITE)
feats = [
"Head tilted TOWARD affected SCM",
"Chin rotated AWAY from affected side",
"Palpable firm/fibrotic SCM mass (congenital)",
"Restricted neck rotation (>30° limitation = poor prognosis)",
"Facial asymmetry: smaller outer canthus–mouth distance, flattened nose, less arched brow on affected side",
"Elevated ipsilateral shoulder in severe cases",
"Plagiocephaly: reduced fronto-occipital diameter",
"Sensory tricks (touching chin) reduce spasm (spasmodic type)",
"Tremor may accompany dystonic posturing",
"Muscle hypertrophy in chronic/fixed cases",
]
add_bullet_tf(slide, 0.45, 1.85, 5.9, 5.15, feats, size=13.5, color=TEXT_DARK)
# Right panel
rect(slide, 6.75, 1.25, 6.2, 2.8, WHITE)
rect(slide, 6.75, 1.25, 6.2, 0.5, GREEN_ACC)
textbox(slide, 6.9, 1.28, 5.9, 0.45, "Diagnostic Investigations", size=16, bold=True, color=WHITE)
inv = [
"Clinical examination: usually sufficient for CMT",
"Ultrasound of SCM: evaluates fibrotic mass thickness & extent; predicts surgery need",
"Cervical X-ray: exclude congenital vertebral anomalies, fracture-dislocation",
"MRI/CT: neurologic findings, atlantoaxial subluxation, posterior fossa tumours",
"EMG: identifies hyperactive muscles in spasmodic type (guides BTX injection)",
]
add_bullet_tf(slide, 6.85, 1.85, 5.95, 2.05, inv, size=13, color=TEXT_DARK)
rect(slide, 6.75, 4.2, 6.2, 2.85, WHITE)
rect(slide, 6.75, 4.2, 6.2, 0.5, ORANGE_ACC)
textbox(slide, 6.9, 4.23, 5.9, 0.45, "Red Flags (Acquired Torticollis)", size=16, bold=True, color=WHITE)
red = [
"Fever + neck stiffness → septic arthritis / retropharyngeal abscess",
"Trauma history → cervical fracture-dislocation",
"Neurological deficits → posterior fossa tumour",
"Recent URTI in child → Grisel syndrome (C1-C2 subluxation)",
"Acute painful onset → atlantoaxial rotatory subluxation",
]
add_bullet_tf(slide, 6.85, 4.8, 5.95, 2.15, red, size=13, color=TEXT_DARK,
bullet_char="⚠")
# ══════════════════════════════════════════════════════════════════════
# SLIDE 6 – Management: Non-Operative
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
rect(slide, 0, 0, 13.333, 7.5, LIGHT_BG)
rect(slide, 0, 0, 13.333, 1.15, DARK_BLUE)
rect(slide, 0, 1.05, 13.333, 0.1, ACCENT)
textbox(slide, 0.4, 0.15, 12.5, 0.85,
"MANAGEMENT — NON-OPERATIVE TREATMENT", size=28, bold=True, color=WHITE)
# Timeline boxes
phases = [
("< 3–4 Months", MED_BLUE,
["Start physiotherapy (stretching) IMMEDIATELY",
"Rotate chin to affected shoulder while tilting head to opposite shoulder",
"92–100% achieve full passive neck rotation",
"Only 1% require surgery with early treatment",
"Each month of delay increases surgical risk"]),
("Botulinum Toxin A (BTX-A)", GREEN_ACC,
["Combined BTX-A + physiotherapy: 84% effective",
"9% conversion to surgery; 1% adverse reactions",
"Injected into hypertonic SCM ± levator scapulae",
"EMG-guided for spasmodic/idiopathic cervical dystonia",
"Repeated every 3–6 months; 90% relief in spasmodic type"]),
("Drug Therapy (Spasmodic)", ORANGE_ACC,
["Botulinum toxin — first-line (Grade A)",
"Trihexyphenidyl / benztropine: partial relief, tolerated poorly",
"L-dopa: rarely useful unless early Parkinson's",
"Muscle relaxants: short-term adjunct",
"NSAIDs: for rheumatic/postural types"]),
]
px = [0.35, 4.6, 8.85]
for i,(title, col, items) in enumerate(phases):
rect(slide, px[i], 1.25, 4.05, 5.95, WHITE)
rect(slide, px[i], 1.25, 4.05, 0.55, col)
textbox(slide, px[i]+0.1, 1.28, 3.8, 0.5, title, size=16, bold=True, color=WHITE)
add_bullet_tf(slide, px[i]+0.1, 1.9, 3.85, 5.1, items, size=14, color=TEXT_DARK)
# Evidence note
rect(slide, 0.35, 7.0, 12.65, 0.42, RGBColor(0xE8, 0xF4, 0xFD))
textbox(slide, 0.5, 7.03, 12.4, 0.37,
"Evidence: SCM thickness >5 cm → longer treatment duration. Nonoperative treatment rarely successful if CMT persists beyond 1 year of age. "
"(Campbell's Operative Orthopaedics 15e; Kaplan et al. 2018 AAPT Guidelines)",
size=11, italic=True, color=GREY)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 7 – Management: Operative Treatment
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
rect(slide, 0, 0, 13.333, 7.5, LIGHT_BG)
rect(slide, 0, 0, 13.333, 1.15, DARK_BLUE)
rect(slide, 0, 1.05, 13.333, 0.1, ACCENT)
textbox(slide, 0.4, 0.15, 12.5, 0.85,
"MANAGEMENT — OPERATIVE TREATMENT", size=28, bold=True, color=WHITE)
# Indications
rect(slide, 0.35, 1.25, 5.5, 2.8, WHITE)
rect(slide, 0.35, 1.25, 5.5, 0.5, RGBColor(0xC0, 0x39, 0x2B))
textbox(slide, 0.5, 1.28, 5.2, 0.45, "Indications for Surgery", size=16, bold=True, color=WHITE)
ind = [
"CMT persisting beyond 1 year of age",
"Failure of 6 months of physiotherapy",
"Limitation of neck rotation >30 degrees",
"Established facial asymmetry",
"Fixed rigid deformity",
]
add_bullet_tf(slide, 0.5, 1.85, 5.2, 2.1, ind, size=14, color=TEXT_DARK)
# Procedures
rect(slide, 0.35, 4.2, 5.5, 2.9, WHITE)
rect(slide, 0.35, 4.2, 5.5, 0.5, MED_BLUE)
textbox(slide, 0.5, 4.23, 5.2, 0.45, "Surgical Procedures (CMT)", size=16, bold=True, color=WHITE)
procs = [
"Unipolar release (distal): mild deformity",
"Bipolar release (origin + insertion): moderate-severe",
"Open sternomastoid tenotomy at clavicle",
"Endoscopic SCM release (newer approach)",
"Z-plasty lengthening of SCM",
]
add_bullet_tf(slide, 0.5, 4.8, 5.2, 2.2, procs, size=14, color=TEXT_DARK)
# Spasmodic type
rect(slide, 6.2, 1.25, 6.8, 5.85, WHITE)
rect(slide, 6.2, 1.25, 6.8, 0.5, RGBColor(0x6C, 0x35, 0x91))
textbox(slide, 6.35, 1.28, 6.5, 0.45,
"Surgical Options — Spasmodic/Idiopathic Cervical Dystonia", size=15, bold=True, color=WHITE)
surg2 = [
"Deep Brain Stimulation (DBS):",
" - Globus pallidus interna (GPi) — preferred target",
" - Subthalamic nucleus (STN)",
" - Used for BTX-refractory cases",
" - Adverse: dysarthria, dyskinesia, worsening dystonia",
"",
"Selective Peripheral Denervation:",
" - Section of spinal accessory nerve (CN XI)",
" - First 3 cervical motor roots (C1–C3) bilaterally",
" - Relief in 1/3 to 1/2 of severe cases",
" - Maintained for up to 6 years (Krauss et al; Ford et al)",
"",
"Ablative procedures (historical — now largely replaced by DBS)",
]
add_bullet_tf(slide, 6.3, 1.85, 6.6, 5.1, surg2, size=13.5, color=TEXT_DARK)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 8 – Spasmodic Torticollis (Idiopathic Cervical Dystonia)
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
rect(slide, 0, 0, 13.333, 7.5, LIGHT_BG)
rect(slide, 0, 0, 13.333, 1.15, DARK_BLUE)
rect(slide, 0, 1.05, 13.333, 0.1, ACCENT)
textbox(slide, 0.4, 0.15, 12.5, 0.85,
"SPASMODIC TORTICOLLIS — IDIOPATHIC CERVICAL DYSTONIA", size=26, bold=True, color=WHITE)
rect(slide, 0.35, 1.25, 6.0, 5.9, WHITE)
rect(slide, 0.35, 1.25, 6.0, 0.5, MED_BLUE)
textbox(slide, 0.5, 1.28, 5.7, 0.45, "Clinical Profile", size=16, bold=True, color=WHITE)
cp = [
"Most frequent form of focal/restricted dystonia",
"Localised to neck and adjacent shoulder muscles",
"Onset: subtle head tilt or turning, slowly progressive",
"Peak incidence: 4th–5th decade; women > men",
"DYT1 gene abnormality in a few cases (otherwise idiopathic)",
"Quality varies: intermittent/smooth, jerky, or sustained deviation",
"High-frequency tremor may accompany dystonic posture",
"Spasms worsen on standing/walking",
"Sensory tricks ('gestes') temporarily relieve spasm",
"Muscle hypertrophy + pain develop in chronic cases",
"15% also have oral/mandibular or hand dystonia",
"10% have associated blepharospasm",
"Spontaneous remission in 10–20% (early onset cases)",
"Nearly all remission cases relapse within 5 years",
]
add_bullet_tf(slide, 0.5, 1.85, 5.75, 5.1, cp, size=13.5, color=TEXT_DARK)
rect(slide, 6.65, 1.25, 6.3, 5.9, WHITE)
rect(slide, 6.65, 1.25, 6.3, 0.5, GREEN_ACC)
textbox(slide, 6.8, 1.28, 6.0, 0.45, "Muscles Involved & Neurology", size=16, bold=True, color=WHITE)
mus = [
"Primary muscles: Sternocleidomastoid (SCM), Levator scapulae, Trapezius",
"Posterior cervical muscles bilaterally active on EMG",
"Levator spasm → elevated ipsilateral shoulder (often earliest sign)",
"Spasms may spread to shoulder girdle, back, face, limbs",
"No consistent neuropathological lesion found on autopsy",
"Abnormal basal ganglia function postulated",
"Related to other focal dystonias in Meige syndrome",
"",
"Diagnosis:",
" - Clinical (history + examination)",
" - EMG to map hyperactive muscles",
" - MRI brain to exclude structural cause",
" - DYT1/DYT6 genetic testing if family history",
]
add_bullet_tf(slide, 6.8, 1.85, 6.0, 5.1, mus, size=13.5, color=TEXT_DARK)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 9 – Grisel Syndrome & Ocular Torticollis
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
rect(slide, 0, 0, 13.333, 7.5, LIGHT_BG)
rect(slide, 0, 0, 13.333, 1.15, DARK_BLUE)
rect(slide, 0, 1.05, 13.333, 0.1, ACCENT)
textbox(slide, 0.4, 0.15, 12.5, 0.85,
"SPECIAL TYPES — GRISEL SYNDROME, OCULAR & BENIGN PAROXYSMAL TORTICOLLIS",
size=24, bold=True, color=WHITE)
panels = [
("Grisel Syndrome", MED_BLUE, [
"Non-traumatic atlantoaxial rotatory subluxation",
"Follows pharyngeal infection/inflammation (e.g., tonsillitis, retropharyngeal abscess)",
"Inflammatory hyperaemia → ligamentous laxity at C1-C2",
"Mostly in children",
"Management: antibiotics for infection + soft collar + cervical traction",
"Surgery (C1-C2 fusion) if neurological compromise or refractory",
]),
("Ocular Torticollis", ORANGE_ACC, [
"Compensatory head tilt to correct diplopia or visual field defect",
"Due to: extraocular muscle palsy (CN III, IV, VI), refractive errors, nystagmus",
"Correct the underlying ocular pathology first",
"Prism therapy or corrective spectacles",
"Strabismus surgery if persistent",
"Critical: rule out before treating as 'muscular' torticollis",
]),
("Benign Paroxysmal Torticollis (BPT)", GREEN_ACC, [
"Episodic head tilt in young children (toddlers)",
"Associated with elevated creatine kinase during episodes",
"Considered a migraine equivalent",
"Episodes: minutes to days; spontaneous resolution",
"Family history of migraine common",
"Not related to vestibular disease",
"No specific treatment; reassurance + prophylactic migraine therapy in severe cases",
]),
]
px2 = [0.35, 4.55, 8.75]
for i,(title, col, items) in enumerate(panels):
rect(slide, px2[i], 1.25, 4.1, 5.9, WHITE)
rect(slide, px2[i], 1.25, 4.1, 0.5, col)
textbox(slide, px2[i]+0.1, 1.28, 3.9, 0.45, title, size=15, bold=True, color=WHITE)
add_bullet_tf(slide, px2[i]+0.1, 1.85, 3.9, 5.15, items, size=13.5, color=TEXT_DARK)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 10 – Prognosis & Summary
# ══════════════════════════════════════════════════════════════════════
slide = prs.slides.add_slide(blank)
rect(slide, 0, 0, 13.333, 7.5, DARK_BLUE)
rect(slide, 0, 1.35, 13.333, 0.1, ACCENT)
textbox(slide, 0.4, 0.2, 12.5, 1.0,
"PROGNOSIS & KEY TAKEAWAYS", size=30, bold=True, color=WHITE)
boxes = [
("Congenital CMT Prognosis", MED_BLUE, [
"Excellent if treatment started <3–4 months: 92–100% achieve full ROM",
"Prognosis worsens with each month of delay",
"SCM thickness >5 cm: longer treatment duration",
"Persistent beyond 1 year → surgical release required",
"Untreated: permanent facial asymmetry, plagiocephaly",
]),
("Spasmodic Torticollis Prognosis", GREEN_ACC, [
"Chronic, rarely cured; managed long-term",
"BTX-A: 90% patients experience some relief",
"5–10% develop neutralising antibodies → resistance",
"Spontaneous remission: 10–20%, but 5-year relapse common",
"DBS: good results in BTX-refractory cases (GPi target)",
]),
("Key Takeaways", ACCENT, [
"Always rule out ocular, bony, and infectious causes first",
"CMT: early physiotherapy is key — start before age 3–4 months",
"SCM stretching: rotate chin to affected side while tilting head away",
"BTX-A: effective adjunct to physiotherapy",
"Spasmodic type: BTX injection guided by EMG every 3–6 months",
"Surgery (unipolar/bipolar SCM release) if conservative fails",
]),
]
px3 = [0.35, 4.55, 8.75]
for i,(title, col, items) in enumerate(boxes):
rect(slide, px3[i], 1.5, 4.1, 5.75, RGBColor(0x0D, 0x1A, 0x30))
rect(slide, px3[i], 1.5, 4.1, 0.5, col)
textbox(slide, px3[i]+0.1, 1.53, 3.9, 0.45, title, size=15, bold=True, color=WHITE)
add_bullet_tf(slide, px3[i]+0.1, 2.1, 3.9, 5.0, items, size=13.5,
color=RGBColor(0xD5, 0xE8, 0xFF))
# References strip
rect(slide, 0, 7.0, 13.333, 0.5, RGBColor(0x05, 0x10, 0x1F))
textbox(slide, 0.35, 7.03, 12.7, 0.44,
"References: Bailey & Love's Short Practice of Surgery 28e | Campbell's Operative Orthopaedics 15e (2026) | "
"Adams & Victor's Principles of Neurology 12e | S Das Manual on Clinical Surgery 13e | "
"Kaplan et al. AAPT Clinical Practice Guidelines 2018",
size=10, italic=True, color=RGBColor(0x7A, 0x98, 0xB8), align=PP_ALIGN.CENTER)
# ══════════════════════════════════════════════════════════════════════
# SAVE
# ══════════════════════════════════════════════════════════════════════
out = "/tmp/workspace/torticollis-ppt/Torticollis.pptx"
buf = BytesIO()
prs.save(buf)
with open(out, "wb") as f:
f.write(buf.getvalue())
print(f"Saved: {out}")
cd /tmp/workspace/torticollis-ppt && python build_ppt.py 2>&1
python -c " from pptx import Presentation prs = Presentation('/tmp/workspace/torticollis-ppt/Torticollis.pptx') print(f'Slides: {len(prs.slides)}') for i, slide in enumerate(prs.slides, 1): texts = [s.text_frame.text.strip()[:60] for s in slide.shapes if s.has_text_frame and s.text_frame.text.strip()] print(f' Slide {i}: {texts[0] if texts else \"[no text]\"}') "
Torticollis
Presentation · PPTX
| Slide | Content |
|---|---|
| 1 | Title slide |
| 2 | Definition & Overview (anatomy, head position, peak incidence) |
| 3 | Classification - all 6 types (Congenital, Spasmodic, Traumatic, Inflammatory, Rheumatic, Compensatory/Other) |
| 4 | CMT - Aetiology & Pathophysiology chain (intrauterine insult → SCM fibrosis → deformity) |
| 5 | Clinical Features & Diagnosis (features, investigations, red flags) |
| 6 | Non-Operative Management (physiotherapy protocol, BTX-A, drugs + evidence notes) |
| 7 | Operative Treatment (CMT release procedures + DBS/denervation for spasmodic type) |
| 8 | Spasmodic Torticollis / Idiopathic Cervical Dystonia (full clinical profile + muscle involvement) |
| 9 | Special Types - Grisel Syndrome, Ocular Torticollis, Benign Paroxysmal Torticollis |
| 10 | Prognosis & Key Takeaways with references |
Make me ppt on toticolis
ls -lh /tmp/workspace/torticollis-ppt/Torticollis.pptx 2>&1
Torticollis
Presentation · PPTX
| Slide | Topic |
|---|---|
| 1 | Title Slide |
| 2 | Definition & Overview |
| 3 | Classification (all 6 types) |
| 4 | CMT - Aetiology & Pathophysiology |
| 5 | Clinical Features & Diagnosis |
| 6 | Non-Operative Management |
| 7 | Operative Treatment |
| 8 | Spasmodic Torticollis / Idiopathic Cervical Dystonia |
| 9 | Special Types (Grisel, Ocular, Benign Paroxysmal) |
| 10 | Prognosis & Key Takeaways |
Floating knee ppt for essay questions for pg orthopedics exam
mkdir -p /tmp/workspace/floating-knee-ppt && echo "ready"
~/floating-knee-ppt/build_fk.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 io import BytesIO
# ── Palette ──────────────────────────────────────────────────────────
DARK = RGBColor(0x0B, 0x24, 0x3B)
MED_BLUE = RGBColor(0x15, 0x5E, 0xA6)
ACCENT = RGBColor(0x00, 0xB0, 0xD8)
LIGHT_BG = RGBColor(0xF2, 0xF7, 0xFF)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
TEXT_DARK = RGBColor(0x12, 0x1A, 0x26)
GREY = RGBColor(0x55, 0x65, 0x78)
GREEN = RGBColor(0x05, 0x96, 0x68)
ORANGE = RGBColor(0xE0, 0x7B, 0x10)
RED = RGBColor(0xBF, 0x28, 0x28)
PURPLE = RGBColor(0x6B, 0x2F, 0x96)
YELLOW_PALE = RGBColor(0xFF, 0xF8, 0xE1)
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
blank = prs.slide_layouts[6]
# ── Helpers ──────────────────────────────────────────────────────────
def rect(slide, x, y, w, h, fill):
s = slide.shapes.add_shape(1, Inches(x), Inches(y), Inches(w), Inches(h))
s.line.fill.background()
s.fill.solid()
s.fill.fore_color.rgb = fill
return s
def tb(slide, x, y, w, h, text, sz=16, bold=False, color=TEXT_DARK,
align=PP_ALIGN.LEFT, italic=False, wrap=True):
box = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = box.text_frame
tf.word_wrap = wrap
tf.margin_left = Inches(0.07); tf.margin_top = Inches(0.03)
tf.margin_right = Inches(0.04); tf.margin_bottom = Inches(0.02)
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run(); r.text = text
r.font.name = "Calibri"; r.font.size = Pt(sz)
r.font.bold = bold; r.font.italic = italic
r.font.color.rgb = color
return tf
def bullets(slide, x, y, w, h, items, sz=14, color=TEXT_DARK,
hdr=None, hdr_color=MED_BLUE, hdr_sz=15, bg=None, bullet="•"):
if bg:
rect(slide, x, y, w, h, bg)
box = slide.shapes.add_textbox(Inches(x), Inches(y+0.04), Inches(w), Inches(h-0.06))
tf = box.text_frame; tf.word_wrap = True
tf.margin_left = Inches(0.10); tf.margin_top = Inches(0.04)
tf.margin_right = Inches(0.06); tf.margin_bottom = Inches(0.04)
first = True
if hdr:
p = tf.paragraphs[0]; first = False
r = p.add_run(); r.text = hdr
r.font.name = "Calibri"; r.font.size = Pt(hdr_sz)
r.font.bold = True; r.font.color.rgb = hdr_color
for itm in items:
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False
r = p.add_run()
r.text = f"{bullet} {itm}" if bullet else itm
r.font.name = "Calibri"; r.font.size = Pt(sz)
r.font.color.rgb = color
return tf
def hdr_bar(slide, title, subtitle=None):
rect(slide, 0, 0, 13.333, 1.18, DARK)
rect(slide, 0, 1.08, 13.333, 0.10, ACCENT)
tb(slide, 0.38, 0.13, 12.6, 0.88, title, sz=27, bold=True, color=WHITE)
if subtitle:
tb(slide, 0.38, 0.72, 12.6, 0.42, subtitle, sz=13, italic=True,
color=RGBColor(0x8A, 0xBE, 0xE0))
def col_card(slide, x, y, w, h, hdr, hdr_col, items, sz=13.5):
rect(slide, x, y, w, h, WHITE)
rect(slide, x, y, w, 0.52, hdr_col)
tb(slide, x+0.10, y+0.06, w-0.2, 0.44, hdr, sz=14.5, bold=True, color=WHITE)
bullets(slide, x+0.10, y+0.56, w-0.20, h-0.62, items, sz=sz)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 1 — Title
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, DARK)
rect(s, 0, 0, 13.333, 2.3, MED_BLUE)
rect(s, 0, 2.18, 13.333, 0.12, ACCENT)
rect(s, 0, 5.6, 13.333, 1.9, RGBColor(0x07, 0x18, 0x28))
tb(s, 0.8, 2.45, 11.8, 2.0, "FLOATING KNEE INJURY",
sz=58, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
tb(s, 0.8, 4.35, 11.8, 0.85,
"Ipsilateral Fractures of the Femur & Tibia — A Comprehensive Review",
sz=22, color=ACCENT, align=PP_ALIGN.CENTER)
tb(s, 0.8, 5.75, 11.8, 0.6,
"Structured for PG Orthopaedics Essay Examination",
sz=17, italic=True, color=RGBColor(0xB0, 0xD0, 0xF0), align=PP_ALIGN.CENTER)
tb(s, 0.8, 6.5, 11.8, 0.55,
"Sources: Campbell's Operative Orthopaedics 15e (2026) | Rockwood & Green's Fractures in Adults 10e (2025) | Miller's Review of Orthopaedics 9e",
sz=11, italic=True, color=RGBColor(0x6A, 0x8CAC), align=PP_ALIGN.CENTER)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 2 — Definition, Epidemiology & Mechanism
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr_bar(s, "DEFINITION, EPIDEMIOLOGY & MECHANISM OF INJURY")
# Definition box
rect(s, 0.35, 1.28, 12.65, 1.30, MED_BLUE)
tb(s, 0.50, 1.33, 12.3, 1.18,
'"Floating knee" describes the flail knee joint segment resulting from concurrent '
'fractures of the ipsilateral femoral and tibial shafts or adjacent metaphyses, '
'leaving the knee segment without bony continuity to either the trunk or the foot.',
sz=16, italic=True, color=WHITE, wrap=True)
# 3 columns
col_card(s, 0.35, 2.72, 4.0, 4.45, "Epidemiology", MED_BLUE, [
"Uncommon but high-morbidity injury",
"Adults: high-energy road traffic accidents",
"Children: motor vehicle–pedestrian injury",
"Male predominance",
"Mean age: 3rd–4th decade (adults)",
"21% associated vascular injury",
"62% open fracture rate",
"Knee ligament instability: ~30% of cases",
])
col_card(s, 4.52, 2.72, 4.0, 4.45, "Mechanism of Injury", ORANGE, [
"High-energy trauma (RTA most common)",
"Axial compressive + rotational forces",
"Motorcycle accidents",
"Pedestrian vs vehicle",
"Fall from height",
"Gunshot wounds",
"Polytrauma is the rule, not the exception",
"Multiple associated injuries expected",
])
col_card(s, 8.70, 2.72, 4.30, 4.45, "Associated Injuries", RED, [
"Popliteal artery injury",
"Peroneal nerve injury",
"Compartment syndrome",
"Ligamentous instability of knee (ACL/PCL/MCL)",
"Head injury (esp. in children)",
"Pelvic fractures",
"Chest / abdominal injuries",
"Skin & soft tissue loss (open fx)",
])
# ══════════════════════════════════════════════════════════════════════
# SLIDE 3 — Classification (Fraser Adult + Letts Paediatric)
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr_bar(s, "CLASSIFICATION",
"Fraser (Adults) | Letts et al. (Paediatric)")
# Fraser
rect(s, 0.35, 1.28, 6.30, 5.9, WHITE)
rect(s, 0.35, 1.28, 6.30, 0.52, MED_BLUE)
tb(s, 0.48, 1.31, 6.0, 0.48,
"FRASER CLASSIFICATION (Adults)", sz=16, bold=True, color=WHITE)
fraser = [
("Type I", GREEN, "Both fractures involve the DIAPHYSIS (shafts only)\n"
"→ Femoral shaft + Tibial shaft\n"
"→ Closed fractures; best prognosis"),
("Type IIA", ORANGE, "Either fracture extends into the KNEE JOINT\n"
"→ Intra-articular involvement\n"
"→ Risk factor for poor outcome"),
("Type IIB", RED, "Either fracture extends into HIP or ANKLE joint\n"
"→ Supracondylar femur / proximal tibia involvement\n"
"→ Most complex; worst prognosis"),
]
fy = 1.88
for label, col, desc in fraser:
rect(s, 0.42, fy, 1.15, 1.55, col)
tb(s, 0.45, fy+0.45, 1.08, 0.7, label, sz=18, bold=True,
color=WHITE, align=PP_ALIGN.CENTER)
rect(s, 1.60, fy, 4.80, 1.55, RGBColor(0xF5, 0xF9, 0xFF))
tb(s, 1.70, fy+0.12, 4.65, 1.38, desc, sz=13.5, color=TEXT_DARK, wrap=True)
fy += 1.68
# Letts
rect(s, 7.00, 1.28, 6.00, 5.9, WHITE)
rect(s, 7.00, 1.28, 6.00, 0.52, GREEN)
tb(s, 7.13, 1.31, 5.70, 0.48,
"LETTS CLASSIFICATION (Paediatric)", sz=16, bold=True, color=WHITE)
letts = [
("Type A", MED_BLUE,
"Both fractures CLOSED DIAPHYSEAL\n→ Best prognosis"),
("Type B", GREEN,
"One diaphyseal + one METAPHYSEAL;\nboth CLOSED"),
("Type C", ORANGE,
"One diaphyseal + one EPIPHYSEAL\ndisplacement (physeal injury)"),
("Type D", RED,
"One OPEN fracture with major\nsoft-tissue injury"),
("Type E", RGBColor(0x7B,0x00,0x00),
"BOTH fractures OPEN with major\nsoft-tissue injury; worst prognosis"),
]
ly = 1.88
for label, col, desc in letts:
rect(s, 7.07, ly, 1.05, 1.08, col)
tb(s, 7.09, ly+0.25, 1.00, 0.6, label, sz=15, bold=True,
color=WHITE, align=PP_ALIGN.CENTER)
rect(s, 8.15, ly, 4.65, 1.08, RGBColor(0xF5, 0xF9, 0xFF))
tb(s, 8.23, ly+0.08, 4.52, 0.95, desc, sz=13, color=TEXT_DARK, wrap=True)
ly += 1.14
# ══════════════════════════════════════════════════════════════════════
# SLIDE 4 — Clinical Evaluation & Investigations
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr_bar(s, "CLINICAL EVALUATION & INVESTIGATIONS")
col_card(s, 0.35, 1.28, 3.80, 5.95, "History", MED_BLUE, [
"High-energy mechanism (RTA, fall)",
"Time of injury (vascular urgency)",
"Loss of consciousness (head injury)",
"Bleeding / open wound",
"Pre-injury mobility",
"Tetanus immunisation status",
"Medications / allergies (polytrauma)",
], sz=14)
col_card(s, 4.30, 1.28, 4.35, 5.95, "Physical Examination", ORANGE, [
"ATLS primary survey first (ABCDE)",
"Inspect: swelling, deformity, open wounds, skin tenting",
"Palpate: crepitus, bony tenderness femur + tibia",
"Neurovascular exam: dorsalis pedis, posterior tibial pulses",
"ABI (Ankle-Brachial Index): if <0.9 → vascular injury",
"Compartment pressure monitoring",
"Examine hip & ankle (associated injuries)",
"Knee: document ligament laxity (post-stabilisation)",
"Log roll: spine evaluation",
], sz=13)
col_card(s, 8.80, 1.28, 4.15, 5.95, "Investigations", GREEN, [
"X-RAYS (mandatory):",
" • AP + lateral femur (full length)",
" • AP + lateral tibia–fibula",
" • AP pelvis, hip, knee, ankle",
"CT SCAN:",
" • Intra-articular extension (plateau/condyle)",
" • Preop planning for complex fractures",
"CT ANGIOGRAPHY / DOPPLER:",
" • Suspected popliteal / SFA injury",
" • ABI <0.9",
"MRI KNEE:",
" • Ligamentous / meniscal injury (after stabilisation)",
"LABS:",
" • FBC, GXM, coagulation, metabolic panel",
], sz=12.5)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 5 — Management Principles & Algorithm
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr_bar(s, "MANAGEMENT PRINCIPLES & ALGORITHM")
# Guiding Principles box
rect(s, 0.35, 1.28, 12.65, 0.85, RGBColor(0x0A, 0x3C, 0x6E))
tb(s, 0.50, 1.32, 12.40, 0.76,
"Principle: Stabilise the patient (ATLS) → Address vascular injury → Fix BOTH fractures → "
"Manage soft tissue → Definitive ligament/cartilage management",
sz=14.5, bold=True, color=WHITE, wrap=True)
# Algorithm boxes (cascade)
steps = [
("STEP 1: ATLS Resuscitation", DARK, [
"Primary survey, airway, breathing, circulation",
"Control haemorrhage (tourniquet / wound packing)",
"Assess GCS; CT head if altered consciousness",
"Damage control resuscitation (massive transfusion protocol if needed)",
]),
("STEP 2: Vascular Assessment", RED, [
"Palpate + Doppler all lower limb pulses",
"ABI < 0.9 → CT angiography / formal angiography",
"Hard signs of injury (absent pulse, expanding haematoma, bruit) → immediate OR",
"Vascular repair BEFORE fracture fixation if limb ischaemia",
]),
("STEP 3: Temporary Stabilisation", ORANGE, [
"External fixation (spanning the knee) = Damage Control Orthopaedics",
"Indicated: open #, severe soft-tissue injury, haemodynamically unstable patient",
"Restore length and alignment; protect soft tissues",
"Convert to definitive fixation at 5–14 days when patient stable",
]),
("STEP 4: Definitive Fixation", GREEN, [
"Retrograde femoral IM nail + Antegrade tibial IM nail (preferred adult)",
"Same anterior incision for both nails (reduces operative time)",
"ORIF with plates for metaphyseal / intra-articular extension",
"Physiological prioritisation: tibia first vs femur first per surgeon preference",
]),
]
sy = 2.22
for title, col, items in steps:
rect(s, 0.35, sy, 2.40, 1.18, col)
tb(s, 0.42, sy+0.28, 2.24, 0.70, title, sz=12.5, bold=True,
color=WHITE, align=PP_ALIGN.CENTER, wrap=True)
bullets(s, 2.82, sy+0.04, 10.20, 1.06, items, sz=13.5)
# connector arrow
if col != GREEN:
arr = s.shapes.add_shape(13, Inches(1.2), Inches(sy+1.18), Inches(0.20), Inches(0.15))
arr.line.fill.background(); arr.fill.solid()
arr.fill.fore_color.rgb = ACCENT
sy += 1.33
# ══════════════════════════════════════════════════════════════════════
# SLIDE 6 — Surgical Fixation Options (Detailed)
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr_bar(s, "SURGICAL FIXATION — OPTIONS & DECISION MAKING")
options = [
("Retrograde Femoral Nail\n(Preferred for Femur)", MED_BLUE, [
"Entry: intercondylar notch (anterior to PCL)",
"Advantage: same incision as tibial nail",
"Allows fixation without fracture table",
"Better control of DISTAL shaft fractures",
"Complications: knee pain (36%), knee sepsis (1.1%)",
"Caution: supracondylar #s → lower union rate (80–84%)",
"Preferred in floating knee, obesity, pregnancy, bilateral femur #",
]),
("Antegrade Tibial IM Nail\n(Standard for Tibia)", GREEN, [
"Entry: patellar tendon / suprapatellar approach",
"Statically locked nail for most diaphyseal fractures",
"Better control of PROXIMAL tibial fractures",
"Complications: anterior knee pain, malrotation",
"Good to excellent results in type I floating knee",
"Poor outcome if intra-articular tibia extension (Type IIA)",
]),
("External Fixation\n(Damage Control)", ORANGE, [
"Spanning knee frame (femur pin + tibial pin)",
"Used for: open #, haemodynamic instability, vascular injury",
"Temporary: convert to IM nailing at 5–14 days",
"Used by Campbell's for 'open fractures with major soft-tissue injury'",
"Caution: pin-track infection, joint stiffness",
"Can be definitive in children < 10 years with closed fractures",
]),
("ORIF with Plates", RED, [
"Indicated: metaphyseal/articular fractures",
"Intra-articular femur (distal femur ORIF + tibial nail)",
"Tibial plateau extension (ORIF plateau + femoral nail)",
"Periarticular locking plates preferred",
"Higher infection risk vs. IM nailing",
"Good option when IM nailing technically difficult",
]),
]
px = [0.35, 3.52, 6.70, 9.87]
for i, (title, col, items) in enumerate(options):
rect(s, px[i], 1.28, 3.05, 5.95, WHITE)
rect(s, px[i], 1.28, 3.05, 0.72, col)
tb(s, px[i]+0.10, 1.32, 2.83, 0.66, title, sz=13.5, bold=True, color=WHITE, wrap=True)
bullets(s, px[i]+0.10, 2.07, 2.85, 5.05, items, sz=12.5)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 7 — Paediatric Floating Knee
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr_bar(s, "PAEDIATRIC FLOATING KNEE",
"Special Considerations — Letts Classification | Age-Based Management")
# Left
col_card(s, 0.35, 1.28, 6.10, 5.95, "Clinical Features & Epidemiology", MED_BLUE, [
"Most often from motor vehicle–pedestrian accidents",
"Associated: major soft-tissue damage, open fractures, head injuries",
"Letts et al. 5-type classification (A–E)",
"At least ONE fracture should be rigidly fixed by ORIF",
"In older children: intramedullary nailing > plate fixation",
"Multicenter study (n=130, mean age 10.2 yrs):",
" → 93% good-to-excellent results with modern fixation",
" → Shorter length of stay than historically reported",
"Poor results historically up to 50% in older children:",
" → Limb-length discrepancy",
" → Angular deformity",
" → Knee instability (especially ligamentous)",
"Physeal injuries (Type C/D/E) worsen prognosis significantly",
], sz=13)
# Right
col_card(s, 6.70, 1.28, 6.30, 5.95, "Age-Based Treatment Strategy", GREEN, [
"< 10 YEARS (younger children):",
" • Closed fractures: nonoperative treatment often successful",
" • Traction + casting for low-energy diaphyseal fractures",
" • ORIF if open fracture or displaced physeal injury",
"",
"> 10 YEARS (older children/adolescents):",
" • Nonoperative treatment → frequent complications",
" • Intramedullary nailing preferred over plates",
" • Allows faster mobilisation",
" • Flexible nails for younger children (physis at risk)",
"",
"OPEN FRACTURES (Type D/E):",
" • External fixation as temporising measure",
" • Definitive fixation after soft-tissue coverage",
" • Wound debridement + washout urgently",
"",
"KEY PRINCIPLE: At least one fracture must be rigidly fixed",
], sz=13)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 8 — Complications
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr_bar(s, "COMPLICATIONS")
comps = [
("Vascular Injury\n(21%)", RED, [
"Popliteal artery most at risk",
"Hard signs: absent pulse, expanding haematoma",
"Soft signs: ABI < 0.9, asymmetric Doppler",
"Management: CT angiography → vascular repair",
"Limb loss risk if delay > 6 hours",
"Fasciotomy mandatory post-repair",
]),
("Compartment\nSyndrome", ORANGE, [
"Elevated intracompartmental pressure",
"Classical 6 Ps: Pain, Pallor, Paraesthesia,\nParalysis, Pulselessness, Pressure",
"Pressure > 30 mmHg or within 30 mmHg of diastolic",
"Management: Emergency 4-compartment fasciotomy",
"Higher risk in tibial fractures",
]),
("Knee Ligament\nInstability (~30%)", PURPLE, [
"ACL, PCL, MCL, LCL injuries",
"Often missed acutely (pain + swelling mask laxity)",
"Evaluate AFTER fracture stabilisation",
"EUA under anaesthesia during nail insertion",
"MRI knee once stabilised",
"Repair/reconstruct ligaments 3–6 weeks post-fixation",
]),
("Non-union /\nMalunion", MED_BLUE, [
"Segmental femoral fragment: avascularity risk",
"Malrotation: assess clinically + CT",
"Limb length discrepancy (LLD)",
"Management: exchange nail, ORIF + ICBG",
"Type IIA (intra-articular) → higher nonunion",
]),
("Fat Embolism\nSyndrome", RGBColor(0x00,0x6B,0x8A), [
"More common with multiple long-bone fractures",
"Triad: hypoxia, petechiae, confusion",
"ARDS can develop",
"Supportive treatment (ICU, respiratory support)",
"Early fracture stabilisation reduces risk",
]),
("Infection &\nOsteomyelitis", RGBColor(0x5A,0x17,0x00), [
"Higher risk in open fractures (Types D/E)",
"Pin-track infection with external fixation",
"Deep infection post-ORIF",
"Management: debridement, antibiotics, staged procedure",
"Closed fracture infection < 5%",
]),
]
px = [0.35, 4.55, 8.75]
py = [1.28, 4.42]
for i, (title, col, items) in enumerate(comps):
x = px[i % 3]
y = py[i // 3]
rect(s, x, y, 3.95, 2.95, WHITE)
rect(s, x, y, 3.95, 0.62, col)
tb(s, x+0.10, y+0.08, 3.73, 0.54, title, sz=14, bold=True, color=WHITE, wrap=True)
bullets(s, x+0.10, y+0.70, 3.73, 2.12, items, sz=12.5)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 9 — Outcomes & Prognosis
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr_bar(s, "OUTCOMES & PROGNOSIS")
# Key data strip
rect(s, 0.35, 1.28, 12.65, 0.85, MED_BLUE)
tb(s, 0.50, 1.33, 12.40, 0.76,
"Both fractures treated with IM nailing → Good to Excellent results achievable | "
"Type IIA (intra-articular) & severe open tibia → Risk factors for poor outcome | "
"Paediatric series: 93% good/excellent with modern fixation (Campbell's 15e)",
sz=14, bold=True, color=WHITE, wrap=True)
col_card(s, 0.35, 2.22, 4.10, 5.05, "Favourable Prognostic Factors", GREEN, [
"Type I (diaphyseal only, closed)",
"Early definitive fixation (both fractures)",
"No intra-articular involvement",
"No vascular injury",
"Age < 10 years in paediatric group",
"Both fractures stabilised with IM nails",
"Good soft tissue coverage",
"Absence of compartment syndrome",
"No major head injury",
], sz=13.5)
col_card(s, 4.60, 2.22, 4.35, 5.05, "Poor Prognostic Factors", RED, [
"Type IIA — intra-articular knee involvement",
"Type IIB — hip/ankle joint extension",
"Severe open tibia fracture (Gustilo IIIB/IIIC)",
"Associated popliteal artery injury",
"Delay in vascular repair > 6 hours",
"Compartment syndrome with delay",
"Missed ligamentous instability",
"Paediatric age > 10 years (historically)",
"Soft tissue loss requiring flap coverage",
], sz=13.5)
col_card(s, 9.10, 2.22, 3.88, 5.05, "Long-term Sequelae", ORANGE, [
"Knee stiffness / restricted ROM",
"Post-traumatic osteoarthritis",
"Ligamentous instability",
"Limb-length discrepancy",
"Angular deformity (malunion)",
"Chronic regional pain",
"Muscle weakness / wasting",
"DVT / pulmonary embolism",
"Need for secondary surgery",
], sz=13.5)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 10 — Exam High-Yield Summary
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, DARK)
rect(s, 0, 1.38, 13.333, 0.12, ACCENT)
tb(s, 0.38, 0.15, 12.6, 1.08,
"HIGH-YIELD EXAM SUMMARY — FLOATING KNEE",
sz=30, bold=True, color=WHITE)
panels = [
("Definition (Write First)", MED_BLUE, [
"Ipsilateral fractures of femur + tibia",
"Knee segment without bony continuity",
'"Floating" = flail, unstable knee segment',
"High-energy injury; polytrauma common",
]),
("Classifications (Must Know)", ACCENT, [
"Fraser (Adults): I, IIA, IIB",
"Letts (Paediatric): A, B, C, D, E",
"Type I / A = diaphyseal, closed = best prognosis",
"Type IIA = intra-articular knee = poor prognosis",
]),
("Key Stats for Essays", ORANGE, [
"Vascular injury rate: 21%",
"Open fracture rate: 62%",
"Knee ligament injury: ~30%",
"Paediatric good/excellent: 93% (modern fixation)",
]),
("Management Mantra", GREEN, [
"1. ATLS → 2. Vascular → 3. Ex-Fix (damage control)",
"4. Retrograde femoral nail + Antegrade tibial nail",
"Same anterior incision for both nails",
"EUA knee ligaments after fracture stabilisation",
]),
("Complications (VASCULAR FIRST)", RED, [
"Popliteal artery injury → emergency",
"Compartment syndrome → 4-compartment fasciotomy",
"Knee instability, non-union, mal-union",
"Fat embolism / ARDS in polytrauma",
]),
("Key Points to Conclude", RGBColor(0x6B,0x2F,0x96), [
"Fix BOTH fractures; IM nailing = gold standard",
"Type IIA + severe open tibia = poor outcome",
"Never miss vascular injury",
"Ligament assessment post-stabilisation essential",
]),
]
px = [0.35, 4.55, 8.75]
py = [1.58, 4.42]
for i, (title, col, items) in enumerate(panels):
x = px[i % 3]; y = py[i // 3]
rect(s, x, y, 3.95, 2.72, RGBColor(0x0C, 0x1C, 0x2E))
rect(s, x, y, 3.95, 0.52, col)
tb(s, x+0.10, y+0.06, 3.73, 0.44, title, sz=13.5, bold=True, color=WHITE)
bullets(s, x+0.10, y+0.58, 3.73, 2.05, items, sz=13,
color=RGBColor(0xD0, 0xE8, 0xFF))
# References
rect(s, 0, 7.08, 13.333, 0.42, RGBColor(0x06, 0x12, 0x22))
tb(s, 0.35, 7.10, 12.6, 0.38,
"References: Campbell's Operative Orthopaedics 15e (2026) | "
"Rockwood & Green's Fractures in Adults 10e (2025) | "
"Miller's Review of Orthopaedics 9e | Letts et al. Classification | Fraser Classification",
sz=10, italic=True, color=RGBColor(0x70, 0x90, 0xB0), align=PP_ALIGN.CENTER)
# ── Save ─────────────────────────────────────────────────────────────
out = "/tmp/workspace/floating-knee-ppt/Floating_Knee.pptx"
buf = BytesIO()
prs.save(buf)
with open(out, "wb") as f:
f.write(buf.getvalue())
print(f"Saved → {out}")
cd /tmp/workspace/floating-knee-ppt && python build_fk.py 2>&1
~/floating-knee-ppt/build_fk.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/floating-knee-ppt/build_fk.py'
cd /tmp/workspace/floating-knee-ppt && python build_fk.py 2>&1
python -c " from pptx import Presentation prs = Presentation('/tmp/workspace/floating-knee-ppt/Floating_Knee.pptx') print(f'Total slides: {len(prs.slides)}') for i, slide in enumerate(prs.slides, 1): texts = [s.text_frame.text.strip()[:70] for s in slide.shapes if s.has_text_frame and s.text_frame.text.strip()] print(f' Slide {i}: {texts[0] if texts else \"[no text]\"}') "
Floating Knee
Presentation · PPTX
| Slide | Content |
|---|---|
| 1 | Title slide |
| 2 | Definition, Epidemiology & Mechanism (vascular injury 21%, open # 62%, ligament instability 30%) |
| 3 | Fraser Classification (Type I, IIA, IIB) + Letts Classification (Types A–E, Paediatric) |
| 4 | Clinical Evaluation & Investigations (ATLS, ABI, X-rays, CT angio, MRI knee) |
| 5 | Management Algorithm (4 steps: ATLS → Vascular → Damage Control Ex-Fix → Definitive Fixation) |
| 6 | Surgical Options — Retrograde femoral nail, Antegrade tibial nail, Ex-Fix, ORIF plates |
| 7 | Paediatric Floating Knee (age-based strategy, Letts, 93% good/excellent with modern fixation) |
| 8 | Complications (6 panels: vascular, compartment syndrome, ligament instability, nonunion, fat embolism, infection) |
| 9 | Outcomes & Prognosis (good vs poor prognostic factors, long-term sequelae) |
| 10 | High-Yield Exam Summary (definition, classifications, key stats, management mantra, complications) |
Generate a PDF summary sheet for last-minute revision
~/floating-knee-ppt/build_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm, cm
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.colors import HexColor
OUT = "/tmp/workspace/floating-knee-ppt/Floating_Knee_Revision.pdf"
# ── Colours ──────────────────────────────────────────────────────────
C_NAVY = HexColor("#0B243B")
C_BLUE = HexColor("#155EA6")
C_ACCENT = HexColor("#00B0D8")
C_GREEN = HexColor("#059668")
C_ORANGE = HexColor("#E07B10")
C_RED = HexColor("#BF2828")
C_PURPLE = HexColor("#6B2F96")
C_LIGHT = HexColor("#EEF4FF")
C_PALE_GRN = HexColor("#E8FAF3")
C_PALE_ORG = HexColor("#FEF3E2")
C_PALE_RED = HexColor("#FDEAEA")
C_PALE_PUR = HexColor("#F3EBF9")
C_PALE_BLU = HexColor("#EAF3FF")
C_WHITE = colors.white
C_BLACK = colors.black
C_DGREY = HexColor("#2C3E50")
C_LGREY = HexColor("#F5F7FA")
C_STRIPE = HexColor("#D6E8F8")
PAGE_W, PAGE_H = A4
MARGIN = 14 * mm
doc = SimpleDocTemplate(
OUT,
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=12*mm, bottomMargin=12*mm,
title="Floating Knee – Last-Minute Revision",
author="Orris Medical"
)
# ── Styles ────────────────────────────────────────────────────────────
def S(name, **kw):
return ParagraphStyle(name, **kw)
BODY_W = PAGE_W - 2 * MARGIN
s_title = S("title", fontName="Helvetica-Bold", fontSize=18,
textColor=C_WHITE, leading=22, alignment=TA_CENTER)
s_sub = S("sub", fontName="Helvetica-Oblique", fontSize=9,
textColor=HexColor("#8ABEE0"), leading=12, alignment=TA_CENTER)
s_sh = S("sh", fontName="Helvetica-Bold", fontSize=9,
textColor=C_WHITE, leading=11, spaceAfter=1)
s_body = S("body", fontName="Helvetica", fontSize=8,
textColor=C_DGREY, leading=11, spaceAfter=1)
s_bold = S("bold", fontName="Helvetica-Bold", fontSize=8,
textColor=C_DGREY, leading=11, spaceAfter=1)
s_small = S("small", fontName="Helvetica", fontSize=7.2,
textColor=C_DGREY, leading=10, spaceAfter=1)
s_bul = S("bul", fontName="Helvetica", fontSize=8,
textColor=C_DGREY, leading=11, leftIndent=6, spaceAfter=0)
s_bul_b = S("bul_b", fontName="Helvetica-Bold", fontSize=8,
textColor=C_DGREY, leading=11, leftIndent=6, spaceAfter=0)
s_key = S("key", fontName="Helvetica-Bold", fontSize=7.5,
textColor=C_WHITE, leading=10, alignment=TA_CENTER)
s_note = S("note", fontName="Helvetica-Oblique", fontSize=7,
textColor=HexColor("#555555"), leading=9, alignment=TA_CENTER)
def P(txt, style=None): return Paragraph(txt, style or s_body)
def B(txt, bullet="•"): return Paragraph(f"{bullet} {txt}", s_bul)
def BB(txt, bullet="▸"): return Paragraph(f"<b>{bullet} {txt}</b>", s_bul_b)
def SP(h=2): return Spacer(1, h*mm)
def HR(c=C_ACCENT, w=0.6): return HRFlowable(width="100%", thickness=w, color=c, spaceAfter=2)
# ── Helpers ───────────────────────────────────────────────────────────
def section_header(text, bg=C_BLUE, fg=C_WHITE):
data = [[Paragraph(text, S("x", fontName="Helvetica-Bold", fontSize=10,
textColor=fg, leading=13))]]
t = Table(data, colWidths=[BODY_W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("ROUNDEDCORNERS", [3]),
]))
return t
def mini_header(text, bg=C_BLUE):
data = [[Paragraph(text, s_sh)]]
t = Table(data, colWidths=[BODY_W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 6),
]))
return t
def key_box(label, value, bg=C_PALE_BLU, lbg=C_BLUE):
"""Small coloured KPI box."""
data = [
[Paragraph(label, S("kl", fontName="Helvetica-Bold", fontSize=7,
textColor=C_WHITE, leading=9, alignment=TA_CENTER))],
[Paragraph(value, S("kv", fontName="Helvetica-Bold", fontSize=13,
textColor=C_NAVY, leading=16, alignment=TA_CENTER))],
]
t = Table(data, colWidths=[None])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), lbg),
("BACKGROUND", (0,1),(0,1), bg),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("BOX", (0,0),(-1,-1), 0.5, C_BLUE),
]))
return t
def two_col(left_items, right_items, left_hdr=None, right_hdr=None,
lbg=C_BLUE, rbg=C_GREEN):
"""Two-column card."""
cw = (BODY_W - 3*mm) / 2
def make_col(hdr, items, hbg):
rows = []
if hdr:
rows.append([Paragraph(hdr, S("ch", fontName="Helvetica-Bold", fontSize=8.5,
textColor=C_WHITE, leading=11))])
for it in items:
rows.append([Paragraph(f"• {it}", s_small)])
t = Table(rows, colWidths=[cw])
ts = [
("TOPPADDING", (0,0),(-1,-1), 2),
("BOTTOMPADDING", (0,0),(-1,-1), 2),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 3),
("BOX", (0,0),(-1,-1), 0.4, hbg),
]
if hdr:
ts.append(("BACKGROUND", (0,0),(0,0), hbg))
t.setStyle(TableStyle(ts))
return t
outer = Table([[make_col(left_hdr, left_items, lbg),
make_col(right_hdr, right_items, rbg)]],
colWidths=[cw, cw], hAlign="LEFT")
outer.setStyle(TableStyle([
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 0),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING",(0,0),(-1,-1), 0),
("VALIGN", (0,0),(-1,-1), "TOP"),
("INNERGRID", (0,0),(-1,-1), 2, C_WHITE),
]))
return outer
# ─────────────────────────────────────────────────────────────────────
story = []
# ══ TITLE BANNER ═════════════════════════════════════════════════════
title_data = [
[Paragraph("FLOATING KNEE INJURY", s_title)],
[Paragraph("Last-Minute Revision Sheet | PG Orthopaedics Essay Exam", s_sub)],
[Paragraph("Sources: Campbell's Operative Orthopaedics 15e (2026) · Rockwood & Green's Fractures 10e (2025) · Miller's Review 9e", s_note)],
]
tt = Table(title_data, colWidths=[BODY_W])
tt.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), C_NAVY),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("ROUNDEDCORNERS", [4]),
]))
story.append(tt)
story.append(SP(3))
# ══ KEY STATISTICS ROW ═══════════════════════════════════════════════
story.append(section_header("⚡ KEY STATISTICS (Quote These in Essays)", bg=C_NAVY))
story.append(SP(2))
kw = BODY_W / 5 - 1.5*mm
kpi_data = [[
key_box("Vascular Injury", "21%", C_PALE_RED, C_RED),
key_box("Open Fracture Rate", "62%", C_PALE_ORG, C_ORANGE),
key_box("Knee Ligament\nInstability", "~30%", C_PALE_PUR, C_PURPLE),
key_box("Good/Excellent Results\n(modern fixation)", "93%", C_PALE_GRN, C_GREEN),
key_box("Paediatric Series\n(mean age)", "10.2 yrs", C_PALE_BLU, C_BLUE),
]]
kt = Table(kpi_data, colWidths=[kw]*5)
kt.setStyle(TableStyle([
("LEFTPADDING", (0,0),(-1,-1), 2),
("RIGHTPADDING", (0,0),(-1,-1), 2),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING",(0,0),(-1,-1), 0),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(kt)
story.append(SP(3))
HR()
# ══ DEFINITION ═══════════════════════════════════════════════════════
story.append(section_header("1. DEFINITION", bg=C_BLUE))
story.append(SP(1))
def_data = [[Paragraph(
'<b>"Floating Knee"</b> = Flail knee joint segment from <b>concurrent fractures of the '
'ipsilateral femoral and tibial shafts (or adjacent metaphyses)</b>, leaving the knee '
'without bony continuity to either the trunk or foot. High-energy injury; polytrauma is the rule.',
S("defn", fontName="Helvetica", fontSize=8.5, textColor=C_NAVY,
leading=12, leftIndent=4, rightIndent=4))]]
dt = Table(def_data, colWidths=[BODY_W])
dt.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), C_LIGHT),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
("BOX", (0,0),(-1,-1), 1, C_BLUE),
("ROUNDEDCORNERS", [4]),
]))
story.append(dt)
story.append(SP(3))
# ══ CLASSIFICATION ═══════════════════════════════════════════════════
story.append(section_header("2. CLASSIFICATION", bg=C_BLUE))
story.append(SP(2))
# Fraser + Letts side by side
fraser_rows = [
[Paragraph("<b>FRASER CLASSIFICATION (Adults)</b>",
S("fh", fontName="Helvetica-Bold", fontSize=8.5,
textColor=C_WHITE, leading=11))],
[Paragraph("<b>Type I</b> – Both fractures involve the <b>DIAPHYSIS</b> (shafts, closed)\n"
"→ Best prognosis; both IM nails", s_small)],
[Paragraph("<b>Type IIA</b> – Either fracture extends into the <b>KNEE JOINT</b>\n"
"→ Intra-articular involvement; risk factor for poor outcome", s_small)],
[Paragraph("<b>Type IIB</b> – Either fracture extends into <b>HIP or ANKLE</b>\n"
"→ Supracondylar / proximal tibia; most complex", s_small)],
]
letts_rows = [
[Paragraph("<b>LETTS CLASSIFICATION (Paediatric)</b>",
S("lh", fontName="Helvetica-Bold", fontSize=8.5,
textColor=C_WHITE, leading=11))],
[Paragraph("<b>Type A</b> – Both fractures closed diaphyseal (best prognosis)", s_small)],
[Paragraph("<b>Type B</b> – One diaphyseal + one metaphyseal; both closed", s_small)],
[Paragraph("<b>Type C</b> – One diaphyseal + one epiphyseal displacement", s_small)],
[Paragraph("<b>Type D</b> – One open with major soft-tissue injury", s_small)],
[Paragraph("<b>Type E</b> – Both open with major soft-tissue injury (worst)", s_small)],
]
cw2 = (BODY_W - 3*mm) / 2
def make_class_table(rows, hbg):
t = Table(rows, colWidths=[cw2])
ts = [
("BACKGROUND", (0,0),(0,0), hbg),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("BOX", (0,0),(-1,-1), 0.5, hbg),
("LINEBELOW",(0,0),(0,0), 0.5, hbg),
]
for i in range(1, len(rows)):
bg = C_PALE_BLU if i % 2 == 1 else C_WHITE
ts.append(("BACKGROUND", (0,i),(0,i), bg))
t.setStyle(TableStyle(ts))
return t
ct = Table([[make_class_table(fraser_rows, C_BLUE),
make_class_table(letts_rows, C_GREEN)]],
colWidths=[cw2, cw2])
ct.setStyle(TableStyle([
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 0),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING",(0,0),(-1,-1), 0),
("VALIGN", (0,0),(-1,-1), "TOP"),
("INNERGRID", (0,0),(-1,-1), 2.5, C_WHITE),
]))
story.append(ct)
story.append(SP(3))
# ══ MECHANISM & ASSOCIATIONS ═════════════════════════════════════════
story.append(section_header("3. MECHANISM & ASSOCIATED INJURIES", bg=C_BLUE))
story.append(SP(2))
story.append(two_col(
["High-energy RTA (most common)", "Motorcycle accidents",
"Pedestrian vs vehicle", "Fall from height", "Gunshot wounds"],
["Popliteal artery injury (21%)", "Compartment syndrome",
"ACL/PCL/MCL instability (~30%)", "Head injury (esp. paediatric)",
"Pelvic / chest / abdominal injuries", "Open fracture (62%)"],
left_hdr="Mechanism", right_hdr="Associated Injuries",
lbg=C_ORANGE, rbg=C_RED,
))
story.append(SP(3))
# ══ MANAGEMENT ALGORITHM ═════════════════════════════════════════════
story.append(section_header("4. MANAGEMENT ALGORITHM (Write in This Order)", bg=C_BLUE))
story.append(SP(2))
algo_rows = [
["STEP", "ACTION", "KEY POINTS"],
["1", "ATLS Resuscitation",
"Primary survey · Haemorrhage control · Tourniquet if limb-threatening bleed · GCS / head injury"],
["2", "Vascular Assessment",
"Palpate pulses · ABI (< 0.9 = abnormal) · CT angiography · Hard signs → immediate OR · Repair BEFORE fixation if ischaemic"],
["3", "Temporary Stabilisation\n(Damage Control)",
"Spanning external fixator across knee · Indicated: open #, haemodynamic instability · Convert to IM nail at 5–14 days"],
["4", "Definitive Fixation",
"Retrograde femoral IM nail + Antegrade tibial IM nail · Same anterior incision · Both fractures fixed · EUA knee ligaments during same anaesthetic"],
["5", "Soft Tissue / Ligaments",
"Debridement & coverage of open wounds · MRI knee once stable · Ligament repair/reconstruction 3–6 weeks post-fixation"],
]
algo_t = Table(algo_rows, colWidths=[10*mm, 42*mm, BODY_W-52*mm])
algo_style = [
("BACKGROUND", (0,0),(-1,0), C_NAVY),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 8),
("ALIGN", (0,0),(0,-1), "CENTER"),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("FONTNAME", (0,1),(-1,-1), "Helvetica"),
("FONTSIZE", (0,1),(-1,-1), 7.5),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#B0C8E0")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_PALE_BLU, C_WHITE]),
("FONTNAME", (0,1),(1,-1), "Helvetica-Bold"),
("BACKGROUND", (0,2),(1,2), HexColor("#FDEAEA")),
("FONTNAME", (0,2),(1,2), "Helvetica-Bold"),
("TEXTCOLOR", (0,2),(1,2), C_RED),
]
# highlight step 2 (vascular) row in red tint
algo_t.setStyle(TableStyle(algo_style))
story.append(algo_t)
story.append(SP(3))
# ══ SURGICAL FIXATION ════════════════════════════════════════════════
story.append(section_header("5. SURGICAL FIXATION OPTIONS", bg=C_BLUE))
story.append(SP(2))
fix_rows = [
["Method", "Indication", "Notes / Complications"],
["Retrograde\nFemoral IM Nail\n(Preferred)", "Floating knee, obesity, pregnancy, bilateral femur #",
"Entry: intercondylar notch · Same incision as tibial nail · Knee pain 36% · Knee sepsis 1.1% · Supracondylar union rate 80–84%"],
["Antegrade\nTibial IM Nail\n(Standard)", "Tibial shaft fractures (diaphyseal)",
"Standard for tibial shaft · Complications: ant. knee pain, malrotation · Poor if intra-articular extension"],
["Spanning\nExternal Fixator\n(Damage Control)", "Open #, haemodynamic instability, vascular injury",
"Temporary → convert to nail 5–14 days · Definitive in paediatric < 10 yrs (closed #)"],
["ORIF Plates", "Metaphyseal / intra-articular fractures",
"Periarticular locking plates · Higher infection risk · Used when IM nailing not feasible"],
]
fix_t = Table(fix_rows, colWidths=[28*mm, 52*mm, BODY_W-80*mm])
fix_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_NAVY),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 8),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("FONTNAME", (0,1),(-1,-1), "Helvetica"),
("FONTSIZE", (0,1),(-1,-1), 7.5),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#B0C8E0")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_PALE_BLU, C_WHITE]),
("FONTNAME", (0,1),(0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1),(0,1), C_BLUE),
("TEXTCOLOR", (0,3),(0,3), C_ORANGE),
]))
story.append(fix_t)
story.append(SP(3))
# ══ COMPLICATIONS ════════════════════════════════════════════════════
story.append(section_header("6. COMPLICATIONS (Must List in Essays)", bg=C_BLUE))
story.append(SP(2))
comp_rows = [
["COMPLICATION", "RATE / NOTES", "MANAGEMENT"],
["⚡ Popliteal Artery Injury", "21% of floating knees",
"CT angio · Repair BEFORE fixation · Fasciotomy post-repair · Limb loss if > 6 hrs delay"],
["Compartment Syndrome", "Highest risk in tibial fractures",
"Monitor pressure · > 30 mmHg → 4-compartment fasciotomy"],
["Knee Ligament Instability", "~30% of cases",
"EUA after fixation · MRI · Repair/reconstruct at 3–6 wks"],
["Non-union / Malunion", "Higher in Type IIA (intra-articular)",
"Exchange nail / ORIF + ICBG · CT for rotation assessment"],
["Fat Embolism / ARDS", "Multiple long-bone fractures → higher risk",
"ICU / respiratory support · Early fixation reduces risk"],
["Infection", "Open # (Gustilo IIIB/C) highest risk",
"Debridement + IV antibiotics · Staged procedure"],
["DVT / PE", "All polytrauma patients",
"LMWH prophylaxis · Mechanical compression · Early mobilisation"],
["Knee Stiffness", "Esp. with distal external fixation",
"Early physiotherapy · CPM · Manipulation under anaesthesia"],
]
comp_t = Table(comp_rows, colWidths=[42*mm, 38*mm, BODY_W-80*mm])
comp_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_NAVY),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 8),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("FONTNAME", (0,1),(-1,-1), "Helvetica"),
("FONTSIZE", (0,1),(-1,-1), 7.5),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#B0C8E0")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_PALE_RED, C_WHITE]),
("FONTNAME", (0,1),(0,1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1),(0,1), C_RED),
("FONTNAME", (0,1),(0,-1), "Helvetica-Bold"),
]))
story.append(comp_t)
story.append(SP(3))
# ══ PROGNOSIS 2-col ══════════════════════════════════════════════════
story.append(section_header("7. PROGNOSIS", bg=C_BLUE))
story.append(SP(2))
story.append(two_col(
["Type I (diaphyseal, closed)",
"Both # fixed with IM nailing",
"No intra-articular involvement",
"No vascular injury",
"Age < 10 yrs (paediatric)",
"Early treatment (< 3–4 months)",
"Good soft-tissue coverage"],
["Type IIA – intra-articular knee",
"Severe open tibia (Gustilo IIIB/C)",
"Popliteal artery injury",
"Delay in vascular repair > 6 hrs",
"Compartment syndrome with delay",
"Missed ligament instability",
"Age > 10 yrs (paediatric, historical)"],
left_hdr="Good Prognosis", right_hdr="Poor Prognosis",
lbg=C_GREEN, rbg=C_RED,
))
story.append(SP(3))
# ══ PAEDIATRIC SPECIAL NOTE ═══════════════════════════════════════════
story.append(section_header("8. PAEDIATRIC FLOATING KNEE — SPECIAL NOTES", bg=C_NAVY))
story.append(SP(2))
ped_rows = [
["< 10 years, closed fractures", "Nonoperative (traction + cast) often successful",
"At least ONE fracture rigidly fixed if needed"],
["> 10 years", "Operative fixation preferred",
"IM nailing > plates; faster mobilisation"],
["Open fractures (Type D/E)", "External fixation → definitive after coverage",
"Debridement urgently"],
["Modern fixation (multicenter n=130)", "93% good/excellent results",
"Shorter length of stay than historical reports"],
["Historical poor results", "Up to 50% in older children",
"LLD, angular deformity, ligamentous instability"],
]
ped_t = Table(ped_rows, colWidths=[42*mm, 60*mm, BODY_W-102*mm])
ped_t.setStyle(TableStyle([
("FONTNAME", (0,0),(-1,-1), "Helvetica"),
("FONTSIZE", (0,0),(-1,-1), 7.5),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#B0C8E0")),
("ROWBACKGROUNDS",(0,0),(-1,-1), [C_PALE_BLU, C_WHITE]),
("FONTNAME", (0,0),(0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,3),(1,3), C_GREEN),
("FONTNAME", (0,3),(1,3), "Helvetica-Bold"),
]))
story.append(ped_t)
story.append(SP(3))
# ══ ESSAY ANSWER OUTLINE ══════════════════════════════════════════════
story.append(section_header("9. HOW TO STRUCTURE YOUR ESSAY ANSWER", bg=C_NAVY))
story.append(SP(2))
outline_data = [
[Paragraph("<b>PARA 1 — Definition</b>", s_bold),
Paragraph("State definition. Mention ipsilateral femur + tibia, flail knee, high-energy mechanism.", s_small)],
[Paragraph("<b>PARA 2 — Epidemiology</b>", s_bold),
Paragraph("Quote stats: 21% vascular injury, 62% open fracture, 30% ligament instability.", s_small)],
[Paragraph("<b>PARA 3 — Classification</b>", s_bold),
Paragraph("Fraser (I, IIA, IIB) for adults. Letts (A–E) for paediatric. Type IIA = worst adult prognosis.", s_small)],
[Paragraph("<b>PARA 4 — Clinical Features</b>", s_bold),
Paragraph("Deformity, swelling, angulation at both levels. Neurovascular exam mandatory. ATLS.", s_small)],
[Paragraph("<b>PARA 5 — Investigations</b>", s_bold),
Paragraph("Full-length X-rays femur + tibia. CT if intra-articular. CT angiography if ABI < 0.9. MRI post-stabilisation.", s_small)],
[Paragraph("<b>PARA 6 — Management</b>", s_bold),
Paragraph("Steps 1–5 (ATLS → Vascular → Ex-fix → Retrograde femoral + antegrade tibial nail → Ligaments).", s_small)],
[Paragraph("<b>PARA 7 — Complications</b>", s_bold),
Paragraph("Lead with vascular injury. Then: compartment syndrome, ligament instability, non-union, fat embolism.", s_small)],
[Paragraph("<b>PARA 8 — Prognosis</b>", s_bold),
Paragraph("93% good/excellent with modern fixation. Poor if Type IIA or severe open tibia.", s_small)],
]
ot = Table(outline_data, colWidths=[40*mm, BODY_W-40*mm])
ot.setStyle(TableStyle([
("FONTNAME", (0,0),(-1,-1), "Helvetica"),
("FONTSIZE", (0,0),(-1,-1), 7.8),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("GRID", (0,0),(-1,-1), 0.3, HexColor("#C0D8F0")),
("ROWBACKGROUNDS",(0,0),(-1,-1), [C_LIGHT, C_WHITE]),
("LINEAFTER", (0,0),(0,-1), 1.5, C_BLUE),
]))
story.append(ot)
story.append(SP(3))
# ══ MEMORY AIDS / MNEMONICS ═══════════════════════════════════════════
story.append(section_header("10. MEMORY AIDS", bg=C_NAVY))
story.append(SP(2))
mem_rows = [
[Paragraph("<b>Fraser Type I</b> → <b>I</b>solated diaphyseal shafts only (closed)",
s_small)],
[Paragraph("<b>Fraser Type IIA</b> → <b>A</b>rticulation of knee involved (intra-articular)",
s_small)],
[Paragraph("<b>Fraser Type IIB</b> → <b>B</b>eyond the knee (hip/ankle)",
s_small)],
[Paragraph("<b>Letts A→E</b> → <b>A</b>ll closed → Both <b>O</b>pen (severity escalates)",
s_small)],
[Paragraph("<b>Management</b> → <b>V</b>ascular first, then <b>B</b>ones "
"(Retrograde Femoral + Antegrade Tibial = same Anterior incision)",
s_small)],
[Paragraph("<b>Stats</b> → <b>2-6-3-9</b>: "
"Vascular 21% · Open 62% · Ligaments 30% · Good outcomes 93%",
S("ms", fontName="Helvetica-Bold", fontSize=8, textColor=C_NAVY, leading=11))],
]
mt = Table(mem_rows, colWidths=[BODY_W])
mt.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), C_PALE_BLU),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 8),
("LINEBELOW", (0,0),(-1,-2), 0.3, HexColor("#B0CCE8")),
("BACKGROUND", (0,5),(0,5), HexColor("#D8EEFF")),
]))
story.append(mt)
story.append(SP(3))
# ══ FOOTER ═══════════════════════════════════════════════════════════
HR(C_ACCENT, 0.8)
ft_data = [[
Paragraph("Floating Knee Injury — Last-Minute Revision Sheet", s_note),
Paragraph("Campbell's 15e · Rockwood & Green's 10e · Miller's 9e", s_note),
Paragraph("Generated by Orris Medical AI", s_note),
]]
ft = Table(ft_data, colWidths=[BODY_W/3]*3)
ft.setStyle(TableStyle([
("LEFTPADDING", (0,0),(-1,-1), 2),
("RIGHTPADDING", (0,0),(-1,-1), 2),
("TOPPADDING", (0,0),(-1,-1), 2),
("BOTTOMPADDING",(0,0),(-1,-1), 2),
]))
story.append(ft)
# ── Build ────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved → {OUT}")
cd /tmp/workspace/floating-knee-ppt && python build_pdf.py 2>&1
ls -lh /tmp/workspace/floating-knee-ppt/Floating_Knee_Revision.pdf && python -c " from pypdf import PdfReader r = PdfReader('/tmp/workspace/floating-knee-ppt/Floating_Knee_Revision.pdf') print(f'Pages: {len(r.pages)}') "
Floating Knee Revision
PDF Document · PDF
| Section | Content |
|---|---|
| Key Statistics Banner | 5 coloured KPI boxes — Vascular 21% · Open # 62% · Ligament ~30% · Good outcomes 93% · Paediatric age 10.2 yrs |
| Definition | Highlighted definition box — quote-ready for essays |
| Classification table | Fraser (I, IIA, IIB) and Letts (A–E) side-by-side with colour coding |
| Mechanism & Associations | Two-column: mechanism vs associated injuries |
| Management Algorithm | 5-step table — ATLS → Vascular → Ex-Fix → IM Nailing → Ligaments (Step 2 highlighted in red) |
| Surgical Fixation | Retrograde femoral / Antegrade tibial / Ex-Fix / ORIF with indications & complications |
| Complications table | 8 complications with rates + management |
| Prognosis | Good vs poor factors side-by-side |
| Paediatric notes | Age-stratified management table |
| Essay answer outline | Para-by-para structure guide |
| Memory aids | 2-6-3-9 mnemonic + Fraser/Letts mnemonics |
Ppt on damage control orthopedics for pg orthopedics exam
mkdir -p /tmp/workspace/dco-ppt && echo "ready"
~/dco-ppt/build_dco.py
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from io import BytesIO
# ── Palette ──────────────────────────────────────────────────────────
DARK = RGBColor(0x0B, 0x24, 0x3B)
NAVY2 = RGBColor(0x0D, 0x1F, 0x3C)
MED_BLUE = RGBColor(0x15, 0x5E, 0xA6)
ACCENT = RGBColor(0x00, 0xB4, 0xD8)
LIGHT_BG = RGBColor(0xF0, 0xF6, 0xFF)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
TEXT_D = RGBColor(0x12, 0x1A, 0x26)
GREY = RGBColor(0x55, 0x65, 0x78)
GREEN = RGBColor(0x05, 0x96, 0x68)
ORANGE = RGBColor(0xE0, 0x7B, 0x10)
RED = RGBColor(0xBF, 0x28, 0x28)
PURPLE = RGBColor(0x6B, 0x2F, 0x96)
TEAL = RGBColor(0x03, 0x7A, 0x8A)
PALE_BLUE = RGBColor(0xE8, 0xF4, 0xFF)
AMBER = RGBColor(0xC0, 0x6A, 0x00)
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
blank = prs.slide_layouts[6]
# ── Helpers ──────────────────────────────────────────────────────────
def rect(slide, x, y, w, h, fill):
s = slide.shapes.add_shape(1, Inches(x), Inches(y), Inches(w), Inches(h))
s.line.fill.background(); s.fill.solid(); s.fill.fore_color.rgb = fill
return s
def tb(slide, x, y, w, h, text, sz=16, bold=False, color=TEXT_D,
align=PP_ALIGN.LEFT, italic=False, wrap=True):
box = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = box.text_frame; tf.word_wrap = wrap
tf.margin_left=Inches(0.07); tf.margin_top=Inches(0.03)
tf.margin_right=Inches(0.04); tf.margin_bottom=Inches(0.02)
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run(); r.text = text
r.font.name="Calibri"; r.font.size=Pt(sz)
r.font.bold=bold; r.font.italic=italic; r.font.color.rgb=color
return tf
def add_bullets(slide, x, y, w, h, items, sz=14, color=TEXT_D,
hdr=None, hdr_col=MED_BLUE, hdr_sz=15, bg=None, bul="•"):
if bg: rect(slide, x, y, w, h, bg)
box = slide.shapes.add_textbox(Inches(x), Inches(y+0.04), Inches(w), Inches(h-0.06))
tf = box.text_frame; tf.word_wrap=True
tf.margin_left=Inches(0.10); tf.margin_top=Inches(0.04)
tf.margin_right=Inches(0.06); tf.margin_bottom=Inches(0.04)
first = True
if hdr:
p = tf.paragraphs[0]; first=False
r=p.add_run(); r.text=hdr
r.font.name="Calibri"; r.font.size=Pt(hdr_sz)
r.font.bold=True; r.font.color.rgb=hdr_col
for itm in items:
p = tf.paragraphs[0] if first else tf.add_paragraph(); first=False
r=p.add_run()
r.text = f"{bul} {itm}" if bul else itm
r.font.name="Calibri"; r.font.size=Pt(sz); r.font.color.rgb=color
def hdr(slide, title, sub=None, bg=DARK):
rect(slide, 0, 0, 13.333, 1.20, bg)
rect(slide, 0, 1.10, 13.333, 0.10, ACCENT)
tb(slide, 0.38, 0.13, 12.6, 0.90, title, sz=27, bold=True, color=WHITE)
if sub: tb(slide, 0.38, 0.76, 12.6, 0.40, sub, sz=12, italic=True,
color=RGBColor(0x8A,0xBE,0xE0))
def card(slide, x, y, w, h, title, tcol, items, sz=13.5, title_sz=14.5):
rect(slide, x, y, w, h, WHITE)
rect(slide, x, y, w, 0.52, tcol)
tb(slide, x+0.10, y+0.06, w-0.20, 0.44, title, sz=title_sz, bold=True, color=WHITE, wrap=True)
add_bullets(slide, x+0.10, y+0.58, w-0.20, h-0.64, items, sz=sz)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 1 — TITLE
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, DARK)
rect(s, 0, 0, 13.333, 2.5, MED_BLUE)
rect(s, 0, 2.38, 13.333, 0.14, ACCENT)
rect(s, 0, 5.6, 13.333, 1.9, NAVY2)
tb(s, 0.8, 2.55, 11.8, 1.9,
"DAMAGE CONTROL\nORTHOPAEDICS (DCO)",
sz=50, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
tb(s, 0.8, 4.38, 11.8, 0.85,
"Concepts, Indications, Staging & Outcomes — PG Orthopaedics Essay Exam Review",
sz=21, color=ACCENT, align=PP_ALIGN.CENTER)
tb(s, 0.8, 5.75, 11.8, 0.60,
"DCO vs ETC | Lethal Triad | Physiological Windows | External Fixation | EAC / PRISM",
sz=15, italic=True, color=RGBColor(0xB0,0xD0,0xF0), align=PP_ALIGN.CENTER)
tb(s, 0.8, 6.50, 11.8, 0.55,
"Sources: Campbell's Orthopaedics 15e (2026) · Rockwood & Green's 10e (2025) · Bailey & Love 28e · Rosen's Emergency Medicine",
sz=11, italic=True, color=RGBColor(0x6A,0x8C,0xAC), align=PP_ALIGN.CENTER)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 2 — HISTORICAL EVOLUTION & DEFINITION
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr(s, "HISTORICAL EVOLUTION & DEFINITION")
# Timeline bar
rect(s, 0.35, 1.30, 12.65, 0.70, NAVY2)
milestones = [
("1970s", "Prolonged bed rest\nshown harmful"),
("1980s", "ETC introduced —\nfix all # within 24 hrs"),
("1993", "Damage control\nfor abdominal trauma\n(lethal triad concept)"),
("Late 1990s", "DCO applied to\nlong bone & pelvic #"),
("2000s", "EAC concept\nemerges"),
("2010s+", "PRISM / Safe\nDefinitive Surgery"),
]
dx = 0.55
for yr, ev in milestones:
tb(s, dx, 1.32, 2.0, 0.32, yr, sz=11, bold=True, color=ACCENT, align=PP_ALIGN.CENTER)
tb(s, dx, 1.57, 2.0, 0.38, ev, sz=9.5, color=RGBColor(0xD0,0xE8,0xFF), align=PP_ALIGN.CENTER)
dx += 2.05
# Definition box
rect(s, 0.35, 2.14, 12.65, 1.28, MED_BLUE)
tb(s, 0.52, 2.20, 12.30, 1.16,
'"Damage Control Orthopaedics (DCO) is a strategy of STAGED fracture management in the '
'polytrauma patient, wherein TEMPORARY stabilisation of fractures (usually with external '
'fixation) is performed during initial resuscitation, avoiding the physiological "second '
'hit" of prolonged surgery, followed by DEFINITIVE fixation once the patient\'s '
'physiological state has been normalised."',
sz=16, italic=True, color=WHITE, wrap=True)
# Two col: History of ETC / origins
rect(s, 0.35, 3.54, 6.15, 3.72, WHITE)
rect(s, 0.35, 3.54, 6.15, 0.50, ORANGE)
tb(s, 0.48, 3.57, 5.90, 0.46, "Early Total Care (ETC) — Background", sz=15, bold=True, color=WHITE)
add_bullets(s, 0.48, 4.12, 5.90, 3.05, [
"Late 1990s gold standard: fix ALL fractures within 24 hours",
"Benefits: reduced pulmonary complications, reduced bed-rest morbidity",
"Suitable for 80–90% of polytrauma patients",
"Failed in: severe chest/head injuries, extreme physiological state, ongoing haemorrhage",
"ETC in 'borderline' patients → ARDS, MODS, mortality",
"Led to development of DCO strategy",
], sz=14)
rect(s, 6.68, 3.54, 6.32, 3.72, WHITE)
rect(s, 6.68, 3.54, 6.32, 0.50, MED_BLUE)
tb(s, 6.82, 3.57, 6.05, 0.46, "Why DCO Was Needed — The 'Second Hit' Concept", sz=15, bold=True, color=WHITE)
add_bullets(s, 6.82, 4.12, 6.05, 3.05, [
"First hit: trauma → inflammatory/immune activation, cytokine release",
"Cytokine elevation → systemic immune response syndrome (SIRS)",
"Second hit: major surgery → amplifies cytokine storm",
"Combined insult → ARDS, MODS, death",
"DCO reduces operative burden during vulnerable physiological window",
"Molecular medicine & ICU advances allowed better patient selection",
], sz=14)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 3 — THE LETHAL TRIAD & PATHOPHYSIOLOGY
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr(s, "THE LETHAL TRIAD & PATHOPHYSIOLOGY OF POLYTRAUMA",
sub="The physiological basis for DCO")
# Central triad diagram (3 boxes + arrows)
for xi, yi, lab, col, desc in [
(4.0, 1.40, "HYPOTHERMIA\n< 34 °C", RGBColor(0x00,0x70,0xC0),
"• Impairs enzymatic processes\n• Reduces cardiac output\n• Worsens coagulopathy\n• Impairs O₂ delivery"),
(0.60, 4.10, "ACIDOSIS\npH < 7.2", RED,
"• Anaerobic respiration\n• Lactic acid accumulation\n• Dysfunctional clotting factors\n• Platelet aggregation failure"),
(7.40, 4.10, "COAGULOPATHY", PURPLE,
"• Dilutional from crystalloid\n• Consumptive from haemorrhage\n• Worsened by hypothermia + acidosis\n• DIC can develop"),
]:
rect(s, xi, yi, 4.10, 1.22, col)
tb(s, xi+0.12, yi+0.14, 3.85, 0.95, lab, sz=17, bold=True, color=WHITE,
align=PP_ALIGN.CENTER)
rect(s, xi, yi+1.25, 4.10, 1.75, PALE_BLUE)
tb(s, xi+0.12, yi+1.28, 3.85, 1.68, desc, sz=13, color=TEXT_D, wrap=True)
# "Point of no return" label in centre
rect(s, 5.15, 3.15, 2.85, 0.80, RGBColor(0x1A,0x1A,0x1A))
tb(s, 5.18, 3.18, 2.78, 0.72, "POINT OF\nNO RETURN",
sz=13, bold=True, color=RGBColor(0xFF,0xCC,0x00), align=PP_ALIGN.CENTER)
# Right column — cascade
rect(s, 9.80, 1.28, 3.20, 6.00, WHITE)
rect(s, 9.80, 1.28, 3.20, 0.50, DARK)
tb(s, 9.92, 1.30, 3.00, 0.46, "Physiological Cascade", sz=14, bold=True, color=WHITE)
cascade = [
("Haemorrhage + Tissue Injury", RED),
("Anaerobic Respiration", ORANGE),
("Lactic Acidosis (lactate > 5)", RED),
("Coagulation Factor Dysfunction", PURPLE),
("Hypothermia from fluid/blood loss", MED_BLUE),
("Cytokine Storm (IL-6, IL-1, TNF-α)", TEAL),
("SIRS", ORANGE),
("ARDS / MODS / Death", RGBColor(0x8B,0x00,0x00)),
]
cy = 1.85
for label, col in cascade:
rect(s, 9.85, cy, 3.10, 0.52, col)
tb(s, 9.92, cy+0.07, 2.96, 0.40, label, sz=12.5, bold=True,
color=WHITE, align=PP_ALIGN.CENTER)
cy += 0.60
# ══════════════════════════════════════════════════════════════════════
# SLIDE 4 — DCO vs ETC: Criteria & Patient Selection
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr(s, "DCO vs ETC vs EAC — CRITERIA & PATIENT SELECTION",
sub="Bailey & Love 28e | Table 26.2 | Miller's Review 9e")
# Three columns
COLS = [
("EARLY TOTAL CARE (ETC)\n80–90% of Polytrauma Patients", GREEN, [
"Haemodynamically STABLE",
"No ongoing vasoactive / inotropic support",
"No hypoxaemia, no hypercapnia",
"Serum lactate < 2 mmol/L",
"Normal coagulation (no coagulopathy)",
"Normothermia",
"Urinary output > 1 mL/kg/h",
"ISS < 36",
"No major head injury (GCS > 8)",
"No major thoracic injury",
"→ Fix ALL fractures within 24 hours",
]),
("DAMAGE CONTROL (DCO)\n'Borderline' / Unstable Patients", RED, [
"Hypothermia: < 34 °C",
"Acidosis: pH < 7.2",
"Serum lactate > 5 mmol/L",
"Coagulopathy (INR > 1.5)",
"Blood pressure < 70 mmHg",
"Transfusion approaching ≥ 15 units pRBC",
"Injury Severity Score (ISS) > 36",
"Severe head injury (GCS ≤ 8)",
"Severe chest injury (AIS ≥ 3)",
"Pelvic ring disruption with ongoing haemorrhage",
"→ Temporary Ex-Fix → ICU → Definitive at 5–14 days",
]),
("EARLY APPROPRIATE CARE (EAC)\n& PRISM Concept", TEAL, [
"Emerging concept — between ETC and DCO",
"Individualised / personalised decision",
"Based on patient's physiological reserve",
"PRISM: 'Do no further harm'",
"Accounts for: genetics, centre resources, team expertise",
"Ongoing evaluation: temperature, lactate, BE, coagulation",
"Plan documented on whiteboard in theatre",
"ETC can be converted to DCO mid-surgery if needed",
"Senior input mandatory for borderline patients",
"→ Right surgery at the right time for the right patient",
]),
]
CX = [0.35, 4.57, 8.80]
for i, (title, col, items) in enumerate(COLS):
rect(s, CX[i], 1.28, 4.05, 6.00, WHITE)
rect(s, CX[i], 1.28, 4.05, 0.72, col)
tb(s, CX[i]+0.10, 1.31, 3.83, 0.68, title, sz=14, bold=True,
color=WHITE, wrap=True)
add_bullets(s, CX[i]+0.10, 2.06, 3.83, 5.10, items, sz=13.5)
# Resuscitation thresholds strip
rect(s, 0.35, 7.15, 12.65, 0.27, RGBColor(0xE8,0xF4,0xFF))
tb(s, 0.50, 7.16, 12.45, 0.24,
"Thresholds for definitive fixation (EAC): Lactate < 4 mmol/L | pH ≥ 7.25 | Base excess > −5.5 mmol/L "
"(Miller's Review 9e)",
sz=11, italic=True, color=GREY)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 5 — STAGES OF DCO
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr(s, "STAGES OF DCO — STEP-BY-STEP APPROACH",
sub="Bailey & Love 28e | Campbell's 15e")
stages = [
("STAGE 1\nRESUSCITATION", MED_BLUE, [
"ATLS primary survey (ABCDE)",
"Control haemorrhage — tourniquet, wound packing",
"Airway management, ventilation",
"Massive transfusion protocol: FFP:PLT:pRBC = 1:1:1",
"Correct lethal triad: warm fluids, TXA, FFP",
"REBOA for non-compressible torso haemorrhage",
"Avoid crystalloid overload",
"Goal: haemodynamic stabilisation",
]),
("STAGE 2\nHAEMORRHAGE CONTROL\n& TEMPORARY FIXATION", RED, [
"Operative haemorrhage control (vascular, pelvic packing)",
"External fixation of long bones (femur, tibia)",
"Pelvic external fixator / C-clamp for pelvic ring",
"Fasciotomy for compartment syndrome",
"Amputation if non-reconstructable limb",
"NPWT for open wounds",
"Minimal dissection — avoid adding to physiological insult",
"Goal: < 90 min operative time",
]),
("STAGE 3\nDECOMPRESSION &\nDECONTAMINATION", ORANGE, [
"Fasciotomy / decompression of compartment syndrome",
"Wound debridement — remove contaminated tissue",
"Fracture irrigation",
"Temporary wound closure — NPWT",
"Skeletal traction if needed",
"Relook at 48–72 hours",
"DO NOT perform definitive soft-tissue procedures",
]),
("STAGE 4\nICU RESUSCITATION", TEAL, [
"Ongoing correction of lethal triad",
"Monitor: lactate, pH, BE, temperature, coagulation",
"Optimise: oxygenation, cardiac output, renal function",
"Nutritional support early",
"Thromboprophylaxis when safe",
"Target: lactate < 4, pH ≥ 7.25, BE > −5.5",
"Reassess: 48–72 hours for readiness",
]),
("STAGE 5\nDEFINITIVE FIXATION\n(5–14 DAYS)", GREEN, [
"Convert Ex-Fix → IM nailing (femur, tibia)",
"Pelvic plating after pelvic Ex-Fix",
"ORIF of articular/metaphyseal fractures",
"Soft-tissue coverage (flap reconstruction)",
"Final wound closure",
"Ligament repair/reconstruction",
"Early rehabilitation and mobilisation",
]),
]
SX = [0.35, 2.82, 5.30, 7.77, 10.24]
for i, (title, col, items) in enumerate(stages):
rect(s, SX[i], 1.28, 2.30, 6.05, WHITE)
rect(s, SX[i], 1.28, 2.30, 0.80, col)
tb(s, SX[i]+0.08, 1.30, 2.13, 0.76, title, sz=12.5, bold=True,
color=WHITE, align=PP_ALIGN.CENTER, wrap=True)
add_bullets(s, SX[i]+0.08, 2.14, 2.14, 5.12, items, sz=12)
# connecting strip
rect(s, 0.35, 7.22, 12.65, 0.22, DARK)
tb(s, 0.50, 7.23, 12.45, 0.19,
"Stages of DCO: Resuscitation → Haemorrhage Control + Temporary Fixation "
"→ Decompression/Decontamination → ICU → Definitive Fixation",
sz=11, bold=True, color=ACCENT, align=PP_ALIGN.CENTER)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 6 — EXTERNAL FIXATION: THE TOOL OF DCO
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr(s, "EXTERNAL FIXATION — THE CORNERSTONE OF DCO",
sub="Indications, Types, Technique & Conversion Protocol")
card(s, 0.35, 1.28, 4.15, 6.00, "Indications for External Fixation", MED_BLUE, [
"Damage control (haemodynamically unstable)",
"Open fractures with major soft-tissue injury",
"Severely comminuted fractures",
"Intra-articular fractures (temporary)",
"Patients with concomitant head injury",
"Floating knee injuries",
"Pelvic ring disruption (haemorrhage control)",
"Multiple closed fractures (polytrauma)",
"Patients requiring frequent transport / ICU monitoring",
"Fractures in infected / contaminated fields",
"(Campbell's Operative Orthopaedics 15e)",
], sz=13.5)
card(s, 4.65, 1.28, 4.05, 6.00, "Types & Sites", GREEN, [
"UNIPLANAR (unilateral) frame:",
" • Femoral shaft",
" • Tibial shaft (most common)",
"",
"SPANNING FRAME:",
" • Knee-spanning: femur + tibia pins",
" • Ankle-spanning: tibial + foot",
"",
"PELVIC EXTERNAL FIXATOR:",
" • Anterior frame (iliac crest pins)",
" • C-clamp (posterior compression)",
"",
"JOINT-SPANNING:",
" • Wrist, ankle, elbow in articular #",
"",
"Definitive Ex-Fix: children < 10 yrs",
], sz=13)
card(s, 8.85, 1.28, 4.15, 6.00, "Conversion Protocol & Complications", ORANGE, [
"CONVERSION TO DEFINITIVE FIXATION:",
" • Timing: 5–14 days post-DCO",
" • Confirm: haemodynamic stability",
" • Check: lactate, pH, BE, coagulation",
" • Pin sites: clean / no infection",
"",
"COMPLICATIONS OF EX-FIX:",
" • Pin-track infection (most common)",
" • Malalignment / loss of reduction",
" • Joint stiffness",
" • Delayed union if left too long",
" • Difficulty with conversion (scar tissue)",
" • DVT (immobility)",
"",
"Soft-tissue stripping of segmental",
"fragment: large traction may not reduce",
], sz=13)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 7 — SPECIFIC FRACTURES IN DCO
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr(s, "DCO FOR SPECIFIC FRACTURES",
sub="Femoral Shaft | Pelvic Ring | Open Fractures | Floating Knee | Spine")
fractures = [
("Femoral Shaft #", MED_BLUE, [
"Temporary: Unilateral Ex-Fix (rapid, < 30 min)",
"Or: Damage-control skeletal traction",
"Definitive: Closed IM nailing (antegrade / retrograde)",
"ISS > 36 + chest injury → DCO preferred over ETC",
"Segmental femur → Ex-Fix to maintain length",
"Key risk: fat embolism syndrome, ARDS",
]),
("Pelvic Ring Disruption", RED, [
"Priority: control massive haemorrhage",
"Pelvic binder → first step in ED",
"Ex-Fix anterior frame (iliac pins) → stabilises volume",
"C-clamp for posterior ring / venous haemorrhage",
"Pelvic packing (retroperitoneal) ± angioembolisation",
"Definitive: ORIF at 5–10 days",
]),
("Open Fractures\n(Gustilo IIIB/C)", ORANGE, [
"Irrigation and debridement urgently",
"Antibiotics within 3 hours of injury",
"Ex-Fix for bony stabilisation",
"NPWT for wound management",
"Definitive coverage < 7 days",
"Vascular repair if arterial injury",
]),
("Floating Knee", TEAL, [
"Spanning knee Ex-Fix (femur + tibia pins)",
"Definitive: Retrograde femoral + Antegrade tibial nail",
"Same anterior incision",
"Reduce operative time in unstable patient",
"EUA ligaments after stabilisation",
]),
("Spinal Fractures", PURPLE, [
"Stabilise on spine board initially",
"Log-roll precautions",
"Unstable: early spinal stabilisation reduces ARDS risk",
"MIST concept: Minimal Invasive Spinal Technique",
"Permissive hypotension: avoid in spinal cord injury",
]),
("Acetabulum / Hip", AMBER, [
"Skeletal traction (distal femoral pin) in DCO phase",
"Reduces pain, maintains alignment",
"Definitive ORIF: once physiologically stable",
"ORIF timing: 3–10 days for best outcomes",
"CT preop planning after resuscitation",
]),
]
FX = [0.35, 4.55, 8.75]
FY = [1.28, 4.38]
for i, (title, col, items) in enumerate(fractures):
x = FX[i % 3]; y = FY[i // 3]
rect(s, x, y, 3.95, 2.90, WHITE)
rect(s, x, y, 3.95, 0.50, col)
tb(s, x+0.10, y+0.06, 3.73, 0.42, title, sz=14, bold=True, color=WHITE, wrap=True)
add_bullets(s, x+0.10, y+0.58, 3.73, 2.22, items, sz=13)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 8 — DAMAGE CONTROL RESUSCITATION (DCR)
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr(s, "DAMAGE CONTROL RESUSCITATION (DCR)",
sub="Haemostatic Resuscitation | Permissive Hypotension | MTP | REBOA")
dcr_panels = [
("Haemostatic Resuscitation", MED_BLUE, [
"Replace blood with blood — avoid crystalloid",
"Massive Transfusion Protocol (MTP): 1:1:1",
" (FFP : Platelets : Packed RBC)",
"Rationale: replaces clotting factors + volume",
"Target: maintain coagulation alongside volume",
"TXA (Tranexamic Acid): within 3 hours of injury",
" → Reduces fibrinolysis and mortality",
"Fibrinogen / cryoprecipitate: if fibrinogen < 1.5 g/L",
"TEG/ROTEM: guides targeted blood product use",
"Calcium: give with massive transfusion",
]),
("Permissive Hypotension", ORANGE, [
"Target SBP 80–90 mmHg until haemostasis achieved",
"Exception: head injury → maintain CPP",
" (Target MAP ≥ 80 mmHg if TBI)",
"Rationale: prevents clot disruption before control",
"Avoid aggressive fluid resuscitation",
"Crystalloid worsens dilutional coagulopathy",
"Warm all fluids: prevent hypothermia",
"Goal: SBP ≥ 90 after haemostasis achieved",
]),
("REBOA & Packing", RED, [
"REBOA: Resuscitative Endovascular Balloon Occlusion of Aorta",
" → Zones I, III of aorta",
" → Non-compressible torso haemorrhage (zone I)",
" → Pelvic haemorrhage (zone III)",
" → Bridges to operative haemostasis",
"Pelvic packing: retroperitoneal",
" → For venous / cancellous haemorrhage",
" → Used with pelvic Ex-Fix or C-clamp",
"FAST exam / CT trauma for decision",
]),
("Monitoring & Targets", GREEN, [
"Continuous monitoring: ECG, SpO₂, BP, EtCO₂",
"Lab targets during resuscitation:",
" • Lactate < 4 mmol/L → safe for surgery",
" • pH ≥ 7.25",
" • Base excess > −5.5 mmol/L",
" • Temp ≥ 35 °C",
" • INR < 1.5",
" • Hb > 8 g/dL",
" • Ionised calcium normal",
"TEG / ROTEM for real-time coagulation status",
]),
]
PX = [0.35, 3.55, 6.75, 9.95]
for i, (title, col, items) in enumerate(dcr_panels):
rect(s, PX[i], 1.28, 3.05, 6.00, WHITE)
rect(s, PX[i], 1.28, 3.05, 0.52, col)
tb(s, PX[i]+0.10, 1.30, 2.83, 0.48, title, sz=14, bold=True, color=WHITE, wrap=True)
add_bullets(s, PX[i]+0.10, 1.87, 2.85, 5.28, items, sz=12.8)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 9 — COMPLICATIONS & OUTCOMES
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, LIGHT_BG)
hdr(s, "COMPLICATIONS, OUTCOMES & EVIDENCE")
# Complications table
rect(s, 0.35, 1.28, 7.30, 5.90, WHITE)
rect(s, 0.35, 1.28, 7.30, 0.52, RED)
tb(s, 0.50, 1.30, 7.05, 0.48, "Complications of DCO / Polytrauma Management", sz=15, bold=True, color=WHITE)
comps = [
("ARDS", "Failed DCO / prolonged first surgery", "Ventilatory support, prone positioning"),
("MODS", "Uncontrolled SIRS, late resuscitation", "ICU, organ support, sepsis protocols"),
("Sepsis", "Open fractures, prolonged ICU stay", "Source control, antibiotics, bundles"),
("Non-union", "Ex-Fix left too long > 14 days", "Exchange nailing, ORIF + ICBG"),
("Pin-track infxn", "External fixator pins", "Pin care, antibiotics, early conversion"),
("Missed injuries", "5–20% in polytrauma (altered GCS)", "Repeat survey after stabilisation"),
("DVT / PE", "Immobility, polytrauma", "LMWH, mechanical, IVC filter if needed"),
("Fat embolism", "Multiple long bone # / delayed fixation", "ICU, O₂, early nailing reduces risk"),
]
cy = 1.88
for comp, cause, mgmt in comps:
rect(s, 0.35, cy, 7.30, 0.58, PALE_BLUE if cy % 1.2 < 0.6 else WHITE)
tb(s, 0.48, cy+0.07, 1.60, 0.46, comp, sz=12.5, bold=True, color=RED)
tb(s, 2.15, cy+0.07, 2.60, 0.46, cause, sz=12, color=TEXT_D)
tb(s, 4.82, cy+0.07, 2.75, 0.46, mgmt, sz=12, color=TEXT_D)
cy += 0.62
# Right: Evidence & outcomes
rect(s, 7.90, 1.28, 5.10, 5.90, WHITE)
rect(s, 7.90, 1.28, 5.10, 0.52, GREEN)
tb(s, 8.05, 1.30, 4.85, 0.48, "Evidence & Outcomes", sz=15, bold=True, color=WHITE)
add_bullets(s, 8.05, 1.88, 4.85, 5.15, [
"DCO vs ETC (Pape et al. 2002 — landmark study):",
" → Changed femoral # management in polytrauma",
" → From ETC to DCO in borderline patients",
"Reduced: pulmonary complications (ARDS), MODS",
"Reduced: ICU length of stay",
"Reduced: mortality in high-ISS patients",
"ETC still preferred in 80–90% (stable patients)",
"EAC (Early Appropriate Care): reduces risk of both",
" pulmonary complications AND DCO overuse",
"",
"ISS > 36: increased risk of ARDS with ETC",
"ISS > 36 + severe chest (AIS ≥ 3):",
" → DCO strongly indicated",
"",
"TEG/ROTEM: better blood product utilisation,",
" improved haemostasis vs lab-guided resuscitation",
"TXA within 3 hours: reduces mortality (CRASH-2 trial)",
], sz=12.8)
# ══════════════════════════════════════════════════════════════════════
# SLIDE 10 — EXAM HIGH-YIELD SUMMARY
# ══════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
rect(s, 0, 0, 13.333, 7.5, DARK)
rect(s, 0, 1.38, 13.333, 0.12, ACCENT)
tb(s, 0.38, 0.15, 12.6, 1.10,
"HIGH-YIELD EXAM SUMMARY — DAMAGE CONTROL ORTHOPAEDICS",
sz=27, bold=True, color=WHITE)
panels = [
("Definition (Write First)", MED_BLUE, [
"Staged fracture management in polytrauma",
"Temporary fixation → ICU resuscitation → Definitive fixation",
"Avoids 'second hit' of prolonged surgery",
"Cornerstone: External fixation",
]),
("Lethal Triad", RED, [
"Hypothermia (< 34°C)",
"Acidosis (pH < 7.2)",
"Coagulopathy (INR > 1.5)",
"Each worsens the other → point of no return",
]),
("DCO Criteria (Must List)", ORANGE, [
"Temp < 34°C, pH < 7.2, Lactate > 5",
"BP < 70 mmHg, pRBC ≥ 15 units",
"ISS > 36, Severe chest / head injury",
"Coagulopathy, Pelvic ring haemorrhage",
]),
("Stages of DCO", GREEN, [
"1. Resuscitation (ATLS, MTP, TXA)",
"2. Haemorrhage control + Ex-Fix",
"3. Decompression / Decontamination",
"4. ICU (correct lethal triad)",
"5. Definitive fixation (5–14 days)",
]),
("DCR Targets", TEAL, [
"Lactate < 4 mmol/L",
"pH ≥ 7.25",
"Base excess > −5.5 mmol/L",
"MTP: FFP:PLT:pRBC = 1:1:1",
"TXA within 3 hours of injury",
]),
("Key Exam Points", ACCENT, [
"ETC suitable for 80–90% of polytrauma",
"DCO for 'borderline' / physiologically deranged",
"EAC & PRISM = modern individualized approach",
"ISS > 36 + AIS chest ≥ 3 → DCO mandatory",
"CRASH-2: TXA within 3 hrs reduces mortality",
]),
]
PX2 = [0.35, 4.55, 8.75]
PY2 = [1.58, 4.42]
for i, (title, col, items) in enumerate(panels):
x = PX2[i % 3]; y = PY2[i // 3]
rect(s, x, y, 3.95, 2.72, NAVY2)
rect(s, x, y, 3.95, 0.52, col)
tb(s, x+0.10, y+0.06, 3.73, 0.44, title, sz=13.5, bold=True, color=WHITE)
add_bullets(s, x+0.10, y+0.58, 3.73, 2.05, items, sz=13,
color=RGBColor(0xD0,0xE8,0xFF))
rect(s, 0, 7.08, 13.333, 0.42, RGBColor(0x06,0x12,0x22))
tb(s, 0.35, 7.10, 12.6, 0.38,
"References: Campbell's Operative Orthopaedics 15e (2026) | Rockwood & Green's Fractures 10e (2025) | "
"Bailey & Love 28e | Rosen's Emergency Medicine | Miller's Review 9e | CRASH-2 Trial",
sz=10, italic=True, color=RGBColor(0x70,0x90,0xB0), align=PP_ALIGN.CENTER)
# ── SAVE ──────────────────────────────────────────────────────────────
out = "/tmp/workspace/dco-ppt/DCO_Damage_Control_Orthopaedics.pptx"
buf = BytesIO()
prs.save(buf)
with open(out, "wb") as f: f.write(buf.getvalue())
print(f"Saved → {out}")
cd /tmp/workspace/dco-ppt && python build_dco.py 2>&1
python -c " from pptx import Presentation prs = Presentation('/tmp/workspace/dco-ppt/DCO_Damage_Control_Orthopaedics.pptx') print(f'Total slides: {len(prs.slides)}') for i, slide in enumerate(prs.slides, 1): texts = [s.text_frame.text.strip()[:70] for s in slide.shapes if s.has_text_frame and s.text_frame.text.strip()] print(f' Slide {i}: {texts[0] if texts else \"[no text]\"}') import os; print(f'File size: {os.path.getsize(\"/tmp/workspace/dco-ppt/DCO_Damage_Control_Orthopaedics.pptx\")/1024:.1f} KB') "
DCO Damage Control Orthopaedics
Presentation · PPTX
| Slide | Content |
|---|---|
| 1 | Title slide |
| 2 | Historical Evolution & Definition — ETC vs DCO timeline (1970s → PRISM 2010s), definition box, "Second Hit" concept |
| 3 | The Lethal Triad & Pathophysiology — Visual 3-box diagram (Hypothermia / Acidosis / Coagulopathy), cascade → ARDS/MODS/Death |
| 4 | DCO vs ETC vs EAC — Full criteria table (Bailey & Love Table 26.2), PRISM concept, resuscitation thresholds (lactate, pH, BE) |
| 5 | 5 Stages of DCO — Resuscitation → Haemorrhage Control + Ex-Fix → Decompression → ICU → Definitive Fixation |
| 6 | External Fixation — Indications (Campbell's 15e list), types/sites, conversion protocol (5–14 days), complications |
| 7 | DCO for Specific Fractures — Femoral shaft, Pelvic ring, Open fractures, Floating knee, Spine, Acetabulum |
| 8 | Damage Control Resuscitation (DCR) — MTP 1:1:1, TXA, permissive hypotension, REBOA, TEG/ROTEM targets |
| 9 | Complications & Evidence — Complications table + Pape 2002 landmark study, ISS > 36 criteria, CRASH-2 trial |
| 10 | High-Yield Exam Summary — 6-panel revision: Definition, Lethal Triad, DCO criteria, 5 stages, DCR targets, key exam points |
Regimen for spinal tb,tb,tb knee
| Drug | Abbreviation | Standard Adult Dose |
|---|---|---|
| Hisoniazid | H / INH | 300 mg/day (5 mg/kg) |
| Rifampicin | R / RIF | 600 mg/day (10 mg/kg) |
| ZPyrazinamide | Z / PZA | 25 mg/kg/day |
| Ethambutol | E / EMB | 15–25 mg/kg/day |
Isoniazid + Rifampicin + Pyrazinamide + Ethambutol daily × 2 months
| Site | Total Duration | Regimen Written |
|---|---|---|
| Spinal TB (Pott's disease) | 9–12 months | 2HRZE + 7HR (or 10HR) |
| TB Knee | 9–12 months | 2HRZE + 7HR (or 10HR) |
| TB Hip | 9–12 months | 2HRZE + 7HR (or 10HR) |
INTENSIVE PHASE: 2 months — HRZE daily (4 drugs)
CONTINUATION PHASE: 7 months — HR daily (2 drugs)
TOTAL: 9 months (can extend to 12 months for severe/complicated cases)
| Drug | Mechanism | Key Toxicity |
|---|---|---|
| Isoniazid (H) | Inhibits mycolic acid synthesis | Peripheral neuropathy (give pyridoxine B6 10–25 mg/day); hepatotoxicity |
| Rifampicin (R) | Inhibits RNA polymerase | Hepatotoxicity; turns secretions orange-red; enzyme inducer |
| Pyrazinamide (Z) | Kills intracellular bacilli (acidic pH) | Hepatotoxicity; hyperuricaemia; arthralgia |
| Ethambutol (E) | Inhibits arabinogalactan synthesis | Optic neuritis (reversible if stopped promptly); check colour vision |
| Situation | Modification |
|---|---|
| Liver failure | Avoid PZA; use EMB + Streptomycin ± fluoroquinolone |
| Renal failure | Avoid aminoglycosides; monitor EMB levels; adjust PZA dose |
| Pregnancy | 9 months: 2HRE + 7HR (avoid PZA in USA; WHO allows it); no Streptomycin |
| MDR-TB | Bedaquiline + linezolid + fluoroquinolone-based regimen; specialist referral |
| HIV co-infection | No intermittent dosing; drug interactions with ARTs (rifampicin ↓ levels) |
Create a PDF cheat sheet on TB drug regimens and side effects
mkdir -p /tmp/workspace/tb-cheatsheet && echo "ready"
~/tb-cheatsheet/build_tb_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib import colors
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.colors import HexColor
OUT = "/tmp/workspace/tb-cheatsheet/TB_Drug_Regimen_CheatSheet.pdf"
# ── Colours ───────────────────────────────────────────────────────────
C_NAVY = HexColor("#0B243B")
C_BLUE = HexColor("#155EA6")
C_ACCENT = HexColor("#00B4D8")
C_GREEN = HexColor("#059668")
C_ORANGE = HexColor("#D97706")
C_RED = HexColor("#B91C1C")
C_PURPLE = HexColor("#6D28D9")
C_TEAL = HexColor("#0F766E")
C_BROWN = HexColor("#92400E")
C_PINK = HexColor("#9D174D")
C_WHITE = colors.white
C_BLACK = colors.black
C_DGREY = HexColor("#1E293B")
C_LGREY = HexColor("#F1F5F9")
C_STRIPE = HexColor("#DBEAFE")
C_PALE_G = HexColor("#D1FAE5")
C_PALE_O = HexColor("#FEF3C7")
C_PALE_R = HexColor("#FEE2E2")
C_PALE_P = HexColor("#EDE9FE")
C_PALE_T = HexColor("#CCFBF1")
C_PALE_N = HexColor("#E0F2FE")
PAGE_W, PAGE_H = A4
MARGIN = 12 * mm
BODY_W = PAGE_W - 2 * MARGIN
doc = SimpleDocTemplate(
OUT, pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=10*mm, bottomMargin=10*mm,
title="TB Drug Regimen Cheat Sheet",
author="Orris Medical"
)
# ── Style helpers ─────────────────────────────────────────────────────
def S(name, **kw):
return ParagraphStyle(name, **kw)
s_tiny = S("tiny", fontName="Helvetica", fontSize=6.8, leading=9, textColor=C_DGREY)
s_small = S("sm", fontName="Helvetica", fontSize=7.8, leading=10.5, textColor=C_DGREY)
s_sm_b = S("smb", fontName="Helvetica-Bold", fontSize=7.8, leading=10.5, textColor=C_DGREY)
s_body = S("body", fontName="Helvetica", fontSize=8.5, leading=11.5, textColor=C_DGREY)
s_bold = S("bold", fontName="Helvetica-Bold", fontSize=8.5, leading=11.5, textColor=C_DGREY)
s_note = S("note", fontName="Helvetica-Oblique",fontSize=7.2, leading=9.5, textColor=HexColor("#475569"), alignment=TA_CENTER)
s_wh = S("wh", fontName="Helvetica-Bold", fontSize=8.5, leading=11, textColor=C_WHITE)
s_wh_sm = S("whsm", fontName="Helvetica", fontSize=7.8, leading=10.5, textColor=C_WHITE)
s_wh_t = S("wht", fontName="Helvetica-Bold", fontSize=9.5, leading=12, textColor=C_WHITE, alignment=TA_CENTER)
s_cent = S("cent", fontName="Helvetica", fontSize=8.5, leading=11.5, textColor=C_DGREY, alignment=TA_CENTER)
s_cent_b = S("centb", fontName="Helvetica-Bold", fontSize=8.5, leading=11.5, textColor=C_DGREY, alignment=TA_CENTER)
def P(t, st=None): return Paragraph(t, st or s_body)
def B(t, bullet="•"): return Paragraph(f"{bullet} {t}", s_small)
def SP(h=2): return Spacer(1, h*mm)
def HR(c=C_ACCENT, w=0.5): return HRFlowable(width="100%", thickness=w, color=c, spaceAfter=1.5)
# ── Table builder shortcuts ───────────────────────────────────────────
def sec_hdr(text, bg=C_NAVY, fg=C_WHITE, sz=10):
data = [[Paragraph(text, S("sh", fontName="Helvetica-Bold", fontSize=sz,
textColor=fg, leading=13))]]
t = Table(data, colWidths=[BODY_W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 8),
]))
return t
def mini_hdr(text, bg, sz=8.5):
data = [[Paragraph(text, S("mh", fontName="Helvetica-Bold", fontSize=sz,
textColor=C_WHITE, leading=11))]]
t = Table(data, colWidths=[BODY_W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 6),
]))
return t
# ─────────────────────────────────────────────────────────────────────
story = []
# ══ TITLE BANNER ══════════════════════════════════════════════════════
title_rows = [
[Paragraph("TB DRUG REGIMEN CHEAT SHEET",
S("tt", fontName="Helvetica-Bold", fontSize=20,
textColor=C_WHITE, leading=24, alignment=TA_CENTER))],
[Paragraph("Anti-Tubercular Therapy (ATT) | First-Line & Second-Line Drugs | "
"Bone & Joint TB | Side Effects | Special Situations",
S("ts", fontName="Helvetica-Oblique", fontSize=9,
textColor=HexColor("#93C5FD"), leading=12, alignment=TA_CENTER))],
[Paragraph("Sources: Harrison's 22e (2025) · Katzung's Pharmacology 16e · "
"Miller's Review 9e · Red Book 2021 · WHO Guidelines",
S("tr", fontName="Helvetica-Oblique", fontSize=7.5,
textColor=HexColor("#60A5FA"), leading=10, alignment=TA_CENTER))],
]
tt = Table(title_rows, colWidths=[BODY_W])
tt.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), C_NAVY),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 4),
]))
story.append(tt)
story.append(SP(3))
# ══ SECTION 1: FIRST-LINE DRUGS ═══════════════════════════════════════
story.append(sec_hdr("1. FIRST-LINE ANTI-TUBERCULAR DRUGS (HRZE)", bg=C_NAVY))
story.append(SP(2))
fl_hdr = [
Paragraph("Drug (Abbrev)", s_wh),
Paragraph("Adult Dose", s_wh),
Paragraph("Mechanism of Action", s_wh),
Paragraph("Main Side Effects", s_wh),
Paragraph("Monitoring", s_wh),
]
fl_rows = [
[
Paragraph("<b>Isoniazid</b>\n(H / INH)", s_sm_b),
Paragraph("300 mg/day\n(5 mg/kg/day)", s_small),
Paragraph("Inhibits mycolic acid synthesis\n(enoyl-ACP reductase / InhA)", s_small),
Paragraph("• Peripheral neuropathy\n• Hepatotoxicity (MOST COMMON cause of drug-induced liver injury in TB)\n• Lupus-like syndrome\n• Pellagra\n• Psychosis / seizures (rare)\n• Haemolytic anaemia", s_small),
Paragraph("LFTs monthly\nGive Pyridoxine (Vit B6) 10–25 mg/day\nwith every INH prescription", s_small),
],
[
Paragraph("<b>Rifampicin</b>\n(R / RIF)", s_sm_b),
Paragraph("600 mg/day\n(10 mg/kg/day)\n(450 mg if < 50 kg)", s_small),
Paragraph("Inhibits DNA-dependent RNA polymerase\n→ Blocks mRNA transcription", s_small),
Paragraph("• Hepatotoxicity\n• Orange-red discolouration of urine, tears, saliva\n• Flu-like syndrome (intermittent dosing)\n• Thrombocytopenic purpura\n• Enzyme inducer → ↓ OCP, warfarin, ARTs\n• Rifampicin rash / urticaria", s_small),
Paragraph("LFTs monthly\nWarn patient: orange secretions\nCheck drug interactions\n(especially ARTs in HIV)", s_small),
],
[
Paragraph("<b>Pyrazinamide</b>\n(Z / PZA)", s_sm_b),
Paragraph("25 mg/kg/day\n(max 2 g/day)", s_small),
Paragraph("Converted to pyrazinoic acid in acidic\nenvironment of macrophage lysosomes\n→ Kills dormant/intracellular bacilli", s_small),
Paragraph("• Hepatotoxicity (most hepatotoxic of the 4)\n• Hyperuricaemia → acute gout\n• Arthralgia / non-gouty polyarthritis\n• Photosensitivity / rash\n• GI upset\n• Avoid in liver failure", s_small),
Paragraph("LFTs monthly\nSerum uric acid\nAllopurinol if symptomatic gout\nAvoid in severe hepatic impairment", s_small),
],
[
Paragraph("<b>Ethambutol</b>\n(E / EMB)", s_sm_b),
Paragraph("15–25 mg/kg/day\n(max 1.6 g/day)", s_small),
Paragraph("Inhibits arabinosyl transferase\n→ Disrupts arabinogalactan synthesis\nin mycobacterial cell wall", s_small),
Paragraph("• Optic neuritis (dose-related, reversible if stopped)\n→ ↓ Visual acuity\n→ Loss of red-green colour discrimination\n• Peripheral neuropathy\n• Hyperuricaemia\n• GI intolerance", s_small),
Paragraph("Visual acuity (Snellen chart)\nColour vision test (Ishihara)\nBEFORE starting and monthly\nAvoid if visual monitoring impossible", s_small),
],
]
cw_fl = [28*mm, 22*mm, 42*mm, 55*mm, BODY_W - 147*mm]
fl_table = Table([fl_hdr] + fl_rows, colWidths=cw_fl, repeatRows=1)
fl_style = [
("BACKGROUND", (0,0),(-1,0), C_BLUE),
("VALIGN", (0,0),(-1,-1), "TOP"),
("FONTSIZE", (0,0),(-1,-1), 7.8),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 3),
("GRID", (0,0),(-1,-1), 0.35, HexColor("#BFDBFE")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_LGREY, C_WHITE]),
# highlight hepatotox column
("TEXTCOLOR", (3,1),(3,4), C_RED),
]
fl_table.setStyle(TableStyle(fl_style))
story.append(fl_table)
story.append(SP(3))
# ══ SECTION 2: REGIMEN PHASES ══════════════════════════════════════════
story.append(sec_hdr("2. STANDARD REGIMEN PHASES", bg=C_BLUE))
story.append(SP(2))
phase_rows = [
[
Paragraph("<b>INTENSIVE PHASE</b>", S("ip", fontName="Helvetica-Bold", fontSize=9, textColor=C_WHITE, leading=12, alignment=TA_CENTER)),
Paragraph("<b>CONTINUATION PHASE</b>", S("cp", fontName="Helvetica-Bold", fontSize=9, textColor=C_WHITE, leading=12, alignment=TA_CENTER)),
Paragraph("<b>KEY PURPOSE</b>", S("kp", fontName="Helvetica-Bold", fontSize=9, textColor=C_WHITE, leading=12, alignment=TA_CENTER)),
],
[
Paragraph("<b>2 months</b>\nH + R + Z + E (HRZE)\nAll 4 drugs daily", s_sm_b),
Paragraph("<b>4 months</b>\nH + R (HR)\n2 drugs daily", s_sm_b),
Paragraph("Standard pulmonary TB, hilar adenopathy\nTotal = <b>6 months (2HRZE / 4HR)</b>", s_small),
],
[
Paragraph("<b>2 months</b>\nH + R + Z + E (HRZE)", s_sm_b),
Paragraph("<b>7 months</b>\nH + R (HR)", s_sm_b),
Paragraph("Bone & joint TB (spine, hip, knee)\nTotal = <b>9 months (2HRZE / 7HR)</b>\n(Standard in India/most orthopaedic practice)", s_small),
],
[
Paragraph("<b>2 months</b>\nH + R + Z + E (HRZE)", s_sm_b),
Paragraph("<b>10 months</b>\nH + R (HR)", s_sm_b),
Paragraph("Severe bone/joint TB, TB meningitis, miliary TB\nWHO / AAP recommendation for children\nTotal = <b>12 months (2HRZE / 10HR)</b>", s_small),
],
[
Paragraph("<b>2 months</b>\nH + R + Z + E (HRZE)", s_sm_b),
Paragraph("<b>7–10 months</b>\nH + R (HR)", s_sm_b),
Paragraph("TB meningitis (ATS/CDC/IDSA)\nContinuation phase extended to 7–10 months\nTotal = <b>9–12 months</b>", s_small),
],
]
cw_ph = [45*mm, 45*mm, BODY_W - 90*mm]
ph_t = Table(phase_rows, colWidths=cw_ph)
ph_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_TEAL),
("BACKGROUND", (0,1),(0,1), HexColor("#EFF6FF")),
("BACKGROUND", (0,2),(0,2), HexColor("#FEF3C7")),
("BACKGROUND", (0,3),(0,3), HexColor("#FEE2E2")),
("BACKGROUND", (0,4),(0,4), HexColor("#EDE9FE")),
("BACKGROUND", (1,1),(-1,1), HexColor("#F0FDF4")),
("BACKGROUND", (1,2),(-1,2), HexColor("#FFFBEB")),
("BACKGROUND", (1,3),(-1,3), HexColor("#FFF1F2")),
("BACKGROUND", (1,4),(-1,4), HexColor("#F5F3FF")),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#CBD5E1")),
]))
story.append(ph_t)
story.append(SP(3))
# ══ SECTION 3: BONE & JOINT TB SITE DURATIONS ════════════════════════
story.append(sec_hdr("3. BONE & JOINT TB — SITE-SPECIFIC REGIMENS", bg=C_GREEN))
story.append(SP(2))
site_hdr = [
Paragraph("Site", s_wh),
Paragraph("Regimen", s_wh),
Paragraph("Duration", s_wh),
Paragraph("Surgical Indications", s_wh),
Paragraph("Surgical Procedure", s_wh),
]
site_rows = [
[
Paragraph("<b>Spinal TB\n(Pott's Disease)</b>\nMost common extrapulmonary TB", s_sm_b),
Paragraph("2HRZE\n+\n7HR", s_cent_b),
Paragraph("<b>9 months</b>\n(up to 12 months in severe/complicated cases)", s_cent),
Paragraph("• Neurological deficit\n• Spinal instability\n• Progressive kyphosis (>30°)\n• Failure of ATT\n• Advanced caseation\n• Abscess compressing cord", s_small),
Paragraph("Hong Kong procedure:\nAnterior radical debridement\n+ autogenous strut graft\n± posterior instrumentation\n(to prevent progressive kyphosis)", s_small),
],
[
Paragraph("<b>TB Hip</b>\n2nd most common\nbone TB site", s_sm_b),
Paragraph("2HRZE\n+\n7HR", s_cent_b),
Paragraph("<b>9 months</b>\n(up to 12 months)", s_cent),
Paragraph("• Destroyed joint (Stage IV)\n• Avascular necrosis of femoral head\n• Failure of ATT\n• Persistent sinus\n• Fixed deformity", s_small),
Paragraph("Synovectomy + debridement\n(early stages)\nArthrodesis (late/destroyed)\nTHR (after disease quiescence\n>10 years or proven cure)", s_small),
],
[
Paragraph("<b>TB Knee</b>\n3rd most common", s_sm_b),
Paragraph("2HRZE\n+\n7HR", s_cent_b),
Paragraph("<b>9 months</b>\n(up to 12 months)", s_cent),
Paragraph("• Destroyed joint\n• Failure of ATT\n• Persistent sinus tract\n• Abscess\n• Fixed flexion deformity", s_small),
Paragraph("Synovectomy (early)\nDebridement\nArthrodesis (late)\nTKR (after quiescence)", s_small),
],
[
Paragraph("<b>TB of Other Bones</b>\n(ribs, wrist, ankle,\nsmall bones)", s_sm_b),
Paragraph("2HRZE\n+\n4–7HR", s_cent_b),
Paragraph("<b>6–9 months</b>", s_cent),
Paragraph("• Abscess\n• Sinus\n• Non-healing\n• Neurological deficit", s_small),
Paragraph("Debridement\n± curettage and bone graft\nfor structural defects", s_small),
],
]
cw_site = [30*mm, 20*mm, 25*mm, 53*mm, BODY_W - 128*mm]
site_t = Table([site_hdr] + site_rows, colWidths=cw_site, repeatRows=1)
site_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_GREEN),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 3),
("GRID", (0,0),(-1,-1), 0.35, HexColor("#A7F3D0")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_PALE_G, C_WHITE]),
("FONTNAME", (1,1),(1,-1), "Helvetica-Bold"),
("FONTSIZE", (1,1),(1,-1), 10),
("TEXTCOLOR", (1,1),(1,-1), C_GREEN),
("ALIGN", (1,0),(2,-1), "CENTER"),
]))
story.append(site_t)
story.append(SP(3))
# ══ SECTION 4: SIDE-EFFECTS QUICK REFERENCE ══════════════════════════
story.append(sec_hdr("4. SIDE EFFECTS — QUICK REFERENCE CARD", bg=C_RED))
story.append(SP(2))
# 4 drug cards side by side
cw4 = (BODY_W - 3*mm) / 4
def drug_card(name, abbr, colour, pale, dose, moa, sides, monitor):
rows = [
[Paragraph(f"<b>{name}</b> ({abbr})", S("dc", fontName="Helvetica-Bold", fontSize=9,
textColor=C_WHITE, leading=11, alignment=TA_CENTER))],
[Paragraph(f"<b>Dose:</b> {dose}", S("dd", fontName="Helvetica", fontSize=7.5,
leading=10, textColor=C_DGREY))],
[Paragraph(f"<b>Mechanism:</b> {moa}", S("dm", fontName="Helvetica", fontSize=7.5,
leading=10, textColor=C_DGREY))],
[Paragraph("<b>Side Effects:</b>", S("ds", fontName="Helvetica-Bold", fontSize=7.8,
leading=10, textColor=colour))],
]
for se in sides:
rows.append([Paragraph(f"▸ {se}", S("dse", fontName="Helvetica", fontSize=7.5,
leading=9.5, textColor=C_DGREY))])
rows.append([Paragraph(f"<b>Monitor:</b> {monitor}",
S("dmo", fontName="Helvetica-Oblique", fontSize=7.2,
leading=9.5, textColor=HexColor("#475569")))])
t = Table(rows, colWidths=[cw4])
ts = [
("BACKGROUND", (0,0),(0,0), colour),
("BACKGROUND", (0,1),(-1,-1), pale),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 2),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("BOX", (0,0),(-1,-1), 0.5, colour),
("LINEBELOW", (0,0),(0,0), 0.5, colour),
]
t.setStyle(TableStyle(ts))
return t
inh_card = drug_card(
"Isoniazid", "H/INH", C_BLUE, C_PALE_N,
"300 mg/day",
"Inhibits InhA → blocks mycolic acid",
["Peripheral neuropathy ★★★",
"Hepatotoxicity ★★★",
"Lupus-like syndrome",
"Pellagra (niacin deficiency)",
"Psychosis / seizures",
"Haemolytic anaemia (G6PD)",
"Optic neuritis (rare)",
"Gynecomastia"],
"LFTs · Give Pyridoxine B6 10–25 mg/day"
)
rif_card = drug_card(
"Rifampicin", "R/RIF", C_ORANGE, C_PALE_O,
"600 mg/day",
"Inhibits RNA polymerase β-subunit",
["Hepatotoxicity ★★★",
"Orange-red secretions ★★★",
"Flu-like syndrome (intermittent)",
"Thrombocytopenia / purpura",
"CYP450 inducer → ↓ OCP, warfarin",
"↓ ARTs (protease inhibitors)",
"Rash / pruritus",
"GI disturbances"],
"LFTs · Drug interactions (HIV ARTs, OCP)"
)
pza_card = drug_card(
"Pyrazinamide", "Z/PZA", C_GREEN, C_PALE_G,
"25 mg/kg/day",
"Pyrazinoic acid kills intracellular bacilli",
["Hepatotoxicity ★★★ (most toxic)",
"Hyperuricaemia / gout ★★★",
"Arthralgia / polyarthritis",
"Photosensitivity / rash",
"GI intolerance",
"Sideroblastic anaemia (rare)",
"AVOID in liver failure",
"AVOID in pregnancy (USA)"],
"LFTs · Serum uric acid · Allopurinol PRN"
)
emb_card = drug_card(
"Ethambutol", "E/EMB", C_PURPLE, C_PALE_P,
"15–25 mg/kg/day",
"Inhibits arabinosyl transferase",
["Optic neuritis ★★★ (UNIQUE to EMB)",
"↓ Visual acuity",
"Loss of red-green colour vision",
"Peripheral neuropathy",
"Hyperuricaemia",
"GI intolerance",
"Rash / pruritus",
"AVOID if cannot monitor vision"],
"Visual acuity + colour vision MONTHLY"
)
cards_t = Table([[inh_card, rif_card, pza_card, emb_card]],
colWidths=[cw4]*4)
cards_t.setStyle(TableStyle([
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 0),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING",(0,0),(-1,-1), 0),
("VALIGN", (0,0),(-1,-1), "TOP"),
("INNERGRID", (0,0),(-1,-1), 2.5, C_WHITE),
]))
story.append(cards_t)
story.append(SP(3))
# ══ SECTION 5: HEPATOTOXICITY MANAGEMENT ══════════════════════════════
story.append(sec_hdr("5. DRUG-INDUCED HEPATOTOXICITY — MANAGEMENT PROTOCOL", bg=C_BROWN))
story.append(SP(2))
hep_rows = [
[Paragraph("<b>STOP ATT if ANY of:</b>", s_sm_b),
Paragraph("<b>RESTART SEQUENCE (after LFTs normalise):</b>", s_sm_b),
Paragraph("<b>Bridge while LFTs recover:</b>", s_sm_b)],
[
Paragraph("• Jaundice (clinical)\n• ALT/AST > 3× ULN with symptoms\n"
"• ALT/AST > 5× ULN (asymptomatic)\n• Severe vomiting / abdominal pain", s_small),
Paragraph("Day 1–7: Rifampicin alone\nDay 8–14: Add Isoniazid\nDay 15+: Add Ethambutol\n"
"(Avoid pyrazinamide in re-challenge if severe)\n\n"
"Re-introduce one drug at a time\nMonitor LFTs after each addition", s_small),
Paragraph("Streptomycin + Ethambutol\n± Fluoroquinolone\n(until LFTs normalise and\nreintroduction complete)", s_small),
],
]
hep_t = Table(hep_rows, colWidths=[(BODY_W/3)]*3)
hep_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_BROWN),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("BACKGROUND", (0,1),(-1,1), C_PALE_O),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#FDE68A")),
]))
story.append(hep_t)
story.append(SP(3))
# ══ SECTION 6: SPECIAL SITUATIONS ════════════════════════════════════
story.append(sec_hdr("6. SPECIAL CLINICAL SITUATIONS", bg=C_PURPLE))
story.append(SP(2))
sp_rows = [
[Paragraph("<b>Situation</b>", s_wh), Paragraph("<b>Modification</b>", s_wh),
Paragraph("<b>Avoid</b>", s_wh)],
["Pregnancy",
"2HRZE / 7HR (9 months total)\nWHO allows PZA; USA avoids PZA\n→ Use 2HRE / 7HR instead",
"Streptomycin (VIII nerve damage in fetus)\nThioamides, Bedaquiline, Delamanid"],
["Liver Failure\n(severe)",
"Ethambutol + Streptomycin ± Fluoroquinolone\nIf required: INH + RIF under strict supervision",
"Pyrazinamide\n(most hepatotoxic → absolutely avoid)"],
["Renal Failure\n(CKD)",
"H + R + Z in usual doses (mild-moderate CKD)\nModify PZA dose in severe CKD\nMonitor EMB levels if used",
"Aminoglycosides (streptomycin, amikacin)\nDo NOT give EMB unless levels monitored"],
["HIV Co-infection",
"Start ATT first, then ART 2–8 wks later\nUse Rifabutin instead of Rifampicin if on PIs\nDOT mandatory; NO intermittent dosing",
"Rifampicin + Protease inhibitors together"],
["MDR-TB\n(H+R resistant)",
"Bedaquiline + Linezolid + Fluoroquinolone\n(Levofloxacin / Moxifloxacin)\n± Clofazimine\nMinimum 18–20 months; specialist only",
"Standard HRZE regimen alone (ineffective)"],
["Children\n(bone/joint TB)",
"Same HRZE regimen\nINH: 10 mg/kg/day (max 300 mg)\nRIF: 15 mg/kg/day (max 600 mg)\nPZA: 35 mg/kg/day\nEMB: 20 mg/kg/day\nDuration: 12 months (WHO/AAP)",
"EMB in children < 5 yrs (cannot report visual symptoms)"],
["Silicotuberculosis",
"Extend therapy by at least 2 additional months",
"Short-course regimens"],
]
cw_sp = [32*mm, BODY_W/2 - 5*mm, BODY_W - 32*mm - BODY_W/2 + 5*mm]
sp_data = [[Paragraph(str(r[0]) if not hasattr(r[0],'text') else r[0],
S("spb", fontName="Helvetica-Bold", fontSize=8, textColor=C_WHITE, leading=11))
if i == 0
else [Paragraph(c if isinstance(c, str) else str(c), s_small) for c in r]
for i in range(3)]
if isinstance(r, list) else r
for r in sp_rows]
sp_data_clean = []
for r in sp_rows:
if isinstance(r[0], Paragraph):
sp_data_clean.append(r)
else:
sp_data_clean.append([
Paragraph(r[0], S("sc", fontName="Helvetica-Bold", fontSize=8,
textColor=C_DGREY, leading=11)),
Paragraph(r[1], s_small),
Paragraph(r[2], S("sav", fontName="Helvetica", fontSize=7.8,
leading=10.5, textColor=C_RED)),
])
sp_t = Table(sp_data_clean, colWidths=cw_sp)
sp_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_PURPLE),
("TEXTCOLOR", (0,0),(-1,0), C_WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 5),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("GRID", (0,0),(-1,-1), 0.35, HexColor("#DDD6FE")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_PALE_P, C_WHITE]),
("FONTNAME", (0,1),(0,-1), "Helvetica-Bold"),
]))
story.append(sp_t)
story.append(SP(3))
# ══ SECTION 7: SECOND-LINE DRUGS ══════════════════════════════════════
story.append(sec_hdr("7. SECOND-LINE DRUGS (MDR-TB / DRUG INTOLERANCE)", bg=C_TEAL))
story.append(SP(2))
sl_rows = [
[Paragraph("<b>Drug</b>", s_wh), Paragraph("<b>Dose</b>", s_wh),
Paragraph("<b>Class</b>", s_wh), Paragraph("<b>Key Side Effects</b>", s_wh)],
["Streptomycin", "15 mg/kg/day IM", "Aminoglycoside", "Ototoxicity, Nephrotoxicity, VIII nerve damage\n⚠ AVOID in pregnancy"],
["Amikacin", "15 mg/kg/day IV/IM", "Aminoglycoside", "Ototoxicity, Nephrotoxicity"],
["Levofloxacin", "750–1000 mg/day", "Fluoroquinolone", "QT prolongation, Tendinopathy, GI"],
["Moxifloxacin", "400 mg/day", "Fluoroquinolone", "QT prolongation, Hepatotoxicity"],
["Bedaquiline", "400 mg/day × 2 wks,\nthen 200 mg 3×/wk", "Diarylquinoline", "QT prolongation, Hepatotoxicity\n(Newer; MDR-TB only)"],
["Linezolid", "600 mg/day", "Oxazolidinone", "Myelosuppression, Peripheral neuropathy, Optic neuritis"],
["Cycloserine", "500–1000 mg/day", "Structural analogue", "Psychiatric effects, Seizures, Peripheral neuropathy"],
["Ethionamide", "500–750 mg/day", "Thioamide", "GI intolerance (worst tolerated), Hepatotoxicity, Hypothyroidism"],
["Clofazimine", "100–200 mg/day", "Riminophenazine", "Skin discolouration (pink-brown), GI, QT prolongation"],
["PAS\n(Aminosalicylic acid)", "8–12 g/day", "Bacteriostatic", "GI (severe), Hypothyroidism, Hepatotoxicity"],
]
cw_sl = [35*mm, 38*mm, 30*mm, BODY_W - 103*mm]
sl_t = Table([sl_rows[0]] + [[
Paragraph(r[0], S("slb", fontName="Helvetica-Bold", fontSize=8, textColor=C_TEAL, leading=11)),
Paragraph(r[1], s_small), Paragraph(r[2], s_small),
Paragraph(r[3], S("slse", fontName="Helvetica", fontSize=7.8, leading=10.5,
textColor=C_DGREY)),
] for r in sl_rows[1:]], colWidths=cw_sl, repeatRows=1)
sl_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), C_TEAL),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("RIGHTPADDING", (0,0),(-1,-1), 3),
("GRID", (0,0),(-1,-1), 0.35, HexColor("#99F6E4")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_PALE_T, C_WHITE]),
]))
story.append(sl_t)
story.append(SP(3))
# ══ SECTION 8: MEMORY AIDS ════════════════════════════════════════════
story.append(sec_hdr("8. MEMORY AIDS & EXAM TRICKS", bg=C_NAVY))
story.append(SP(2))
mem_data = [
[
Paragraph("<b>HRZE = Drug Names</b>", S("mh", fontName="Helvetica-Bold", fontSize=8.5,
textColor=C_BLUE, leading=11)),
Paragraph("<b>Unique Side Effects</b>", S("mh2", fontName="Helvetica-Bold", fontSize=8.5,
textColor=C_RED, leading=11)),
Paragraph("<b>Duration Mnemonics</b>", S("mh3", fontName="Helvetica-Bold", fontSize=8.5,
textColor=C_GREEN, leading=11)),
],
[
Paragraph('<b>"<font color="#155EA6">H</font>ere <font color="#D97706">R</font>uns '
'<font color="#059668">Z</font>ebras <font color="#6D28D9">E</font>agerly"</b>\n\n'
'H = isoniazid\nR = rifampicin\nZ = pyrazinamide\nE = ethambutol\n\n'
'Or: <b>RIPE therapy</b>\n(Rifampicin, INH, Pyrazinamide, Ethambutol)',
S("mt", fontName="Helvetica", fontSize=8, leading=11, textColor=C_DGREY)),
Paragraph('<b>INH</b> → Neuropathy (give B6)\n'
'<b>Rifampicin</b> → Orange secretions\n'
'<b>PZA</b> → Gout (hyperuricaemia)\n'
'<b>EMB</b> → Eye (optic neuritis)\n\n'
'"<b>I Never Put Ethambutol</b>"\n→ I=INH/Neuropathy, N=Never give RIF without\nchecking interactions, P=PZA/Gout, E=EMB/Eye',
S("mu", fontName="Helvetica", fontSize=8, leading=11, textColor=C_DGREY)),
Paragraph('<b>Pulmonary TB:</b>\n2 + 4 = 6 months\n\n'
'<b>Bone & Joint TB (India):</b>\n2 + 7 = 9 months\n\n'
'<b>Severe/Children (WHO):</b>\n2 + 10 = 12 months\n\n'
'<b>TB Meningitis:</b>\n2 + 7–10 = 9–12 months\n\n'
'<b>MDR-TB:</b>\n≥ 18–20 months',
S("md", fontName="Helvetica", fontSize=8, leading=11, textColor=C_DGREY)),
],
]
cw_mem = [(BODY_W/3)] * 3
mem_t = Table(mem_data, colWidths=cw_mem)
mem_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), HexColor("#EFF6FF")),
("BACKGROUND", (0,1),(0,1), HexColor("#EFF6FF")),
("BACKGROUND", (1,1),(1,1), HexColor("#FFF1F2")),
("BACKGROUND", (2,1),(2,1), HexColor("#F0FDF4")),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 5),
("GRID", (0,0),(-1,-1), 0.4, HexColor("#CBD5E1")),
("LINEAFTER", (0,0),(1,-1), 1, HexColor("#CBD5E1")),
]))
story.append(mem_t)
story.append(SP(2))
# ══ FOOTER ═══════════════════════════════════════════════════════════
HR(C_ACCENT)
ft = Table([[
Paragraph("TB Drug Regimen Cheat Sheet", s_note),
Paragraph("Harrison's 22e · Katzung 16e · Miller's 9e · Red Book 2021 · WHO", s_note),
Paragraph("Orris Medical AI", s_note),
]], colWidths=[BODY_W/3]*3)
ft.setStyle(TableStyle([
("LEFTPADDING", (0,0),(-1,-1), 2),
("RIGHTPADDING", (0,0),(-1,-1), 2),
("TOPPADDING", (0,0),(-1,-1), 1),
("BOTTOMPADDING",(0,0),(-1,-1), 1),
]))
story.append(ft)
# ── Build ─────────────────────────────────────────────────────────────
doc.build(story)
print(f"Saved → {OUT}")
cd /tmp/workspace/tb-cheatsheet && python build_tb_pdf.py 2>&1
~/tb-cheatsheet/build_tb_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/tb-cheatsheet/build_tb_pdf.py'
cd /tmp/workspace/tb-cheatsheet && python build_tb_pdf.py 2>&1
python -c " from pypdf import PdfReader r = PdfReader('/tmp/workspace/tb-cheatsheet/TB_Drug_Regimen_CheatSheet.pdf') import os print(f'Pages: {len(r.pages)}') print(f'Size: {os.path.getsize(\"/tmp/workspace/tb-cheatsheet/TB_Drug_Regimen_CheatSheet.pdf\")/1024:.1f} KB') "
TB Drug Regimen CheatSheet
PDF Document · PDF
| Section | Content |
|---|---|
| 1. First-Line Drugs (HRZE) | Full table — dose, mechanism, ALL side effects, monitoring for each of the 4 drugs (side effects highlighted in red) |
| 2. Regimen Phases | Phase-wise table: 2HRZE intensive → continuation HR, with exact durations for pulmonary / bone+joint / severe / TBM |
| 3. Bone & Joint TB | Site-specific table: Spinal TB (Pott's), TB Hip, TB Knee, other bones — regimen, duration, surgical indications, surgical procedure |
| 4. Side Effects Quick-Reference | 4 colour-coded drug cards (INH/RIF/PZA/EMB) — dose, mechanism, ranked side effects with ★★★ severity markers |
| 5. Hepatotoxicity Protocol | When to stop ATT, restart sequence (day by day), bridge regimen |
| 6. Special Situations | Pregnancy, Liver failure, Renal failure, HIV, MDR-TB, Children, Silicotuberculosis — modifications + drugs to avoid |
| 7. Second-Line Drugs | Full table of 10 second-line agents: dose, class, key side effects |
| 8. Memory Aids | HRZE mnemonics, unique side-effect clues, duration quick-reference |