~/ophthalmology-colour-coding/generate_diagrams.py
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, Circle, FancyArrowPatch, Arc, Wedge, Rectangle, Ellipse
from matplotlib.gridspec import GridSpec
import matplotlib.patheffects as pe
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
import warnings
warnings.filterwarnings('ignore')
# ─── Global style ────────────────────────────────────────────────────────────
BG = '#0d1117'
TEXT = '#e6edf3'
ACCENT = '#58a6ff'
HEADER_BG = '#161b22'
def styled_fig(w=18, h=11):
fig = plt.figure(figsize=(w, h), facecolor=BG)
return fig
def title_bar(fig, text, subtitle=''):
fig.text(0.5, 0.965, text, ha='center', va='top', fontsize=20,
fontweight='bold', color='white',
bbox=dict(boxstyle='round,pad=0.4', facecolor='#1f6feb', edgecolor='#388bfd', lw=1.5))
if subtitle:
fig.text(0.5, 0.932, subtitle, ha='center', va='top', fontsize=10,
color='#8b949e', style='italic')
def add_watermark(fig):
fig.text(0.99, 0.01, 'Colour Coding in Ophthalmology', ha='right', va='bottom',
fontsize=7, color='#30363d')
# ═══════════════════════════════════════════════════════════════════════════════
# PAGE 1 – DRUG BOTTLE CAP COLOUR CODING
# ═══════════════════════════════════════════════════════════════════════════════
def page1_drug_caps():
fig = styled_fig(18, 13)
title_bar(fig, 'COLOUR CODING OF OPHTHALMIC EYE DROP BOTTLE CAPS',
'AAO (American Academy of Ophthalmology) Standardised System')
drugs = [
# (Class, Cap colour hex, Text colour, Examples, Mnemonic hint)
('BETA-BLOCKERS', '#FFD700', '#000000', 'Timolol, Betaxolol,\nLevobunolol', 'Yellow'),
('BETA-BLOCKER\nCOMBINATIONS', '#003087', '#FFFFFF', 'Cosopt\n(Timolol+Dorzolamide)', 'Dark Blue'),
('PROSTAGLANDIN\nANALOGUES', '#00B4B4', '#000000', 'Latanoprost, Bimatoprost,\nTravoprost', 'Turquoise'),
('ADRENERGIC\nAGONISTS (α2)', '#8B47C8', '#FFFFFF', 'Brimonidine,\nApraclonidine', 'Purple'),
('ADRENERGIC AGONIST\nCOMBINATIONS', '#7CBF3C', '#000000', 'Simbrinza\n(Brinzolamide+Brimonidine)', 'Light Green'),
('CARBONIC ANHYDRASE\nINHIBITORS (CAIs)', '#FF7F00', '#000000', 'Dorzolamide,\nBrinzolamide', 'Orange'),
('MIOTICS\n(Cholinergics)', '#006400', '#FFFFFF', 'Pilocarpine,\nCarbachol', 'Dark Green'),
('MYDRIATICS &\nCYCLOPLEGICS', '#CC2200', '#FFFFFF', 'Atropine, Tropicamide,\nPhenylephrine','Red'),
('ANTI-INFECTIVES\n(Antibiotics/Antivirals)', '#C8A96A', '#000000', 'Moxifloxacin, Ciprofloxacin,\nGanciclovir, Natamycin', 'Tan'),
('STEROIDS /\nANTI-INFLAMMATORY', '#FF80A0', '#000000', 'Prednisolone, Dexamethasone,\nFluorometholone', 'Pink'),
('NSAIDs', '#888888', '#FFFFFF', 'Ketorolac, Nepafenac,\nDiclofenac, Bromfenac', 'Gray'),
('IMMUNOMODULATORS', '#6B7A3C', '#FFFFFF', 'Cyclosporine (Restasis),\nLifitegrast', 'Olive Green'),
('CYTOTOXIC', '#111111', '#FFFFFF', '5-FU, Mitomycin-C\n(MMC)', 'Black'),
]
cols = 4
rows = 4
ax = fig.add_axes([0.02, 0.03, 0.96, 0.88])
ax.set_xlim(0, cols)
ax.set_ylim(0, rows)
ax.axis('off')
ax.set_facecolor(BG)
positions = [(c, r) for r in range(rows-1, -1, -1) for c in range(cols)]
for i, (drug_class, cap_hex, txt_col, examples, label) in enumerate(drugs):
if i >= len(positions):
break
cx, cy = positions[i]
x = cx + 0.05
y = cy + 0.05
w = 0.90
h = 0.88
# Card background
card = FancyBboxPatch((x, y), w, h,
boxstyle='round,pad=0.025',
facecolor='#161b22', edgecolor='#30363d', lw=1.2)
ax.add_patch(card)
# Cap circle (large coloured cap visual)
cap_x = x + 0.18
cap_y = y + h - 0.28
cap_r = 0.13
cap = Circle((cap_x, cap_y), cap_r, color=cap_hex, zorder=5)
ax.add_patch(cap)
# Cap border
cap_border = Circle((cap_x, cap_y), cap_r, fill=False, edgecolor='#ffffff44', lw=1.2, zorder=6)
ax.add_patch(cap_border)
# Bottle body
bx, by, bw, bh = cap_x - 0.08, y + 0.05, 0.16, 0.22
bottle = FancyBboxPatch((bx, by), bw, bh,
boxstyle='round,pad=0.01',
facecolor='#eef0f2', edgecolor='#cccccc', lw=1, zorder=4)
ax.add_patch(bottle)
# Bottle label strip
label_strip = Rectangle((bx + 0.01, by + 0.03), bw - 0.02, 0.10,
facecolor='#c8d8f0', edgecolor='none', zorder=5)
ax.add_patch(label_strip)
# Class name
ax.text(x + 0.38, y + h - 0.12, drug_class, fontsize=7.8, fontweight='bold',
color='white', va='top', ha='left', wrap=True,
multialignment='left')
# Colour label badge
badge = FancyBboxPatch((x + 0.38, y + h - 0.42), 0.48, 0.16,
boxstyle='round,pad=0.015',
facecolor=cap_hex, edgecolor='none', zorder=5)
ax.add_patch(badge)
ax.text(x + 0.62, y + h - 0.34, label, fontsize=6.5, fontweight='bold',
color=txt_col, va='center', ha='center', zorder=6)
# Examples
ax.text(x + 0.38, y + 0.30, examples, fontsize=6.2, color='#8b949e',
va='top', ha='left', multialignment='left')
# Legend note at bottom
fig.text(0.5, 0.015, '★ System developed by AAO + FDA + Pharmaceutical Industry | Voluntary compliance — reduces medication errors',
ha='center', fontsize=8, color='#8b949e')
add_watermark(fig)
return fig
# ═══════════════════════════════════════════════════════════════════════════════
# PAGE 2 – ANTERIOR SEGMENT DIAGRAM COLOUR CODING
# ═══════════════════════════════════════════════════════════════════════════════
def page2_anterior_segment():
fig = styled_fig(18, 13)
title_bar(fig, 'COLOUR CODING — ANTERIOR SEGMENT CLINICAL DIAGRAM',
'Standard used in case documentation, postgraduate exams & medico-legal records')
# Left: schematic eye diagram
ax_eye = fig.add_axes([0.02, 0.05, 0.40, 0.85])
ax_eye.set_xlim(-1.5, 1.5)
ax_eye.set_ylim(-1.5, 1.5)
ax_eye.set_aspect('equal')
ax_eye.axis('off')
ax_eye.set_facecolor(BG)
ax_eye.text(0, 1.42, 'SCHEMATIC EYE — ANTERIOR SEGMENT', ha='center', va='top',
fontsize=9, color=ACCENT, fontweight='bold')
# ── Draw eye ──────────────────────────────
# Sclera/white
sclera = Circle((0, 0), 1.2, facecolor='#f5f5f0', edgecolor='#333333', lw=2, zorder=1)
ax_eye.add_patch(sclera)
# Cornea arc (top)
cornea_arc = Arc((0, 0), 2.4, 2.4, angle=0, theta1=60, theta2=120,
color='black', lw=3, zorder=3)
ax_eye.add_patch(cornea_arc)
ax_eye.text(0, 1.30, 'CORNEA (BLACK outline)', ha='center', fontsize=7, color='white')
# Conjunctiva / limbus ring
limbus = Circle((0, 0), 1.2, fill=False, edgecolor='black', lw=2.5, zorder=2)
ax_eye.add_patch(limbus)
# Iris (brown)
iris = Circle((0, 0), 0.75, facecolor='#8B6914', edgecolor='#6B4F10', lw=1.5, zorder=4)
ax_eye.add_patch(iris)
ax_eye.text(-1.45, 0.0, 'IRIS\n(Brown)', ha='left', fontsize=6.5, color='#C8A030', va='center')
ax_eye.annotate('', xy=(-0.70, 0.22), xytext=(-1.35, 0.10),
arrowprops=dict(arrowstyle='->', color='#C8A030', lw=1))
# Pupil (dark)
pupil = Circle((0, 0), 0.32, facecolor='#1a0a00', edgecolor='#3d2010', lw=1, zorder=5)
ax_eye.add_patch(pupil)
ax_eye.text(0, -0.10, 'PUPIL\n(Brown)', ha='center', fontsize=6, color='#C8A030', zorder=10)
# Hyphema - red AC fill (partial, inferior)
hyphema_wedge = Wedge((0, 0), 0.73, 200, 340, facecolor='#cc2200aa', edgecolor='none', zorder=6)
ax_eye.add_patch(hyphema_wedge)
ax_eye.text(0, -0.82, '★ RED = Hyphema (blood in AC)', ha='center', fontsize=6.5, color='#FF4444')
# Corneal edema (blue shading - top of cornea area)
edema_patch = Arc((0, 0.95), 0.5, 0.25, angle=0, theta1=0, theta2=180,
color='#4488FF', lw=2, zorder=7)
ax_eye.add_patch(edema_patch)
ax_eye.text(1.42, 0.85, 'BLUE =\nStromal edema,\nDescemet folds,\nEpith. bullae', ha='right',
fontsize=6, color='#4488FF', va='top')
ax_eye.annotate('', xy=(0.25, 1.0), xytext=(1.10, 0.88),
arrowprops=dict(arrowstyle='->', color='#4488FF', lw=1))
# Corneal ulcer/epithelial defect (green)
green_spot = Circle((-0.25, 1.05), 0.12, facecolor='#00AA44', edgecolor='#00FF66', lw=1, zorder=8, alpha=0.85)
ax_eye.add_patch(green_spot)
ax_eye.text(-1.45, 1.05, 'GREEN = Epith defect,\nPEK, dendrites', ha='left', fontsize=6.5,
color='#00CC55', va='center')
ax_eye.annotate('', xy=(-0.37, 1.05), xytext=(-1.10, 1.05),
arrowprops=dict(arrowstyle='->', color='#00CC55', lw=1))
# Corneal neovascularization (red lines)
for angle in [80, 95, 110]:
rad = np.radians(angle)
x1 = 1.0 * np.cos(rad)
y1 = 1.0 * np.sin(rad)
x2 = 1.15 * np.cos(rad)
y2 = 1.15 * np.sin(rad)
ax_eye.plot([x1, x2], [y1, y2], color='#FF3333', lw=2, zorder=7)
ax_eye.text(1.42, 1.15, 'RED = Vessels,\nhemorrhage,\nrose Bengal', ha='right', fontsize=6,
color='#FF4444', va='center')
ax_eye.annotate('', xy=(1.14, 1.08), xytext=(1.20, 1.15),
arrowprops=dict(arrowstyle='->', color='#FF4444', lw=1))
# Corneal scar (black dot)
scar = Circle((0.15, 1.08), 0.05, facecolor='black', edgecolor='#555555', lw=1, zorder=9)
ax_eye.add_patch(scar)
# Yellow infiltrate / hypopyon level
hypopyon = Wedge((0, 0), 0.72, 235, 305, facecolor='#FFFF0088', edgecolor='#CCCC00', lw=1.5, zorder=7)
ax_eye.add_patch(hypopyon)
ax_eye.text(0, -1.42, '★ YELLOW = Hypopyon, infiltrates, fresh KPs', ha='center',
fontsize=6.5, color='#FFDD00')
# Lens (green tint)
lens_ellipse = Ellipse((0, 0), 0.28, 0.22, facecolor='#00882266', edgecolor='#00AA44', lw=1.5, zorder=10)
ax_eye.add_patch(lens_ellipse)
ax_eye.text(0.58, -0.38, 'LENS = Green\nIOL = Black', ha='left', fontsize=6.5, color='#00CC55')
ax_eye.annotate('', xy=(0.14, -0.05), xytext=(0.55, -0.30),
arrowprops=dict(arrowstyle='->', color='#00CC55', lw=1))
# Vitreous in AC (green)
ax_eye.text(-1.45, -0.45, 'Vitreous in AC\n= GREEN', ha='left', fontsize=6.5, color='#00CC55')
# Right: detailed legend table
ax_tbl = fig.add_axes([0.44, 0.05, 0.54, 0.85])
ax_tbl.axis('off')
ax_tbl.set_facecolor(BG)
ax_tbl.text(0.5, 0.99, 'ANTERIOR SEGMENT COLOUR CODING TABLE', ha='center', va='top',
fontsize=10, fontweight='bold', color=ACCENT,
transform=ax_tbl.transAxes)
entries = [
# (Structure, Colour_hex, Colour_name, What it represents)
('CORNEA', '#555555', 'BLACK',
'Scars (nebular/macular/leucomatous)\nDegenerations, dystrophies\nForeign bodies, sutures (broken lines)\nContact lens (dotted arc), band keratopathy'),
('CORNEA', '#4488FF', 'BLUE',
'Diffuse stromal edema (shading)\nEpithelial microcystic edema (small circles)\nDescemet\'s membrane folds (wavy lines)\nEpithelial bullae (Ω on slit view)'),
('CORNEA', '#8B6400', 'BROWN',
'Epithelial iron lines (Hudson-Stahli, Fleischer, Stocker\'s)\nEpithelial melanosis\nOld inactive KPs\nKrukenberg\'s spindle'),
('CORNEA', '#FF3333', 'RED',
'Corneal neovascularization\nRose Bengal staining (dots)\nGhost vessels (dotted lines)\nCiliary/conjunctival/mixed congestion, hemorrhages'),
('CORNEA', '#00AA44', 'GREEN',
'Filaments (lines)\nPunctate epithelial keratopathy — PEK (dots)\nEpithelial defect (shading)\nDendrites (HSV), geographic ulcer, lenticular changes'),
('CORNEA', '#CCCC00', 'YELLOW',
'Hypopyon\nActive/fresh keratic precipitates (KPs)\nCorneal infiltrates (bacterial, fungal, Acanthamoeba)\nRing infiltrate'),
('PUPIL / IRIS', '#8B6914', 'BROWN',
'Normal pupil\nIris: iridodialysis, iris nodules\n(Koeppe/Busacca), anterior & posterior synechiae'),
('LIMBUS', '#333333', 'BLACK',
'Limbal outline\nLimbal nodules, scleritis boundary'),
('ANTERIOR CHAMBER', '#CC2200', 'RED',
'Hyphema (blood in AC)\n— level drawn as horizontal red line'),
('ANTERIOR CHAMBER', '#00AA44', 'GREEN',
'Vitreous in AC\n(vitreous prolapse, post-ICCE)'),
('LENS', '#00AA44', 'GREEN',
'Lens opacities — nuclear/cortical/PSC\nCataract changes (green shading)'),
('IOL', '#222222', 'BLACK',
'Implanted intraocular lens\nPositioning holes and haptics'),
]
y_start = 0.94
row_h = 0.070
col_w = [0.14, 0.09, 0.14, 0.63]
headers = ['STRUCTURE', 'COLOUR', 'NAME', 'REPRESENTS']
# Header row
header_bg = FancyBboxPatch((0, y_start - 0.025), 1.0, 0.032,
boxstyle='square', facecolor='#1f6feb',
edgecolor='none', transform=ax_tbl.transAxes, clip_on=False)
ax_tbl.add_patch(header_bg)
cx = 0
for w, h_text in zip(col_w, headers):
ax_tbl.text(cx + 0.005, y_start - 0.009, h_text, ha='left', va='center',
fontsize=7, fontweight='bold', color='white', transform=ax_tbl.transAxes)
cx += w
y = y_start - 0.038
for i, (structure, col_hex, col_name, represents) in enumerate(entries):
row_bg_color = '#161b22' if i % 2 == 0 else '#0d1117'
n_lines = represents.count('\n') + 1
rh = max(row_h, 0.022 * n_lines)
bg = FancyBboxPatch((0, y - rh + 0.005), 1.0, rh,
boxstyle='square', facecolor=row_bg_color,
edgecolor='#21262d', lw=0.5,
transform=ax_tbl.transAxes, clip_on=False)
ax_tbl.add_patch(bg)
# colour swatch
swatch = FancyBboxPatch((col_w[0] + col_w[1] * 0.05, y - rh * 0.5),
col_w[1] * 0.75, rh * 0.7,
boxstyle='round,pad=0.005',
facecolor=col_hex, edgecolor='#ffffff44', lw=0.7,
transform=ax_tbl.transAxes, clip_on=False)
ax_tbl.add_patch(swatch)
ax_tbl.text(0.005, y - rh * 0.4, structure, ha='left', va='center', fontsize=6.5,
color='#cccccc', fontweight='bold', transform=ax_tbl.transAxes)
ax_tbl.text(col_w[0] + col_w[1] + 0.005, y - rh * 0.4, col_name, ha='left', va='center',
fontsize=6.5, color=col_hex, fontweight='bold', transform=ax_tbl.transAxes)
ax_tbl.text(col_w[0] + col_w[1] + col_w[2] + 0.005, y - 0.004, represents,
ha='left', va='top', fontsize=5.8, color='#8b949e',
transform=ax_tbl.transAxes, multialignment='left')
y -= rh
add_watermark(fig)
return fig
# ═══════════════════════════════════════════════════════════════════════════════
# PAGE 3 – POSTERIOR SEGMENT / RETINAL DIAGRAM
# ═══════════════════════════════════════════════════════════════════════════════
def page3_posterior_segment():
fig = styled_fig(18, 13)
title_bar(fig, 'COLOUR CODING — POSTERIOR SEGMENT / RETINAL DIAGRAM',
'Critical for retinal detachment surgery planning, case records & examinations')
# Left: schematic fundus diagram
ax_fundus = fig.add_axes([0.01, 0.05, 0.44, 0.84])
ax_fundus.set_xlim(-1.6, 1.6)
ax_fundus.set_ylim(-1.6, 1.6)
ax_fundus.set_aspect('equal')
ax_fundus.axis('off')
ax_fundus.set_facecolor('#1a0000')
ax_fundus.text(0, 1.56, 'FUNDUS DIAGRAM', ha='center', va='top',
fontsize=10, color=ACCENT, fontweight='bold')
# Fundus circle
fundus_circle = Circle((0, 0), 1.45, facecolor='#3a1500', edgecolor='#888888', lw=2.5, zorder=1)
ax_fundus.add_patch(fundus_circle)
# Retinal detachment area (BLUE — upper left quadrant)
det_wedge = Wedge((0, 0), 1.40, 100, 210, facecolor='#1133AA88', edgecolor='#2255FF', lw=2, zorder=3)
ax_fundus.add_patch(det_wedge)
ax_fundus.text(-1.55, 0.95, 'BLUE =\nDetached\nRetina', ha='center', fontsize=7,
color='#4488FF', fontweight='bold', va='center')
# Attached retina area (RED fill — right quadrant)
att_wedge = Wedge((0, 0), 1.38, 280, 100, facecolor='#AA220033', edgecolor='none', lw=0, zorder=2)
ax_fundus.add_patch(att_wedge)
ax_fundus.text(1.55, 0.50, 'RED =\nAttached\nRetina', ha='center', fontsize=7,
color='#FF4444', fontweight='bold', va='center')
# Ora serrata (BLUE outline)
ax_fundus.text(0, -1.55, '◀ ORA SERRATA outline = BLUE ▶', ha='center', fontsize=6.5, color='#4488FF')
# Optic disc (pale circle)
disc = Circle((0.45, 0.10), 0.18, facecolor='#FFE0A0', edgecolor='#CC9900', lw=1.5, zorder=6)
ax_fundus.add_patch(disc)
ax_fundus.text(0.45, 0.10, 'OD', ha='center', va='center', fontsize=7, color='#663300', fontweight='bold', zorder=7)
ax_fundus.text(0.45, -0.14, 'Disc', ha='center', fontsize=5.5, color='#FFCC44')
# Macula (red dot — normal macula = RED)
macula = Circle((-0.28, 0.10), 0.12, facecolor='#CC0000', edgecolor='#FF0000', lw=1.5, zorder=6)
ax_fundus.add_patch(macula)
ax_fundus.text(-0.28, 0.10, '★', ha='center', va='center', fontsize=9, color='#FFaaaa', zorder=7)
ax_fundus.text(-0.28, -0.10, 'MACULA\n(RED)', ha='center', fontsize=5.5, color='#FF4444')
# Macular edema symbol (RED-BLUE cross + 4 blue dots)
me_x, me_y = -0.55, 0.48
ax_fundus.plot([me_x - 0.10, me_x + 0.10], [me_y, me_y], color='#FF3333', lw=2.5, zorder=8)
ax_fundus.plot([me_x, me_x], [me_y - 0.10, me_y + 0.10], color='#3355FF', lw=2.5, zorder=8)
for dx, dy in [(-0.13, 0), (0.13, 0), (0, -0.13), (0, 0.13)]:
dot = Circle((me_x + dx, me_y + dy), 0.03, facecolor='#3355FF', zorder=9)
ax_fundus.add_patch(dot)
ax_fundus.text(-0.55, 0.25, 'Macular edema\n(Red+Blue cross\n+ 4 blue dots)', ha='center',
fontsize=5.5, color='#AAAAFF', va='top')
# Retinal break (BLUE outline, RED interior)
break_x, break_y = 0.20, 0.80
break_outer = Circle((break_x, break_y), 0.10, facecolor='#CC2200', edgecolor='#2255FF', lw=2.5, zorder=7)
ax_fundus.add_patch(break_outer)
ax_fundus.text(break_x, break_y, '✦', ha='center', va='center', fontsize=7, color='white', zorder=8)
ax_fundus.text(break_x, break_y + 0.16, 'Retinal\nbreak\n(Blue rim,\nRed interior)', ha='center',
fontsize=5.5, color='#FFAAAA', va='bottom')
# Retinal arteriole (RED line)
for angle in [30, 60, 90, 150, 210, 270, 330]:
r = np.radians(angle)
x1 = 0.45 * np.cos(r) + 0.45
y1 = 0.45 * np.sin(r) + 0.10
x2 = 1.1 * np.cos(r)
y2 = 1.1 * np.sin(r)
ax_fundus.plot([0.45, x2 * 0.9], [0.10, y2 * 0.9], color='#FF3333', lw=1.5, zorder=5)
# Retinal vein (BLUE line)
for angle in [15, 45, 75, 135, 195, 255, 315]:
r = np.radians(angle)
x2 = 1.1 * np.cos(r)
y2 = 1.1 * np.sin(r)
ax_fundus.plot([0.45, x2 * 0.9], [0.10, y2 * 0.9], color='#3366FF', lw=1, zorder=5, linestyle='--')
ax_fundus.text(1.55, -0.10, 'RED =\nArterioles', ha='center', fontsize=6, color='#FF4444')
ax_fundus.text(1.55, -0.50, 'BLUE =\nVeins', ha='center', fontsize=6, color='#4488FF')
# Hard exudates (YELLOW dots — inferior)
for (ex, ey) in [(-0.15, -0.55), (-0.05, -0.60), (0.08, -0.58), (0.18, -0.52)]:
dot = Circle((ex, ey), 0.04, facecolor='#FFFF00', zorder=7)
ax_fundus.add_patch(dot)
ax_fundus.text(0.02, -0.78, 'YELLOW = Hard exudates, drusen', ha='center', fontsize=6, color='#FFFF44')
# Laser treatment marks (GREEN dots)
for angle in np.linspace(120, 200, 8):
r = np.radians(angle)
lx = 1.0 * np.cos(r)
ly = 1.0 * np.sin(r)
dot = Circle((lx, ly), 0.04, facecolor='#00BB44', edgecolor='#00FF66', lw=0.8, zorder=8)
ax_fundus.add_patch(dot)
ax_fundus.text(-1.55, -0.55, 'GREEN =\nLaser/Cryo\nmarks', ha='center', fontsize=6.5, color='#00CC55')
# Choroidal melanoma (BROWN filled)
melanoma = Ellipse((-0.75, -0.40), 0.25, 0.18, facecolor='#8B4513', edgecolor='#6B3010', lw=1.5, zorder=7)
ax_fundus.add_patch(melanoma)
ax_fundus.text(-0.75, -0.65, 'Melanoma\n(BROWN)', ha='center', fontsize=5.5, color='#C8A030')
# Buckle positions
ax_fundus.text(-1.55, -1.1, 'Buckle under\ndetached = BROWN\nBuckle under\nattached = BLACK', ha='center',
fontsize=5.5, color='#C8A030', va='center')
# Master rule box
rule_box = FancyBboxPatch((-1.55, 1.10), 3.10, 0.38,
boxstyle='round,pad=0.04',
facecolor='#1f2937', edgecolor='#F59E0B', lw=1.5, zorder=10)
ax_fundus.add_patch(rule_box)
ax_fundus.text(0, 1.45, '⭐ MASTER RULE', ha='center', va='top', fontsize=8,
color='#F59E0B', fontweight='bold', zorder=11)
ax_fundus.text(0, 1.35, 'RED = Attached retina / Arterioles / Open break interior',
ha='center', va='top', fontsize=7, color='#FF7777', zorder=11)
ax_fundus.text(0, 1.24, 'BLUE = Detached retina / Veins / Break outline',
ha='center', va='top', fontsize=7, color='#7777FF', zorder=11)
# Right: table
ax_tbl = fig.add_axes([0.46, 0.05, 0.52, 0.84])
ax_tbl.axis('off')
ax_tbl.set_facecolor(BG)
ax_tbl.text(0.5, 0.99, 'POSTERIOR SEGMENT COLOUR CODING TABLE',
ha='center', va='top', fontsize=10, fontweight='bold', color=ACCENT,
transform=ax_tbl.transAxes)
entries = [
('#CC2200', 'RED',
'Retinal arterioles\nElevated neovascularization (NVD, NVE)\nVascular tumors, vortex veins\n★ ATTACHED retina area\nPre-retinal / intraretinal / subhyaloid hemorrhages\nOpen interior of retinal breaks (tears & holes)\nNormal/healthy macula\nMacular edema symbol (red part of cross)\nOpen part of giant retinal tear\nInner portions of thinned retinal areas\nLarge dialyses interior\nOuter layer holes in retinoschisis (interior)'),
('#2255FF', 'BLUE',
'★ DETACHED retina area\nRetinal veins (lighter than arterioles)\nOutline/RIM of retinal breaks (tears, holes)\nOra serrata outline\nVitreous base outline\nFlat/closed retinal breaks\nSubretinal fluid outline\nRetinoschisis inner & outer layer outlines\nRetinoblastoma outline (filled yellow)\nMacular edema symbol (blue part of cross + 4 dots)'),
('#8B4513', 'BROWN',
'Uveal tissue, pars plana cysts\nCiliary processes, striae ciliaris\nPigment beneath detached retina\nChorioretinal atrophy outline (under detachment)\nRPE detachment (PED)\nPosterior staphyloma outline\nMalignant choroidal melanoma\nEdge of scleral buckle under DETACHED retina\nChoroidal detachment'),
('#CCCC00', 'YELLOW',
'Intraretinal edema\nHard exudates (intraretinal / subretinal)\nDeposits in RPE\nDetached macula area\nPost-cryotherapy / post-laser retinal edema\nDrusen (hard and soft)\nLong and short ciliary nerves\nVenous sheathing\nCotton-wool spots (soft exudates)\nRetinoblastoma interior (outline = blue)'),
('#333333', 'BLACK',
'Edge of scleral buckle under ATTACHED retina\nChorioretinal atrophy outline (on attached side)\nLattice degeneration outline\nVitreoretinal/epiretinal membranes\nCNVM (choroidal neovascular membrane) outline\nPVR (proliferative vitreoretinopathy) membranes'),
('#00AA44', 'GREEN',
'Cryotherapy application marks (cryo dots)\nLaser photocoagulation spots\nTreatment demarcation lines\nSclerotomy sites'),
]
y = 0.93
for col_hex, col_name, represents in entries:
n_lines = represents.count('\n') + 1
rh = 0.021 * n_lines + 0.022
# Row background
bg = FancyBboxPatch((0, y - rh), 1.0, rh,
boxstyle='square', facecolor='#161b22',
edgecolor='#21262d', lw=0.5,
transform=ax_tbl.transAxes, clip_on=False)
ax_tbl.add_patch(bg)
# Colour swatch (large)
swatch = FancyBboxPatch((0.005, y - rh + rh * 0.1),
0.10, rh * 0.80,
boxstyle='round,pad=0.005',
facecolor=col_hex, edgecolor='#ffffff33', lw=0.8,
transform=ax_tbl.transAxes, clip_on=False)
ax_tbl.add_patch(swatch)
ax_tbl.text(0.055, y - rh * 0.5, col_name, ha='center', va='center', fontsize=8,
color='white' if col_hex not in ['#CCCC00'] else '#333333',
fontweight='bold', transform=ax_tbl.transAxes)
ax_tbl.text(0.12, y - 0.008, represents, ha='left', va='top', fontsize=5.8,
color='#c9d1d9', transform=ax_tbl.transAxes, multialignment='left')
y -= (rh + 0.005)
add_watermark(fig)
return fig
# ═══════════════════════════════════════════════════════════════════════════════
# PAGE 4 – CORNEAL TOPOGRAPHY + OCT + GLAUCOMA VF
# ═══════════════════════════════════════════════════════════════════════════════
def page4_imaging():
fig = styled_fig(18, 13)
title_bar(fig, 'COLOUR CODING — CORNEAL TOPOGRAPHY • OCT • GLAUCOMA ANALYSIS',
'Imaging & Diagnostic Colour Maps')
# ── PANEL A: Corneal topography ──────────────────────────────
ax1 = fig.add_axes([0.02, 0.52, 0.30, 0.40])
ax1.set_xlim(-1.2, 1.2)
ax1.set_ylim(-1.2, 1.2)
ax1.set_aspect('equal')
ax1.axis('off')
ax1.set_facecolor(BG)
ax1.text(0, 1.18, 'A. CORNEAL TOPOGRAPHY', ha='center', va='top', fontsize=9,
fontweight='bold', color=ACCENT)
ax1.text(0, 1.05, '(Pentacam / Orbscan — Axial Curvature Map)', ha='center', va='top',
fontsize=7, color='#8b949e')
topo_colors = ['#6600CC', '#0033FF', '#0099FF', '#00CCCC', '#00CC44',
'#CCCC00', '#FF9900', '#FF4400', '#CC0000']
topo_labels = ['<35D\nViolet', '36D\nBlue', '38D\nCyan', '40D\nTeal',
'42D\nGreen', '44D\nYellow', '46D\nOrange', '48D\nRed', '>50D\nDark Red']
radii = np.linspace(1.0, 0.10, len(topo_colors))
for i, (r, c) in enumerate(zip(radii, topo_colors)):
wedge = Circle((0, 0), r, facecolor=c, edgecolor='none', zorder=i + 1)
ax1.add_patch(wedge)
ax1.text(0, 0, '43D\n(Normal)', ha='center', va='center', fontsize=7,
color='white', fontweight='bold', zorder=20)
# Keratoconus indicator (inferior steepening)
kc_ellipse = Ellipse((0.0, -0.55), 0.45, 0.35, facecolor='#CC0000', edgecolor='#FF0000',
lw=2, zorder=25, alpha=0.85)
ax1.add_patch(kc_ellipse)
ax1.text(0, -0.55, 'KC', ha='center', va='center', fontsize=8, color='white', fontweight='bold', zorder=26)
ax1.text(0, -1.10, '↑ Inferior steepening = Keratoconus', ha='center', fontsize=6.5, color='#FF4444')
# Colour scale bar (vertical)
ax_cbar = fig.add_axes([0.315, 0.55, 0.025, 0.34])
ax_cbar.set_xlim(0, 1)
ax_cbar.set_ylim(0, len(topo_colors))
ax_cbar.axis('off')
for i, (c, lbl) in enumerate(zip(reversed(topo_colors), reversed(topo_labels))):
rect = Rectangle((0, i), 1, 1, facecolor=c, edgecolor='none')
ax_cbar.add_patch(rect)
ax_cbar.text(1.1, i + 0.5, lbl, va='center', ha='left', fontsize=5.5, color='white')
ax_cbar.text(0.5, -0.8, 'FLAT', ha='center', va='top', fontsize=6, color='#6600CC', fontweight='bold')
ax_cbar.text(0.5, len(topo_colors) + 0.2, 'STEEP', ha='center', va='bottom', fontsize=6,
color='#CC0000', fontweight='bold')
# Scale types
ax1.text(0, -1.18, 'ABSOLUTE: each band = 1.5D (35–50D range)\nNORMALIZED: 11 equal bands for that eye\'s power range',
ha='center', fontsize=6, color='#8b949e', multialignment='center')
# ── PANEL B: OCT macular map ─────────────────────────────────
ax2 = fig.add_axes([0.38, 0.52, 0.28, 0.40])
ax2.set_xlim(-1.2, 1.2)
ax2.set_ylim(-1.2, 1.2)
ax2.set_aspect('equal')
ax2.axis('off')
ax2.set_facecolor(BG)
ax2.text(0, 1.18, 'B. OCT MACULAR THICKNESS MAP (ETDRS)', ha='center', va='top',
fontsize=9, fontweight='bold', color=ACCENT)
# Draw ETDRS grid
oct_data = {
'center': ('#FF0000', '350µm\nEdema'),
'inner_sup': ('#FF8800', '310µm'),
'inner_nas': ('#FFCC00', '300µm'),
'inner_inf': ('#FFFF00', '290µm'),
'inner_temp': ('#AADD00', '275µm'),
'outer_sup': ('#44BB44', '265µm'),
'outer_nas': ('#228844', '260µm'),
'outer_inf': ('#2255FF', '230µm\nAtrophy'),
'outer_temp': ('#000088', '200µm\nSevere\natrophy'),
}
# Outer ring
for angle, (sector_col, lbl) in zip([90, 0, 270, 180],
[oct_data['outer_sup'], oct_data['outer_nas'],
oct_data['outer_inf'], oct_data['outer_temp']]):
wedge = Wedge((0, 0), 1.1, angle, angle + 90, width=0.45,
facecolor=sector_col, edgecolor='#333333', lw=0.8, zorder=2)
ax2.add_patch(wedge)
r = np.radians(angle + 45)
ax2.text(0.85 * np.cos(r), 0.85 * np.sin(r), lbl, ha='center', va='center',
fontsize=5.5, color='white', fontweight='bold', zorder=3)
# Inner ring
for angle, (sector_col, lbl) in zip([90, 0, 270, 180],
[oct_data['inner_sup'], oct_data['inner_nas'],
oct_data['inner_inf'], oct_data['inner_temp']]):
wedge = Wedge((0, 0), 0.65, angle, angle + 90, width=0.30,
facecolor=sector_col, edgecolor='#333333', lw=0.8, zorder=3)
ax2.add_patch(wedge)
r = np.radians(angle + 45)
ax2.text(0.50 * np.cos(r), 0.50 * np.sin(r), lbl, ha='center', va='center',
fontsize=5.5, color='black', fontweight='bold', zorder=4)
# Center
cen = Circle((0, 0), 0.35, facecolor=oct_data['center'][0], edgecolor='#333333', lw=1, zorder=4)
ax2.add_patch(cen)
ax2.text(0, 0, oct_data['center'][1], ha='center', va='center', fontsize=6.5,
color='white', fontweight='bold', zorder=5)
# OCT legend
oct_legend = [
('#FF0000', 'Thick / Severe edema (> 350µm)'),
('#FF8800', 'Moderately thick (> 320µm)'),
('#FFFF00', 'Mildly thick'),
('#44BB44', 'Normal range (~250-320µm)'),
('#2255FF', 'Thinned / Atrophic'),
('#000088', 'Severely thin (< 200µm)'),
]
for j, (c, lbl) in enumerate(oct_legend):
y_pos = -1.12 + j * 0.0
ax2.text(0, -1.10, 'RED/Orange = Thick/Edema | GREEN = Normal | BLUE/Black = Thin/Atrophy',
ha='center', fontsize=6, color='#8b949e')
# ── PANEL C: Glaucoma RNFL / VF traffic light ───────────────
ax3 = fig.add_axes([0.68, 0.52, 0.30, 0.40])
ax3.set_xlim(0, 3.0)
ax3.set_ylim(0, 3.5)
ax3.axis('off')
ax3.set_facecolor(BG)
ax3.text(1.5, 3.45, 'C. GLAUCOMA — TRAFFIC LIGHT SYSTEM', ha='center', va='top',
fontsize=9, fontweight='bold', color=ACCENT)
# Traffic light circles
for i, (tl_col, tl_text, tl_detail) in enumerate([
('#CC0000', 'RED\nOutside normal\nlimits', '< 1st percentile\nAbnormally thin RNFL\nGHT "Outside NL"'),
('#CC8800', 'YELLOW\nBorderline', '1st–5th percentile\nSuspect glaucoma\nGHT "Borderline"'),
('#00AA33', 'GREEN\nWithin normal\nlimits', '> 5th percentile\nNormal RNFL\nGHT "Within NL"'),
]):
y = 2.55 - i * 1.05
circ = Circle((0.45, y), 0.33, facecolor=tl_col, edgecolor='white', lw=1.5, zorder=3)
ax3.add_patch(circ)
ax3.text(0.45, y, ['✕', '?', '✓'][i], ha='center', va='center', fontsize=16,
color='white', fontweight='bold', zorder=4)
ax3.text(0.9, y + 0.15, tl_text, ha='left', va='center', fontsize=7.5,
color=tl_col, fontweight='bold', multialignment='left')
ax3.text(0.9, y - 0.22, tl_detail, ha='left', va='center', fontsize=6,
color='#8b949e', multialignment='left')
ax3.text(1.5, 0.25, 'WHITE = Abnormally THICK (papilledema)', ha='center',
fontsize=6.5, color='white')
rect_w = FancyBboxPatch((0.5, 0.05), 2.0, 0.18, boxstyle='round,pad=0.02',
facecolor='white', edgecolor='#888888', lw=1)
ax3.add_patch(rect_w)
ax3.text(1.5, 0.14, 'Disc edema / Papilledema', ha='center', va='center',
fontsize=6, color='black', fontweight='bold')
# ── PANEL D: HVF probability symbols ───────────────────────
ax4 = fig.add_axes([0.02, 0.06, 0.45, 0.42])
ax4.set_xlim(0, 5)
ax4.set_ylim(0, 3.5)
ax4.axis('off')
ax4.set_facecolor(BG)
ax4.text(2.5, 3.45, 'D. HUMPHREY VISUAL FIELD — Probability Symbols', ha='center', va='top',
fontsize=9, fontweight='bold', color=ACCENT)
hvf_data = [
('#FFFFFF', 'WHITE □', 'p > 5%\n(Normal)', 0.5),
('#BBBBBB', 'LIGHT GRAY ■', 'p < 5%\nMild depression', 1.2),
('#777777', 'GRAY ■', 'p < 2%\nModerate depression', 2.1),
('#333333', 'DARK GRAY ■', 'p < 1%\nSignificant depression', 3.0),
('#000000', 'BLACK ■', 'p < 0.5%\nAbsolute scotoma', 3.9),
]
for shade, name, meaning, x in hvf_data:
sq = FancyBboxPatch((x - 0.23, 1.8), 0.46, 0.90,
boxstyle='round,pad=0.04',
facecolor=shade, edgecolor='#555555', lw=1.2)
ax4.add_patch(sq)
ax4.text(x, 2.8, name, ha='center', va='bottom', fontsize=6.5,
color='#cccccc' if shade != '#FFFFFF' else '#333333', fontweight='bold')
ax4.text(x, 1.65, meaning, ha='center', va='top', fontsize=6,
color='#8b949e', multialignment='center')
ax4.text(2.5, 0.65, 'TOTAL DEVIATION / PATTERN DEVIATION maps use these shades', ha='center',
fontsize=7, color='#8b949e')
ax4.text(2.5, 0.30, 'GHT (Glaucoma Hemifield Test): Red = Outside NL | Yellow = Borderline | Green = Within NL',
ha='center', fontsize=7, color='#cccccc')
# ── PANEL E: OCT B-scan reflectivity ─────────────────────────
ax5 = fig.add_axes([0.50, 0.06, 0.47, 0.42])
ax5.axis('off')
ax5.set_facecolor(BG)
ax5.text(0.5, 0.98, 'E. OCT B-SCAN — Layer Reflectivity & False Colour', ha='center', va='top',
fontsize=9, fontweight='bold', color=ACCENT, transform=ax5.transAxes)
layers = [
('#FFFFFF', 'RNFL (Retinal Nerve Fibre Layer)', 'Hyper-reflective (bright white)'),
('#DDDDDD', 'GCL + IPL (Ganglion Cell / Inner Plexiform)', 'Moderately reflective'),
('#888888', 'INL (Inner Nuclear Layer)', 'Hypo-reflective (dark)'),
('#CCCCCC', 'OPL (Outer Plexiform Layer)', 'Moderately reflective'),
('#666666', 'ONL (Outer Nuclear Layer)', 'Hypo-reflective'),
('#EEEEEE', 'ELM (External Limiting Membrane)', 'Hyper-reflective line'),
('#DDDDDD', 'IS/OS (Ellipsoid Zone)', 'Bright hyper-reflective band — photoreceptor health'),
('#FFFFFF', 'RPE / Bruch\'s membrane', 'Strongest hyper-reflective band'),
('#111111', 'Choroid', 'Dark / hypo-reflective in standard mode'),
('#000000', 'Sclera / Vitreous / Subretinal fluid', 'Signal-poor / black'),
]
y_start = 0.88
for lyr_col, lyr_name, lyr_detail in layers:
swatch = FancyBboxPatch((0.03, y_start - 0.055), 0.06, 0.048,
boxstyle='round,pad=0.005',
facecolor=lyr_col, edgecolor='#555555', lw=0.8,
transform=ax5.transAxes, clip_on=False)
ax5.add_patch(swatch)
ax5.text(0.11, y_start - 0.030, lyr_name, ha='left', va='center', fontsize=7,
color='#cccccc', fontweight='bold', transform=ax5.transAxes)
ax5.text(0.60, y_start - 0.030, lyr_detail, ha='left', va='center', fontsize=6.5,
color='#8b949e', transform=ax5.transAxes)
y_start -= 0.072
add_watermark(fig)
return fig
# ═══════════════════════════════════════════════════════════════════════════════
# PAGE 5 – INSTRUMENTS, SUTURES, NEEDLES, LASERS, DYES
# ═══════════════════════════════════════════════════════════════════════════════
def page5_instruments():
fig = styled_fig(18, 14)
title_bar(fig, 'COLOUR CODING — SUTURES • NEEDLE GAUGES • SLIT LAMP FILTERS • LASERS • SURGICAL DYES',
'Surgical instruments, Equipment & Intraoperative Colour Systems')
# ── A: Suture colours ───────────────────────────────────────
ax_sut = fig.add_axes([0.01, 0.68, 0.37, 0.24])
ax_sut.axis('off')
ax_sut.set_facecolor(HEADER_BG)
ax_sut.text(0.5, 0.97, 'A. OPHTHALMIC SUTURE COLOUR CODING', ha='center', va='top',
fontsize=9, fontweight='bold', color=ACCENT, transform=ax_sut.transAxes)
sutures = [
('#E0D0B0', '10-0 Nylon', 'Clear/Colorless monofilament', 'Non-absorbable', 'Corneal wounds, PKP, phaco incision'),
('#8888AA', 'Prolene (Polypropylene)', 'BLUE monofilament', 'Non-absorbable', 'Scleral fixation of IOL, filtering surgery'),
('#9966CC', 'Vicryl (Polyglactin 910)', 'VIOLET', 'Absorbable 56–70d', 'Conjunctiva, muscle (strabismus), scleral closure'),
('#E0E0E0', 'Vicryl Rapide', 'Undyed (colourless)', 'Fast-absorb 10–14d', 'Skin sutures, lid repair'),
('#111111', 'Silk 4-0/5-0/6-0', 'BLACK', 'Non-absorbable', 'Skin, lid margin, traction sutures (visibility)'),
('#44AA44', 'Mersilene / Ethibond', 'GREEN (polyester)', 'Non-absorbable', 'Scleral buckling, muscle reattachment (strabismus)'),
('#7755BB', 'PDS (Polydioxanone)', 'VIOLET monofilament', 'Absorbable 180d', 'Scleral closure, retinal surgery'),
]
col_x = [0.02, 0.22, 0.40, 0.58, 0.74]
col_h = ['MATERIAL', 'COLOUR', 'TYPE', 'USE']
for cx, h in zip(col_x[1:], col_h):
ax_sut.text(cx, 0.87, h, ha='left', va='top', fontsize=6.5, fontweight='bold',
color='#8b949e', transform=ax_sut.transAxes)
y = 0.80
for (sut_col, name, colour_desc, absorbable, use) in sutures:
# swatch
sw = FancyBboxPatch((0.01, y - 0.08), 0.18, 0.070,
boxstyle='round,pad=0.01',
facecolor=sut_col, edgecolor='#555555', lw=0.8,
transform=ax_sut.transAxes, clip_on=False)
ax_sut.add_patch(sw)
ax_sut.text(0.10, y - 0.045, name, ha='center', va='center', fontsize=5.8,
color='black' if sut_col not in ['#111111', '#8888AA', '#9966CC', '#7755BB'] else 'white',
fontweight='bold', transform=ax_sut.transAxes)
ax_sut.text(0.22, y - 0.010, colour_desc, ha='left', va='top', fontsize=5.5,
color='#cccccc', transform=ax_sut.transAxes)
ax_sut.text(0.58, y - 0.010, absorbable, ha='left', va='top', fontsize=5.5,
color='#8b949e', transform=ax_sut.transAxes)
ax_sut.text(0.74, y - 0.010, use, ha='left', va='top', fontsize=5.5,
color='#8b949e', transform=ax_sut.transAxes)
y -= 0.110
# ── B: Needle gauge colours (ISO 6009) ─────────────────────
ax_ndl = fig.add_axes([0.40, 0.68, 0.28, 0.24])
ax_ndl.set_xlim(0, 3.5)
ax_ndl.set_ylim(0, 4.5)
ax_ndl.axis('off')
ax_ndl.set_facecolor(HEADER_BG)
ax_ndl.text(1.75, 4.42, 'B. NEEDLE GAUGE — ISO 6009 Hub Colour', ha='center', va='top',
fontsize=9, fontweight='bold', color=ACCENT)
needles = [
('18G', '#FF88A8', '1.2mm', 'Paracentesis, AC taps'),
('20G', '#FFD700', '0.9mm', 'Vitreous tap, old PPV'),
('21G', '#006400', '0.8mm', 'Subconjunctival injection'),
('22G', '#111111', '0.7mm', 'Peribulbar / sub-Tenon\'s'),
('23G', '#003087', '0.6mm', '23G vitrectomy system'),
('25G', '#FF7F00', '0.5mm', '★ INTRAVITREAL INJECTIONS (anti-VEGF)'),
('26G', '#8B4513', '0.45mm', 'Sub-Tenon\'s anaesthesia'),
('27G', '#888888', '0.4mm', 'Fine intravitreal, AC cannulas'),
('30G', '#FFD700', '0.3mm', 'AC irrigation, hydrodissection'),
]
for i, (gauge, hub_col, diam, use) in enumerate(needles):
y = 4.05 - i * 0.42
# Hub (coloured cylinder)
hub = FancyBboxPatch((0.05, y - 0.16), 0.40, 0.28,
boxstyle='round,pad=0.03',
facecolor=hub_col, edgecolor='#888888', lw=1)
ax_ndl.add_patch(hub)
# Needle shaft
ax_ndl.plot([0.45, 1.10], [y, y], color='#CCCCCC', lw=2.0)
# Text
ax_ndl.text(0.25, y, gauge, ha='center', va='center', fontsize=7.5,
color='black' if hub_col in ['#FFD700', '#FF88A8', '#FF7F00', '#FF7F00'] else 'white',
fontweight='bold')
ax_ndl.text(1.15, y + 0.08, diam, ha='left', va='bottom', fontsize=6, color='#cccccc')
ax_ndl.text(1.15, y - 0.10, use, ha='left', va='top', fontsize=5.8, color='#8b949e')
# ── C: Slit lamp filters ────────────────────────────────────
ax_sl = fig.add_axes([0.70, 0.68, 0.28, 0.24])
ax_sl.set_xlim(0, 3.5)
ax_sl.set_ylim(0, 4.0)
ax_sl.axis('off')
ax_sl.set_facecolor(HEADER_BG)
ax_sl.text(1.75, 3.95, 'C. SLIT LAMP FILTERS', ha='center', va='top',
fontsize=9, fontweight='bold', color=ACCENT)
filters = [
('#FFFFFF', 'White\n(Unfiltered)', 'General examination\nAll structures'),
('#4477FF', 'Cobalt Blue\n(450–490nm)', 'Fluorescein staining\nSeidel test, tonometry\nContact lens fitting'),
('#44AA44', 'Red-Free\n(Green, ~540nm)', 'RNFL defects (appear dark)\nHemorrhages & vessels\nNerve fibre layer'),
('#FFFF00', 'Yellow barrier\n(>530nm)', 'Blocks blue exciter light\nTransmits fluorescence only'),
('#888888', 'Neutral Density\n(Grey)', 'Reduces light intensity\nPhotophobic patients\nDilated pupils'),
('#FFFFFF', 'Diffuser\n(White screen)', 'External examination\nEyelids, adnexa'),
]
y = 3.60
for f_col, f_name, f_use in filters:
circ = Circle((0.30, y - 0.15), 0.20, facecolor=f_col, edgecolor='#555555', lw=1.2, zorder=3)
ax_sl.add_patch(circ)
ax_sl.text(0.60, y - 0.03, f_name, ha='left', va='top', fontsize=6,
color='#cccccc', fontweight='bold', multialignment='left')
ax_sl.text(1.40, y - 0.03, f_use, ha='left', va='top', fontsize=5.5,
color='#8b949e', multialignment='left')
y -= 0.58
# ── D: Laser wavelengths ────────────────────────────────────
ax_las = fig.add_axes([0.01, 0.34, 0.55, 0.30])
ax_las.axis('off')
ax_las.set_facecolor(HEADER_BG)
ax_las.text(0.5, 0.98, 'D. OPHTHALMIC LASERS & WAVELENGTHS', ha='center', va='top',
fontsize=9, fontweight='bold', color=ACCENT, transform=ax_las.transAxes)
lasers = [
('UV\n193nm', '#DDBBFF', 'Excimer (ArF)', 'Invisible UV', 'LASIK, PRK, LASEK, SMILE\nPhotoablation of corneal stroma'),
('Blue-green\n488/514nm', '#66AAFF', 'Argon', 'Blue-green visible', 'PRP (panretinal photocoagulation)\nFocal laser for DME\nALT (trabeculoplasty)'),
('Green\n532nm', '#44DD44', 'Nd:YAG\n(frequency doubled)\nPASCAL/SLT', 'Bright green', 'SLT (glaucoma)\nMacular laser, PRP\nPattern scan laser'),
('Yellow\n577nm', '#FFFF00', 'Micropulse\nyellow', 'Yellow visible', 'Subthreshold macular laser\nDME, CSR\n(No visible burns)'),
('Red\n647nm', '#FF3333', 'Krypton', 'Red visible', 'Subretinal membranes\nJuxtafoveal CNV\n(spares inner retina)'),
('NIR\n810nm', '#880000', 'Diode', 'Invisible NIR\n(aiming beam = red)', 'Cyclophotocoagulation (CPC)\nRetinopexy, TTT'),
('NIR\n1064nm', '#440000', 'Nd:YAG\n(Q-switched)', 'Invisible NIR\n(aiming beam = He:Ne red)', 'Posterior capsulotomy (PCO)\nLaser iridotomy, vitreolysis'),
]
col_positions = [0.01, 0.14, 0.30, 0.45, 0.62]
col_heads = ['BAND / λ', 'COLOUR BAND', 'LASER TYPE', 'VISIBLE?', 'OPHTHALMIC USE']
for cx, h in zip(col_positions, col_heads):
ax_las.text(cx, 0.90, h, ha='left', va='top', fontsize=6.5,
fontweight='bold', color='#8b949e', transform=ax_las.transAxes)
y = 0.84
step = 0.116
for (band, col_hex, laser_type, visible, use) in lasers:
swatch = FancyBboxPatch((col_positions[1], y - step * 0.85), 0.13, step * 0.80,
boxstyle='round,pad=0.008',
facecolor=col_hex, edgecolor='#555555', lw=0.8,
transform=ax_las.transAxes, clip_on=False)
ax_las.add_patch(swatch)
ax_las.text(col_positions[0], y - 0.010, band, ha='left', va='top', fontsize=6,
color='#cccccc', fontweight='bold', transform=ax_las.transAxes)
ax_las.text(col_positions[2], y - 0.010, laser_type, ha='left', va='top', fontsize=6,
color='#cccccc', transform=ax_las.transAxes)
ax_las.text(col_positions[3], y - 0.010, visible, ha='left', va='top', fontsize=5.5,
color='#8b949e', transform=ax_las.transAxes, multialignment='left')
ax_las.text(col_positions[4], y - 0.010, use, ha='left', va='top', fontsize=5.8,
color='#8b949e', transform=ax_las.transAxes, multialignment='left')
y -= step
# ── E: Chromovitrectomy / surgical dyes ────────────────────
ax_dye = fig.add_axes([0.58, 0.34, 0.40, 0.30])
ax_dye.axis('off')
ax_dye.set_facecolor(HEADER_BG)
ax_dye.text(0.5, 0.98, 'E. CHROMOVITRECTOMY — SURGICAL DYES', ha='center', va='top',
fontsize=9, fontweight='bold', color=ACCENT, transform=ax_dye.transAxes)
dyes = [
('#3355CC', 'Trypan Blue\n(Vision Blue)', 'BLUE', 'Anterior capsule (CCC)\nILM staining'),
('#2244AA', 'Brilliant Blue G\n(BBG)', 'BLUE', 'ILM staining (SAFER than ICG)\nMacular hole surgery'),
('#00AA44', 'Indocyanine Green\n(ICG)', 'GREEN\n(NIR)', 'ILM & ERM peeling\nCaution: retinal toxicity'),
('#FFFFFF', 'Triamcinolone\nAcetonide', 'WHITE/opaque', 'Vitreous visualization\nConfirms complete vitreous removal'),
('#2244AA', 'Membrane Blue-Dual\n(Dual-stain)', 'Blue+Yellow', 'Blue = ILM\nYellow = ERM\n(Differential staining)'),
('#DD8800', 'Sodium Fluorescein', 'YELLOW-GREEN', 'FFA / AF\nCorneal staining (slit lamp)'),
]
y = 0.90
for (d_col, d_name, d_colour, d_use) in dyes:
swatch = FancyBboxPatch((0.02, y - 0.130), 0.14, 0.115,
boxstyle='round,pad=0.008',
facecolor=d_col, edgecolor='#555555', lw=1,
transform=ax_dye.transAxes, clip_on=False)
ax_dye.add_patch(swatch)
ax_dye.text(0.09, y - 0.070, d_colour, ha='center', va='center', fontsize=6,
color='black' if d_col in ['#FFFFFF', '#DD8800'] else 'white',
fontweight='bold', transform=ax_dye.transAxes)
ax_dye.text(0.18, y - 0.015, d_name, ha='left', va='top', fontsize=7,
color='#cccccc', fontweight='bold', transform=ax_dye.transAxes)
ax_dye.text(0.55, y - 0.015, d_use, ha='left', va='top', fontsize=6,
color='#8b949e', transform=ax_dye.transAxes, multialignment='left')
y -= 0.148
# ── F: Trial lens box ───────────────────────────────────────
ax_tr = fig.add_axes([0.01, 0.04, 0.96, 0.26])
ax_tr.set_xlim(0, 10)
ax_tr.set_ylim(0, 2.8)
ax_tr.axis('off')
ax_tr.set_facecolor(HEADER_BG)
ax_tr.text(5.0, 2.72, 'F. TRIAL LENS BOX • ACCESSORY COLOUR CODING',
ha='center', va='top', fontsize=9, fontweight='bold', color=ACCENT)
trial_items = [
('#DDDDDD', 'White / Silver\nRim', 'PLUS (+)\nSpheres', 'Convex lenses\n+0.12 to +20.00D\nFor hyperopia, presbyopia'),
('#222222', 'Black / Dark\nRim', 'MINUS (−)\nSpheres', 'Concave lenses\n−0.12 to −20.00D\nFor myopia'),
('#CC3333', 'Red Rim', 'PLUS\nCylinders', 'Plus cylinder lenses\nFor astigmatism correction'),
('#CC3333', 'Red', 'Maddox Rod', 'Dissociation test\nHeterophoria / tropia\nRed streak vs white dot'),
('#CC3333', 'Red Filter', 'RED filter', 'Worth 4-dot test\n(one eye sees red dots)'),
('#33AA33', 'Green Filter', 'GREEN filter', 'Worth 4-dot test\n(other eye sees green)\nBinocular vision testing'),
('#222222', 'Black opaque', 'Occluder', 'Cover test\nMonocular testing\nFusion dissociation'),
('#AAAAAA', 'Black with\nnarrow slit', 'Stenopaeic\nSlit', 'Locating astigmatism axis\nIrregular astigmatism'),
('#EEEEEE', 'Clear', 'Pinhole', 'Differentiates refractive\nerror from pathology'),
('#EEEEEE', 'Clear / Plano', 'Plano Lens\n(0D)', 'Malingering detection\nRefractive baseline'),
]
x_start = 0.10
x_step = 0.98
for i, (t_col, t_rim, t_name, t_use) in enumerate(trial_items):
x = x_start + i * x_step
# Lens circle
lens = Circle((x, 1.75), 0.38, facecolor=t_col, edgecolor='#888888', lw=2, zorder=3)
ax_tr.add_patch(lens)
ax_tr.text(x, 1.75, t_rim.split('\n')[0], ha='center', va='center', fontsize=6.0,
color='black' if t_col in ['#DDDDDD', '#CC3333', '#AAAAAA', '#EEEEEE', '#33AA33'] else 'white',
fontweight='bold', zorder=4)
ax_tr.text(x, 1.22, t_name, ha='center', va='top', fontsize=6.5,
color='#FFD700', fontweight='bold', multialignment='center')
ax_tr.text(x, 0.58, t_use, ha='center', va='top', fontsize=5.4,
color='#8b949e', multialignment='center')
add_watermark(fig)
return fig
# ═══════════════════════════════════════════════════════════════════════════════
# GENERATE PDF
# ═══════════════════════════════════════════════════════════════════════════════
output_path = '/tmp/workspace/ophthalmology-colour-coding/Colour_Coding_Ophthalmology.pdf'
with PdfPages(output_path) as pdf:
print('Generating page 1: Drug bottle caps...')
fig1 = page1_drug_caps()
pdf.savefig(fig1, bbox_inches='tight', dpi=150)
plt.close(fig1)
print('Generating page 2: Anterior segment...')
fig2 = page2_anterior_segment()
pdf.savefig(fig2, bbox_inches='tight', dpi=150)
plt.close(fig2)
print('Generating page 3: Posterior segment...')
fig3 = page3_posterior_segment()
pdf.savefig(fig3, bbox_inches='tight', dpi=150)
plt.close(fig3)
print('Generating page 4: Imaging (topography, OCT, VF)...')
fig4 = page4_imaging()
pdf.savefig(fig4, bbox_inches='tight', dpi=150)
plt.close(fig4)
print('Generating page 5: Instruments, sutures, lasers, dyes...')
fig5 = page5_instruments()
pdf.savefig(fig5, bbox_inches='tight', dpi=150)
plt.close(fig5)
d = pdf.infodict()
d['Title'] = 'Colour Coding in Ophthalmology — Complete Schematic Guide'
d['Author'] = 'Orris Medical AI'
d['Subject'] = 'Ophthalmology — Clinical Colour Coding Reference'
print(f'PDF saved to {output_path}')