ENT eai anatomy handwriting pdf colour full
ENT ear anatomy handwritten colour PDF notes free download
ENT ear anatomy handwritten notes coloured PDF medical students
Create a structured ENT ear anatomy PDF with colour formatting
mkdir -p /tmp/workspace/ent-ear-anatomy && ls /tmp/workspace/ent-ear-anatomy/
~/ent-ear-anatomy/generate_ear_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether, ListFlowable, ListItem, PageBreak
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate
from reportlab.pdfgen import canvas as pdfcanvas
from reportlab.lib.colors import HexColor
OUTPUT = "/tmp/workspace/ent-ear-anatomy/ENT_Ear_Anatomy.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
C_DEEP_BLUE = HexColor("#1A3A5C") # title / major headings
C_TEAL = HexColor("#0B7A75") # section banners
C_ORANGE = HexColor("#E07B39") # sub-section headings
C_GOLD = HexColor("#F4B942") # accent / key-point boxes
C_LIGHT_TEAL = HexColor("#D0EFED") # section banner bg
C_LIGHT_ORANGE= HexColor("#FFF0E6") # sub-section bg
C_LIGHT_BLUE = HexColor("#EBF3FA") # table alternating row
C_KEY_BG = HexColor("#FFFBE6") # key-points background
C_RED = HexColor("#C0392B") # clinical notes
C_LIGHT_RED = HexColor("#FDEDEC") # clinical box bg
C_GREEN = HexColor("#1D6A3A") # mnemonic headings
C_LIGHT_GREEN = HexColor("#E8F8F0") # mnemonic box bg
C_WHITE = colors.white
C_BLACK = colors.black
C_GRAY = HexColor("#555555")
C_LIGHT_GRAY = HexColor("#F2F2F2")
# ── Page template with header/footer ────────────────────────────────────────
def make_page(canvas, doc):
canvas.saveState()
w, h = A4
# Top stripe
canvas.setFillColor(C_DEEP_BLUE)
canvas.rect(0, h - 18*mm, w, 18*mm, fill=1, stroke=0)
canvas.setFillColor(C_WHITE)
canvas.setFont("Helvetica-Bold", 11)
canvas.drawString(15*mm, h - 12*mm, "ENT EAR ANATOMY")
canvas.setFont("Helvetica", 9)
canvas.drawRightString(w - 15*mm, h - 12*mm, "Cummings Otolaryngology | Gray's Anatomy")
# Bottom stripe
canvas.setFillColor(C_DEEP_BLUE)
canvas.rect(0, 0, w, 10*mm, fill=1, stroke=0)
canvas.setFillColor(C_GOLD)
canvas.setFont("Helvetica-Bold", 8)
canvas.drawCentredString(w / 2, 3.5*mm, f"Page {doc.page}")
canvas.restoreState()
# ── Document ─────────────────────────────────────────────────────────────────
doc = BaseDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=18*mm,
rightMargin=18*mm,
topMargin=24*mm,
bottomMargin=18*mm,
title="ENT Ear Anatomy",
author="Orris Medical AI",
subject="Structured colour notes on ear anatomy",
)
frame = Frame(
doc.leftMargin, doc.bottomMargin,
A4[0] - doc.leftMargin - doc.rightMargin,
A4[1] - doc.topMargin - doc.bottomMargin,
id="main"
)
doc.addPageTemplates([PageTemplate(id="main", frames=frame, onPage=make_page)])
# ── Styles ───────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()
def S(name, parent="Normal", **kw):
return ParagraphStyle(name, parent=base[parent], **kw)
title_s = S("Title", "Normal",
fontName="Helvetica-Bold", fontSize=26, textColor=C_DEEP_BLUE,
spaceAfter=4, leading=30, alignment=TA_CENTER)
subtitle_s = S("Subtitle", "Normal",
fontName="Helvetica", fontSize=13, textColor=C_TEAL,
spaceAfter=2, leading=16, alignment=TA_CENTER)
banner_s = S("Banner", "Normal",
fontName="Helvetica-Bold", fontSize=14, textColor=C_WHITE,
spaceAfter=0, leading=18, leftIndent=4)
sub_s = S("Sub", "Normal",
fontName="Helvetica-Bold", fontSize=11, textColor=C_ORANGE,
spaceAfter=3, leading=14, leftIndent=2)
body_s = S("Body", "Normal",
fontName="Helvetica", fontSize=9.5, textColor=C_GRAY,
spaceAfter=4, leading=14, alignment=TA_JUSTIFY)
bullet_s = S("Bullet", "Normal",
fontName="Helvetica", fontSize=9.5, textColor=C_GRAY,
spaceAfter=2, leading=13, leftIndent=12, bulletIndent=4)
kp_s = S("KP", "Normal",
fontName="Helvetica", fontSize=9, textColor=C_DEEP_BLUE,
spaceAfter=3, leading=13, leftIndent=8)
clin_s = S("Clin", "Normal",
fontName="Helvetica-Oblique", fontSize=9, textColor=C_RED,
spaceAfter=3, leading=13, leftIndent=8)
mnem_s = S("Mnem", "Normal",
fontName="Helvetica-Bold", fontSize=9, textColor=C_GREEN,
spaceAfter=3, leading=13, leftIndent=8)
label_s = S("Label", "Normal",
fontName="Helvetica-Bold", fontSize=9, textColor=C_DEEP_BLUE,
leading=12)
val_s = S("Val", "Normal",
fontName="Helvetica", fontSize=9, textColor=C_GRAY,
leading=12)
tbl_head_s = S("TblHead", "Normal",
fontName="Helvetica-Bold", fontSize=9, textColor=C_WHITE,
leading=12, alignment=TA_CENTER)
tbl_cell_s = S("TblCell", "Normal",
fontName="Helvetica", fontSize=8.5, textColor=C_GRAY,
leading=12)
# ── Helper builders ──────────────────────────────────────────────────────────
def section_banner(text):
"""Coloured banner for major section."""
t = Table([[Paragraph(text, banner_s)]], colWidths=[174*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_TEAL),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("ROUNDEDCORNERS", [4,4,4,4]),
]))
return t
def sub_heading(text):
t = Table([[Paragraph(text, sub_s)]], colWidths=[174*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_LIGHT_ORANGE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("LINEBELOW", (0,0), (-1,-1), 1, C_ORANGE),
]))
return t
def key_points_box(points):
rows = [[Paragraph("⭐ KEY POINTS", S("KPH","Normal",
fontName="Helvetica-Bold", fontSize=10, textColor=C_GOLD,
leading=13))]]
for p in points:
rows.append([Paragraph(f"• {p}", kp_s)])
t = Table(rows, colWidths=[174*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_KEY_BG),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 1.5, C_GOLD),
("LINEBELOW", (0,0), (0,0), 1, C_GOLD),
]))
return t
def clinical_box(points):
rows = [[Paragraph("🩺 CLINICAL NOTES", S("CN","Normal",
fontName="Helvetica-Bold", fontSize=10, textColor=C_RED,
leading=13))]]
for p in points:
rows.append([Paragraph(f"• {p}", clin_s)])
t = Table(rows, colWidths=[174*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_LIGHT_RED),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 1.5, C_RED),
]))
return t
def mnemonic_box(title, content):
rows = [
[Paragraph(f"💡 MNEMONIC: {title}", S("MH","Normal",
fontName="Helvetica-Bold", fontSize=10, textColor=C_GREEN,
leading=13))],
[Paragraph(content, mnem_s)],
]
t = Table(rows, colWidths=[174*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_LIGHT_GREEN),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 1.5, C_GREEN),
]))
return t
def two_col_table(headers, rows_data, col_widths=None):
if col_widths is None:
col_widths = [60*mm, 114*mm]
header_row = [Paragraph(h, tbl_head_s) for h in headers]
table_rows = [header_row]
for i, row in enumerate(rows_data):
bg = C_LIGHT_BLUE if i % 2 == 0 else C_WHITE
table_rows.append([Paragraph(str(c), tbl_cell_s) for c in row])
t = Table(table_rows, colWidths=col_widths)
style = [
("BACKGROUND", (0, 0), (-1, 0), C_DEEP_BLUE),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [C_LIGHT_BLUE, C_WHITE]),
("GRID", (0, 0), (-1, -1), 0.5, HexColor("#CCCCCC")),
("TOPPADDING", (0, 0), (-1, -1), 4),
("BOTTOMPADDING", (0, 0), (-1, -1), 4),
("LEFTPADDING", (0, 0), (-1, -1), 6),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
]
t.setStyle(TableStyle(style))
return t
def sp(n=4):
return Spacer(1, n*mm)
def hr():
return HRFlowable(width="100%", thickness=0.5, color=HexColor("#CCCCCC"), spaceAfter=2*mm)
def bp(text):
return Paragraph(f"<bullet>•</bullet> {text}", bullet_s)
# ── CONTENT ──────────────────────────────────────────────────────────────────
story = []
# =========== COVER ===========
story += [
sp(20),
Paragraph("ENT EAR ANATOMY", title_s),
sp(2),
Paragraph("Structured Colour Notes for Medical Students", subtitle_s),
sp(1),
Paragraph("Based on Cummings Otolaryngology & Gray's Anatomy", subtitle_s),
sp(8),
HRFlowable(width="60%", thickness=3, color=C_GOLD, spaceAfter=6*mm),
sp(2),
]
# Quick-reference box on cover
cover_data = [
["Section", "Topic"],
["1", "Overview of the Ear"],
["2", "Temporal Bone Osteology"],
["3", "External Ear (Auricle + EAC)"],
["4", "Tympanic Membrane"],
["5", "Middle Ear (Tympanic Cavity)"],
["6", "Ossicular Chain"],
["7", "Eustachian Tube"],
["8", "Inner Ear (Cochlea + Vestibule)"],
["9", "Nerve Supply of the Ear"],
["10", "Blood Supply of the Ear"],
["11", "Embryology Summary"],
["12", "Clinical Correlations"],
]
cover_tbl = Table(cover_data, colWidths=[20*mm, 140*mm])
cover_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_DEEP_BLUE),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 10),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_LIGHT_BLUE, C_WHITE]),
("FONTNAME", (0,1), (-1,-1), "Helvetica"),
("FONTSIZE", (0,1), (-1,-1), 9.5),
("GRID", (0,0), (-1,-1), 0.5, HexColor("#CCCCCC")),
("ALIGN", (0,0), (0,-1), "CENTER"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
]))
story += [cover_tbl, sp(6)]
story.append(PageBreak())
# =========== SECTION 1: OVERVIEW ===========
story += [section_banner("SECTION 1 — OVERVIEW OF THE EAR"), sp(3)]
story.append(Paragraph(
"The ear is a complex sensory organ responsible for both hearing (audition) and balance (vestibular function). "
"It is divided into three anatomically and functionally distinct regions: the external ear, middle ear, and inner ear. "
"All three regions are housed within the temporal bone of the skull.",
body_s))
story += [sp(3)]
# Overview table
story.append(two_col_table(
["Region", "Components & Function"],
[
["External Ear", "Auricle (pinna) + External auditory canal (EAC). Collects and funnels sound waves. Acoustic → kinetic energy transfer."],
["Middle Ear (Tympanic Cavity)", "Tympanic membrane (TM), ossicles (malleus, incus, stapes), Eustachian tube, mastoid air cells. Amplifies and transmits vibrations."],
["Inner Ear (Labyrinth)", "Bony labyrinth: vestibule, semicircular canals, cochlea. Membranous labyrinth within. Converts vibration → electrical impulse (hair cells)."],
],
col_widths=[50*mm, 124*mm]
))
story += [sp(3)]
story.append(key_points_box([
"Outer ear: acoustic → kinetic energy",
"Middle ear: increases kinetic energy ~18× (impedance matching)",
"Inner ear: kinetic → hydraulic → electrical energy",
"Two sensory organs in inner ear: Organ of Corti (hearing) + Macula/Crista (balance)",
]))
story += [sp(4)]
# =========== SECTION 2: TEMPORAL BONE ===========
story += [section_banner("SECTION 2 — TEMPORAL BONE OSTEOLOGY"), sp(3)]
story.append(Paragraph(
"The temporal bone forms part of the lateral skull base and houses the entire auditory and vestibular apparatus. "
"It articulates with the sphenoid, parietal, occipital, and zygomatic bones.",
body_s))
story += [sp(3), sub_heading("Four Parts of the Temporal Bone"), sp(2)]
story.append(two_col_table(
["Part", "Key Features"],
[
["Squamous", "Thin, flat lateral plate. Forms roof of infratemporal fossa. Contains temporal line (~5 mm below middle fossa floor)."],
["Mastoid", "Posterior part. Contains mastoid air cells (pneumatised). MacEwen triangle: cribriform area posterior to spine of Henle - marks mastoid antrum."],
["Petrous", "Dense, pyramidal. Houses inner ear structures. Contains internal auditory canal (IAC), jugular foramen, carotid canal."],
["Tympanic", "Curved plate forming anterior, inferior and posterior walls of EAC. Forms tympanic ring (sulcus for TM)."],
],
col_widths=[40*mm, 134*mm]
))
story += [sp(3)]
story.append(clinical_box([
"MacEwen triangle - surgical landmark for mastoid antrum (cortical mastoidectomy entry point).",
"Temporal line: ~5 mm below middle fossa floor - safe reference for dissection.",
"Stylomastoid foramen: located at anterior limit of digastric groove - facial nerve exits here.",
"Arcuate eminence: prominence of superior SCC visible on middle fossa floor.",
]))
story += [sp(4)]
# =========== SECTION 3: EXTERNAL EAR ===========
story += [section_banner("SECTION 3 — EXTERNAL EAR"), sp(3)]
story += [sub_heading("3.1 Auricle (Pinna)"), sp(2)]
story.append(Paragraph(
"The auricle is a funnel-shaped cartilaginous structure that is continuous with the external auditory canal. "
"Its framework is elastic fibrocartilage covered by tightly adherent perichondrium and skin.",
body_s))
story += [sp(2)]
auricle_data = [
["Structure", "Description"],
["Helix", "Curved outer rim of auricle"],
["Antihelix", "Inner curved ridge parallel to helix; bifurcates superiorly into crura"],
["Tragus", "Small projection anterior to EAC opening"],
["Antitragus", "Small projection opposite to tragus"],
["Concha", "Deep bowl-shaped depression leading to EAC"],
["Fossa triangularis", "Triangular depression between crura of antihelix"],
["Scapha", "Groove between helix and antihelix"],
["Lobule", "Inferior, fat-filled, non-cartilaginous portion"],
["Cymba conchae", "Superior part of concha; bounded by crus of helix"],
]
story.append(two_col_table(auricle_data[0], auricle_data[1:], col_widths=[55*mm, 119*mm]))
story += [sp(3)]
story.append(mnemonic_box(
"Auricular Hillocks of His",
"Hillocks 1-3 from 1st arch → Tragus, Helix crus, Helix\n"
"Hillocks 4-6 from 2nd arch → Antihelix, Antitragus, Lobule\n"
"Memory: '1st arch = Tragus & Helix (T-H); 2nd arch = Antihelix to Lobule (A-L)'"
))
story += [sp(3)]
story += [sub_heading("3.2 External Auditory Canal (EAC)"), sp(2)]
story.append(Paragraph(
"The EAC is approximately 2.5 cm in length and is S-shaped. It extends from the concha of the auricle "
"to the tympanic membrane.",
body_s))
story += [sp(2)]
eac_data = [
["Feature", "Detail"],
["Length", "~2.5 cm total"],
["Outer 1/3 (Cartilaginous)", "Lateral third. Skin is thick and mobile. Contains sebaceous glands, apocrine (ceruminous) glands, hair follicles."],
["Inner 2/3 (Bony)", "Medial two-thirds. Skin is thin, immobile, no glands/hair. Continuous with TM epithelium."],
["Isthmus", "Bony-cartilaginous junction; narrowest point of EAC. Site of malignant otitis externa granulations."],
["Foramen of Huschke", "Incomplete ossification of anterior bony canal → opening to infratemporal fossa. Pathway for tumour spread to parotid."],
["Fissures of Santorini", "Natural defects in cartilaginous EAC → route to superficial parotid lobe."],
["Direction", "Lateral portion: directed upward, backward. To straighten EAC: pull pinna up and back (adult), down and back (child)."],
]
story.append(two_col_table(eac_data[0], eac_data[1:], col_widths=[55*mm, 119*mm]))
story += [sp(3)]
story.append(clinical_box([
"Malignant otitis externa: granulation at bony-cartilaginous junction is pathognomonic.",
"Failed involution of meatal plug → canal atresia with conductive hearing loss.",
"En bloc resection needed for EAC malignancies due to spread via foramen of Huschke and fissures of Santorini.",
]))
story += [sp(4), PageBreak()]
# =========== SECTION 4: TYMPANIC MEMBRANE ===========
story += [section_banner("SECTION 4 — TYMPANIC MEMBRANE (TM)"), sp(3)]
story.append(Paragraph(
"The tympanic membrane (eardrum) forms the medial wall of the EAC and the lateral wall of the middle ear. "
"It is a four-layered, concave, pearlescent membrane that vibrates in response to sound waves.",
body_s))
story += [sp(3)]
story += [sub_heading("4.1 Layers of the TM"), sp(2)]
story.append(two_col_table(
["Layer", "Details"],
[
["Outer (Epithelial)", "Keratinising stratified squamous epithelium; continuous with EAC skin"],
["Outer Fibrous (Radiate)", "Fibres radiate from umbo/manubrium outward — provides structural support"],
["Inner Fibrous (Circular)", "Circumferential arrangement at periphery; integrates with annular ligament"],
["Inner (Mucosal)", "Simple cuboidal/squamous mucosa; continuous with middle ear mucosa"],
],
col_widths=[55*mm, 119*mm]
))
story += [sp(3)]
story += [sub_heading("4.2 Landmarks of the TM"), sp(2)]
story.append(two_col_table(
["Landmark", "Description"],
[
["Umbo", "Central depression; tip of malleus manubrium attaches here"],
["Mallear stria", "Light streak from umbo to lateral process of malleus (manubrium visible through TM)"],
["Lateral process (short process)", "Small projection of malleus; creates anterior & posterior mallear folds"],
["Anterior mallear fold", "Superior demarcation between pars flaccida and pars tensa (anteriorly)"],
["Posterior mallear fold", "Superior demarcation between pars flaccida and pars tensa (posteriorly)"],
["Pars tensa", "Inferior, thicker portion; has all 4 layers; taut due to fibrous layers"],
["Pars flaccida (Shrapnell's membrane)", "Superior, flaccid; lacks fibrous layer; attached to notch of Rivinus"],
["Annular ligament", "Fibrocartilaginous ring anchoring TM periphery to tympanic sulcus"],
["Light reflex (cone of light)", "Triangular reflection: anterior-inferior quadrant; absent in otitis media"],
["Tympanic annulus", "Fibrocartilaginous ring; absent superiorly at notch of Rivinus"],
],
col_widths=[65*mm, 109*mm]
))
story += [sp(3)]
story.append(mnemonic_box(
"TM Quadrants",
"Divided into 4 quadrants by manubrium (vertical) + horizontal line through umbo:\n"
"Antero-superior | Antero-inferior | Postero-superior | Postero-inferior\n"
"Light reflex = Antero-inferior | Incudostapedial joint visible = Postero-inferior\n"
"Chorda tympani = Postero-superior | Round window shadow = visible through pars tensa"
))
story += [sp(3)]
story.append(clinical_box([
"Pars flaccida: most common site for acquired cholesteatoma (lacks fibrous layer, weakest).",
"Cone of light lost in otitis media with effusion / middle ear effusion.",
"Traumatic perforation: usually pars tensa (large central perforations); pars flaccida → cholesteatoma.",
"Retraction pockets of pars flaccida are the earliest sign of attic cholesteatoma.",
]))
story += [sp(4), PageBreak()]
# =========== SECTION 5: MIDDLE EAR ===========
story += [section_banner("SECTION 5 — MIDDLE EAR (TYMPANIC CAVITY)"), sp(3)]
story.append(Paragraph(
"The middle ear (tympanic cavity) is an air-filled space within the temporal bone connecting the "
"nasopharynx (via Eustachian tube) to the mastoid air cells (via the aditus and antrum). "
"Its epithelial lining is columnar ciliated (near ET) and pavement epithelium elsewhere.",
body_s))
story += [sp(3)]
story += [sub_heading("5.1 Boundaries of the Tympanic Cavity"), sp(2)]
story.append(two_col_table(
["Wall", "Boundary & Contents"],
[
["Lateral (membranous)", "Tympanic membrane (pars tensa + pars flaccida); bony tympanic ring superiorly"],
["Medial (labyrinthine)", "Promontory (basal cochlea); oval window (with stapes footplate); round window (secondary TM); facial nerve canal (horizontal); lateral semicircular canal prominence"],
["Roof (tegmental)", "Tegmen tympani — thin plate of petrous bone separating middle ear from middle cranial fossa"],
["Floor (jugular)", "Thin plate overlying jugular bulb; contains tympanic branch of IX (Jacobson's nerve)"],
["Anterior (carotid)", "Eustachian tube opening (superiorly); carotid canal below; tensor tympani muscle canal"],
["Posterior (mastoid)", "Aditus ad antrum (→ mastoid antrum); pyramid (contains stapedius muscle); chorda tympani enters here"],
],
col_widths=[50*mm, 124*mm]
))
story += [sp(3)]
story += [sub_heading("5.2 Divisions of the Tympanic Cavity"), sp(2)]
story.append(two_col_table(
["Division", "Level", "Contents"],
[
["Epitympanum (Attic)", "Above level of TM", "Head of malleus, body of incus, ossicular ligaments, chorda tympani"],
["Mesotympanum", "Level of TM (pars tensa)", "Manubrium, long process of incus, stapes, oval window, round window"],
["Hypotympanum", "Below level of TM", "Floor; jugular bulb nearby"],
],
col_widths=[40*mm, 40*mm, 94*mm]
))
story += [sp(3)]
story.append(clinical_box([
"Tegmen tympani erosion: middle fossa CSF leak or meningitis.",
"High jugular bulb (on floor): risk of bleeding during myringotomy.",
"Promontory biopsy: do NOT biopsy without imaging — aberrant carotid artery or glomus tumour risk.",
"Epitympanum and mesotympanum separated by ossicular chain → narrow communication (important in cholesteatoma spread).",
]))
story += [sp(4), PageBreak()]
# =========== SECTION 6: OSSICULAR CHAIN ===========
story += [section_banner("SECTION 6 — OSSICULAR CHAIN"), sp(3)]
story.append(Paragraph(
"The ossicular chain transmits sound vibrations from the TM to the oval window of the inner ear. "
"It consists of three bones: the malleus, incus, and stapes — the three smallest bones in the human body.",
body_s))
story += [sp(3)]
story.append(two_col_table(
["Ossicle", "Parts", "Attachments & Notes"],
[
["Malleus (Hammer)", "Head, neck, manubrium (handle), lateral process, anterior process",
"Manubrium attached to TM (at umbo). Head in epitympanum. Tensor tympani attaches to neck. Most lateral ossicle."],
["Incus (Anvil)", "Body, short process (posterior), long process (inferior)",
"Body articulates with malleus head (incudomalleal joint). Long process descends to lenticular process → stapes head. Most vulnerable ossicle (avascular long process)."],
["Stapes (Stirrup)", "Head, neck, anterior crus, posterior crus, footplate",
"Footplate sits in oval window sealed by annular ligament. Stapedius attaches to neck. Smallest bone in body (~3 mm)."],
],
col_widths=[30*mm, 50*mm, 94*mm]
))
story += [sp(3)]
story += [sub_heading("6.1 Muscles of the Middle Ear"), sp(2)]
story.append(two_col_table(
["Muscle", "Origin", "Insertion", "Nerve", "Action"],
[
["Tensor Tympani", "Cartilage of ET + sphenoid", "Manubrium of malleus", "Medial pterygoid nerve (V3)", "Pulls malleus medially; tenses TM; dampens loud sounds"],
["Stapedius", "Pyramidal eminence", "Neck of stapes", "Facial nerve (CN VII)", "Pulls stapes posteriorly; protective reflex against loud noise (stapedial reflex)"],
],
col_widths=[28*mm, 32*mm, 32*mm, 36*mm, 46*mm]
))
story += [sp(3)]
story.append(key_points_box([
"Impedance matching: TM area (~85 mm²) vs oval window (~3.2 mm²) → 17:1 area ratio.",
"Ossicular lever mechanism adds further ~1.3× amplification → total ~22× pressure gain.",
"Acoustic reflex (stapedial reflex): bilateral; latency ~25 ms; tests CN VII integrity.",
"Long process of incus is most vulnerable: single nutrient vessel, no collateral circulation → first to erode in chronic OM.",
]))
story += [sp(3)]
story.append(clinical_box([
"Ossicular discontinuity (erosion of long process of incus): common cause of conductive hearing loss in CSOM.",
"Stapedial reflex absent ipsilaterally in Bell's palsy / CN VII lesion distal to nerve to stapedius.",
"Otosclerosis: abnormal bone growth at footplate → fixation of stapes → conductive hearing loss.",
]))
story += [sp(4), PageBreak()]
# =========== SECTION 7: EUSTACHIAN TUBE ===========
story += [section_banner("SECTION 7 — EUSTACHIAN (PHARYNGOTYMPANIC) TUBE"), sp(3)]
story.append(Paragraph(
"The Eustachian tube (auditory tube / pharyngotympanic tube) connects the anterior wall of the middle ear "
"to the nasopharynx. Its primary function is pressure equalisation of the middle ear cleft.",
body_s))
story += [sp(3)]
story.append(two_col_table(
["Feature", "Details"],
[
["Length", "~35-40 mm in adults"],
["Direction", "Runs anteromedially, inferiorly from middle ear to nasopharynx"],
["Isthmus", "Narrowest point at bony-cartilaginous junction (~1 mm)"],
["Bony portion", "Posterior 1/3; rigid; always open"],
["Cartilaginous portion", "Anterior 2/3; normally closed at rest; opens with swallowing/yawning"],
["Opening mechanism", "Tensor veli palatini (primary), levator veli palatini & salpingopharyngeus (assist) — all via V3"],
["Pharyngeal opening", "Torus tubarius: cartilaginous elevation on lateral nasopharynx wall"],
["Infant vs Adult", "Infant ET: shorter (~18 mm), horizontal, wider → more prone to middle ear infections"],
["Functions", "1. Pressure equalisation 2. Mucociliary clearance (toward pharynx) 3. Protective (prevents reflux)"],
],
col_widths=[50*mm, 124*mm]
))
story += [sp(3)]
story.append(clinical_box([
"ET dysfunction → negative middle ear pressure → retraction pockets → OME (glue ear).",
"Adenoid hypertrophy in children → ET blockage → recurrent otitis media.",
"Barotrauma: inability to equalise pressure during descent (flying/diving); TM retraction or rupture.",
"Patulous (abnormally patent) ET: autophony, breathing sounds heard in ear, relieved by head-down position.",
]))
story += [sp(4), PageBreak()]
# =========== SECTION 8: INNER EAR ===========
story += [section_banner("SECTION 8 — INNER EAR (COCHLEA, VESTIBULE, SCCs)"), sp(3)]
story.append(Paragraph(
"The inner ear (labyrinth) is embedded within the petrous part of the temporal bone. It consists of "
"a bony labyrinth housing a membranous labyrinth. The inner ear serves two functions: hearing (cochlea) "
"and balance (vestibule + semicircular canals).",
body_s))
story += [sp(3)]
story += [sub_heading("8.1 Fluids"), sp(2)]
story.append(two_col_table(
["Fluid", "Location", "Composition", "Function"],
[
["Perilymph", "Between bony and membranous labyrinth (scala vestibuli & scala tympani)", "Similar to extracellular fluid (high Na⁺, low K⁺)", "Transmits hydraulic vibrations"],
["Endolymph", "Inside membranous labyrinth (scala media / endolymphatic duct)", "Similar to intracellular fluid (high K⁺, low Na⁺)", "Bathes hair cells; K⁺ influx triggers depolarisation"],
],
col_widths=[30*mm, 50*mm, 50*mm, 44*mm]
))
story += [sp(3)]
story += [sub_heading("8.2 Cochlea"), sp(2)]
story.append(Paragraph(
"The cochlea is a snail-shaped structure with 2.5 turns. It encodes sound frequency (tonotopy) along "
"its length: high frequency at base, low frequency at apex.",
body_s))
story += [sp(2)]
story.append(two_col_table(
["Structure", "Details"],
[
["Scala vestibuli", "Perilymph-filled; begins at oval window; connects to scala tympani at helicotrema (apex)"],
["Scala tympani", "Perilymph-filled; terminates at round window (secondary TM)"],
["Scala media (cochlear duct)", "Endolymph-filled membranous duct; contains Organ of Corti"],
["Organ of Corti", "Sensory epithelium on basilar membrane. Contains inner (1 row) and outer (3 rows) hair cells. Inner hair cells: primary auditory transducers."],
["Basilar membrane", "Tonotopic: narrow/stiff at base (high freq) → wide/floppy at apex (low freq)"],
["Reissner's membrane", "Separates scala vestibuli from scala media; maintains endolymph composition"],
["Stria vascularis", "Lateral wall of scala media; produces endolymph; high blood supply"],
["Tectorial membrane", "Gelatinous membrane overlying hair cells; stereocilia of outer HCs embedded in it"],
["Helicotrema", "Apex of cochlea; connection between scala vestibuli and scala tympani"],
["Round window", "Secondary TM; allows perilymph displacement during sound transmission"],
],
col_widths=[55*mm, 119*mm]
))
story += [sp(3)]
story += [sub_heading("8.3 Vestibule & Semicircular Canals"), sp(2)]
story.append(two_col_table(
["Structure", "Sensory Organ", "Detects"],
[
["Utricle (horizontal macula)", "Macula utriculi", "Linear acceleration (horizontal); head tilt"],
["Saccule (vertical macula)", "Macula sacculi", "Linear acceleration (vertical); gravity"],
["Anterior (superior) SCC", "Crista ampullaris", "Rotation in sagittal plane (pitching - head nod)"],
["Posterior SCC", "Crista ampullaris", "Rotation in coronal plane (rolling - head tilt)"],
["Lateral (horizontal) SCC", "Crista ampullaris", "Rotation in horizontal plane (turning of head)"],
],
col_widths=[50*mm, 45*mm, 79*mm]
))
story += [sp(3)]
story.append(key_points_box([
"SCCs develop in order: superior → posterior → lateral",
"Otoliths (otoconia = calcium carbonate crystals) on macula; dislodged otoconia cause BPPV",
"Endolymphatic sac (in posterior fossa dura): regulates endolymph; implicated in Meniere's disease",
"Cochlear duct: 10 weeks → 2.5 turns; 20 weeks → full adult size; 21 weeks → organ of Corti functional",
]))
story += [sp(3)]
story.append(clinical_box([
"BPPV: canalith repositioning (Epley manoeuvre) — posterior canal most commonly affected.",
"Meniere's disease: endolymphatic hydrops → low-frequency SNHL + tinnitus + episodic vertigo.",
"Cochlear implants: electrode array placed in scala tympani via round window or cochleostomy.",
"Presbycusis: high-frequency SNHL first (base of cochlea affected by hair cell loss).",
]))
story += [sp(4), PageBreak()]
# =========== SECTION 9: NERVE SUPPLY ===========
story += [section_banner("SECTION 9 — NERVE SUPPLY OF THE EAR"), sp(3)]
story.append(two_col_table(
["Region", "Nerve(s)", "Details"],
[
["Auricle — anterior surface", "Auriculotemporal (V3 — mandibular)", "Greater part of anterior auricle & tragus"],
["Auricle — posterior surface", "Greater auricular nerve (C2, C3)", "Most of posterior auricle and lobule"],
["Auricle — posterior surface (sup)", "Lesser occipital nerve (C2)", "Superior posterior auricle"],
["EAC anterior wall", "Auriculotemporal (V3)", "Anterior + superior EAC wall and anterior TM"],
["EAC posterior wall", "Arnold's nerve (auricular branch of CN X)", "Posterior EAC wall; cough reflex on ear examination"],
["EAC (additional)", "Facial nerve (CN VII) cutaneous branch", "Small area of EAC/concha"],
["TM outer layer", "Auriculotemporal (V3)", "Outer epithelial layer"],
["TM inner layer", "Tympanic plexus (IX)", "Mucosal (inner) layer of TM"],
["Middle ear mucosa", "Tympanic plexus (Jacobson's nerve, CN IX)", "Tympanic branch of glossopharyngeal nerve"],
["Inner ear — hearing", "Cochlear nerve (CN VIII)", "Spiral ganglion → cochlear nucleus"],
["Inner ear — balance", "Vestibular nerve (CN VIII)", "Scarpa's ganglion → vestibular nuclei"],
],
col_widths=[45*mm, 50*mm, 79*mm]
))
story += [sp(3)]
story.append(clinical_box([
"Arnold's nerve reflex: stimulation of posterior EAC (ear syringing, hearing aids) → cough via CN X. Basis for 'ear-cough reflex'.",
"Referred otalgia: ear pain without local pathology → via CN V (dental), CN IX (tonsil), CN X (larynx), C2/C3 (neck).",
"Jacobson's nerve (tympanic plexus) gives rise to glomus tympanicum tumour on promontory.",
]))
story += [sp(4), PageBreak()]
# =========== SECTION 10: BLOOD SUPPLY ===========
story += [section_banner("SECTION 10 — BLOOD SUPPLY OF THE EAR"), sp(3)]
story.append(two_col_table(
["Region", "Arteries", "Notes"],
[
["Auricle (anterior)", "Superficial temporal artery (ECA)", "Branch of ECA"],
["Auricle (posterior)", "Posterior auricular artery (ECA)", "Branch of ECA; also supplies mastoid"],
["EAC & TM (outer)", "Posterior auricular + superficial temporal (ECA)", "External supply"],
["TM (inner)", "Anterior tympanic artery (maxillary a.) + posterior tympanic (posterior auricular a.)", "Forms vascular circle around TM"],
["Middle ear", "Inferior tympanic (ascending pharyngeal) + anterior tympanic (maxillary) + posterior tympanic + superior petrosal (middle meningeal) + caroticotympanic aa.", "Tympanic plexus"],
["Inner ear", "Internal auditory (labyrinthine) artery → branch of AICA (anterior inferior cerebellar artery)", "Terminal artery; no collaterals → sudden SNHL"],
],
col_widths=[35*mm, 70*mm, 69*mm]
))
story += [sp(3)]
story.append(key_points_box([
"Labyrinthine (internal auditory) artery is a terminal branch of AICA - NO collaterals",
"AICA infarct can cause sudden-onset ipsilateral SNHL + vertigo + facial palsy (lateral pontine syndrome)",
"Labyrinthine segment of facial nerve is watershed area between vertebrobasilar and ECA supply → vulnerable in viral infections (Bell's palsy / Ramsay Hunt)",
]))
story += [sp(4), PageBreak()]
# =========== SECTION 11: EMBRYOLOGY ===========
story += [section_banner("SECTION 11 — EMBRYOLOGY OF THE EAR"), sp(3)]
story += [sub_heading("11.1 External Ear Development"), sp(2)]
story.append(two_col_table(
["Structure", "Origin", "Week"],
[
["Auricle", "Hillocks of His (6 condensations): H1-H3 from 1st arch, H4-H6 from 2nd arch", "5-12 weeks"],
["EAC", "Dorsal portion of 1st branchial groove (ectoderm)", "4-28 weeks"],
["TM (outer layer)", "Ectoderm of 1st branchial groove", "—"],
["TM (inner layer)", "Endoderm of 1st pharyngeal pouch", "—"],
["TM (fibrous layer)", "Mesoderm of 1st/2nd branchial arch", "—"],
],
col_widths=[45*mm, 95*mm, 34*mm]
))
story += [sp(3)]
story += [sub_heading("11.2 Middle Ear Development"), sp(2)]
story.append(two_col_table(
["Structure", "Origin"],
[
["Tympanic cavity + ET lining", "Endoderm of 1st pharyngeal pouch (tubotympanic recess)"],
["Malleus + Incus", "Meckel's cartilage (1st arch) — head of malleus + body & short process of incus"],
["Manubrium of malleus", "Meckel's + Reichert's cartilage"],
["Stapes (most parts)", "Reichert's cartilage (2nd arch) — stapes, styloid, stylohyoid ligament"],
["Stapes footplate", "Otic capsule (mesoderm)"],
["Tensor tympani", "1st branchial arch (innervated by V3)"],
["Stapedius", "2nd branchial arch (innervated by VII)"],
],
col_widths=[50*mm, 124*mm]
))
story += [sp(3)]
story += [sub_heading("11.3 Inner Ear Development"), sp(2)]
story.append(two_col_table(
["Week", "Developmental Event"],
[
["3 weeks", "Otic placode appears (thickened ectoderm on surface)"],
["3-4 weeks", "Otic placode invaginates → otic cup → otic vesicle (otocyst)"],
["5 weeks", "Endolymphatic duct forms (first structure). Otocyst divides into pars superior and pars inferior."],
["5-6 weeks", "Pars superior → utricle, ampullae, semicircular canals (superior → posterior → lateral order)"],
["5-6 weeks", "Pars inferior → saccule + cochlear duct (coils 2.5 turns by 10 weeks)"],
["20 weeks", "Cochlear duct reaches full adult size"],
["21 weeks", "Organ of Corti becomes functional"],
],
col_widths=[25*mm, 149*mm]
))
story += [sp(3)]
story.append(clinical_box([
"Meatal plug failure → congenital canal atresia (conductive HL; requires BAHA or surgical reconstruction).",
"Thalidomide / rubella / CMV in 1st trimester → sensorineural or mixed HL (inner ear malformation).",
"Michel aplasia: complete absence of inner ear (most severe malformation).",
"Mondini dysplasia: incomplete cochlear coiling (1.5 turns instead of 2.5) → congenital SNHL.",
]))
story += [sp(4), PageBreak()]
# =========== SECTION 12: CLINICAL CORRELATIONS SUMMARY ===========
story += [section_banner("SECTION 12 — CLINICAL CORRELATIONS SUMMARY"), sp(3)]
story.append(two_col_table(
["Condition", "Key Anatomical Basis"],
[
["Otitis Externa (Swimmer's ear)", "Infection of EAC skin; Pseudomonas commonest. Tragal tenderness pathognomonic."],
["Malignant Otitis Externa", "Osteomyelitis of temporal bone; granulation at B-C junction; CN VII at stylomastoid foramen at risk."],
["Acute Otitis Media (AOM)", "Middle ear mucosal infection via ET; TM bulging/erythema; pars tensa perforation if ruptures."],
["Otitis Media with Effusion (OME / Glue Ear)", "ET dysfunction → negative pressure → transudate; dull retracted TM with fluid level; conductive HL."],
["Cholesteatoma", "Keratoma in middle ear; pars flaccida (Attic/acquired); erodes ossicles, SCCs, tegmen, facial canal."],
["Otosclerosis", "Abnormal bone at oval window → stapes fixation → conductive HL; Schwartze sign (flamingo pink promontory)."],
["Meniere's Disease", "Endolymphatic hydrops; low-freq SNHL + episodic vertigo + tinnitus + aural fullness."],
["BPPV", "Otoconia dislodged from macula into SCC (posterior most common); rotatory nystagmus on Dix-Hallpike."],
["Acoustic Neuroma (Vestibular Schwannoma)", "CN VIII tumour in IAC/CPA; unilateral progressive SNHL + tinnitus + imbalance."],
["Bell's Palsy", "CN VII palsy; stapedial reflex absent; hyperacusis due to loss of stapedius function."],
["Presbycusis", "Age-related SNHL; hair cell loss at cochlear base → high-frequency loss first."],
],
col_widths=[55*mm, 119*mm]
))
story += [sp(4)]
# Final page reference box
story.append(mnemonic_box(
"Quick Anatomy Summary — 3-2-1 Rule",
"3 ossicles (malleus-incus-stapes) | 3 semicircular canals | 3 layers of TM (fibrous: 2 layers)\n"
"2 muscles: tensor tympani (V3) + stapedius (VII) | 2 fluids: perilymph + endolymph\n"
"1 Eustachian tube | 1 oval window | 1 round window | 1 labyrinthine artery (terminal!)"
))
# ── Build ────────────────────────────────────────────────────────────────────
doc.build(story)
print("PDF generated:", OUTPUT)
cd /tmp/workspace/ent-ear-anatomy && python generate_ear_pdf.py 2>&1
ls -lh /tmp/workspace/ent-ear-anatomy/ENT_Ear_Anatomy.pdf
ENT Ear Anatomy
PDF Document · PDF
| Colour | Used for |
|---|---|
| Deep Blue banners | Major section headers |
| Teal boxes | Section banners |
| Orange highlights | Sub-section headings |
| Gold boxes (⭐) | Key points |
| Red boxes (🩺) | Clinical correlations |
| Green boxes (💡) | Mnemonics |
| Alternating blue/white rows | All data tables |