Give me pdf foR 10 mark on Larynx that includes Gross anatomy, cartilages, membrane,Ligaments Muscles, action drainage the innervation with diagram tables Flowchart and points By Refer BD Chaurasia's Human Anatomy for dental Students 5ᵗʰ edition & add extra Points if needed supply
mkdir -p /tmp/workspace/larynx-pdf && ls /tmp/workspace/larynx-pdf/
~/larynx-pdf/generate_larynx_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon, Circle, Arrow
from reportlab.graphics import renderPDF
from reportlab.graphics.shapes import Drawing, Group, Rect, String, Line, PolyLine
from reportlab.platypus.flowables import Flowable
import os
OUTPUT_PATH = "/tmp/workspace/larynx-pdf/Larynx_10Mark_Notes.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE = colors.HexColor("#1A3A6B")
MED_BLUE = colors.HexColor("#2563A8")
LIGHT_BLUE = colors.HexColor("#D0E4F7")
ACCENT_RED = colors.HexColor("#C0392B")
ACCENT_GREEN= colors.HexColor("#1E7A48")
GOLD = colors.HexColor("#D4A017")
PALE_YELLOW = colors.HexColor("#FFFBEA")
PALE_GREEN = colors.HexColor("#E8F5E9")
PALE_RED = colors.HexColor("#FDEDEC")
WHITE = colors.white
GREY_BG = colors.HexColor("#F4F6F9")
BORDER_GREY = colors.HexColor("#B0BEC5")
# ── Doc setup ────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT_PATH,
pagesize=A4,
rightMargin=1.8*cm,
leftMargin=1.8*cm,
topMargin=2*cm,
bottomMargin=2*cm,
title="Larynx – 10 Mark Anatomy Notes",
author="Orris AI | Ref: BD Chaurasia & Gray's Anatomy"
)
W = A4[0] - 3.6*cm # usable width
styles = getSampleStyleSheet()
def S(name, **kw):
"""Quick style builder."""
base = styles.get(name, styles["Normal"])
return ParagraphStyle(name + "_custom", parent=base, **kw)
TITLE_STYLE = S("Title", fontSize=22, textColor=WHITE, alignment=TA_CENTER, spaceAfter=4, leading=26)
H1_STYLE = S("Heading1", fontSize=14, textColor=WHITE, alignment=TA_CENTER, spaceAfter=2, leading=18)
H2_STYLE = S("Heading2", fontSize=12, textColor=DARK_BLUE, spaceBefore=8, spaceAfter=3, leading=15, fontName="Helvetica-Bold")
H3_STYLE = S("Heading3", fontSize=10.5, textColor=MED_BLUE, spaceBefore=5, spaceAfter=2, leading=14, fontName="Helvetica-Bold")
BODY_STYLE = S("Normal", fontSize=9.5, leading=14, textColor=colors.black, spaceAfter=2, alignment=TA_JUSTIFY)
BULLET_STYLE = S("Normal", fontSize=9.5, leading=13, textColor=colors.black, leftIndent=14, bulletIndent=6)
SMALL_STYLE = S("Normal", fontSize=8.5, leading=12, textColor=colors.HexColor("#444444"))
NOTE_STYLE = S("Normal", fontSize=9, leading=13, textColor=ACCENT_RED, fontName="Helvetica-Oblique")
TABLE_HDR = S("Normal", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)
TABLE_CELL = S("Normal", fontSize=8.5, textColor=colors.black, alignment=TA_LEFT, leading=11)
TABLE_CELL_C = S("Normal", fontSize=8.5, textColor=colors.black, alignment=TA_CENTER, leading=11)
FOOT_STYLE = S("Normal", fontSize=8, textColor=colors.grey, alignment=TA_CENTER)
story = []
# ════════════════════════════════════════════════════════════════════════════
# Helper: section header box
# ════════════════════════════════════════════════════════════════════════════
class ColorBox(Flowable):
def __init__(self, text, width, bg=DARK_BLUE, fg=WHITE, height=22, radius=4, style=None):
super().__init__()
self.text = text
self._width = width
self.bg = bg
self.fg = fg
self.height = height
self.radius = radius
self.style = style or H1_STYLE
self.spaceAfter = 6
def wrap(self, aW, aH):
return (self._width, self.height + 4)
def draw(self):
c = self.canv
c.setFillColor(self.bg)
c.roundRect(0, 0, self._width, self.height, self.radius, fill=1, stroke=0)
c.setFillColor(self.fg)
c.setFont("Helvetica-Bold", self.style.fontSize)
c.drawCentredString(self._width / 2, self.height / 2 - self.style.fontSize / 3, self.text)
def section_header(text, bg=DARK_BLUE, fg=WHITE, fontsize=13):
return ColorBox(text, W, bg=bg, fg=fg, height=24,
style=S("h", fontSize=fontsize, textColor=fg))
def sub_header(text):
return ColorBox(text, W, bg=MED_BLUE, fg=WHITE, height=20,
style=S("sh", fontSize=11, textColor=WHITE))
def mini_header(text):
return ColorBox(text, W, bg=LIGHT_BLUE, fg=DARK_BLUE, height=18,
style=S("mh", fontSize=10, textColor=DARK_BLUE))
def bullet(text, indent=0):
return Paragraph(f"<bullet>•</bullet> {text}", BULLET_STYLE)
def hline(color=BORDER_GREY, thickness=0.6):
return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=4, spaceBefore=2)
def note(text):
return Paragraph(f"<i>⚠ {text}</i>", NOTE_STYLE)
def sp(h=4):
return Spacer(1, h)
# ════════════════════════════════════════════════════════════════════════════
# COVER PAGE
# ════════════════════════════════════════════════════════════════════════════
class CoverPage(Flowable):
def __init__(self, w, h):
super().__init__()
self._w = w
self._h = h
def wrap(self, aW, aH):
return (self._w, self._h)
def draw(self):
c = self.canv
# gradient-like background
c.setFillColor(DARK_BLUE)
c.rect(0, self._h * 0.45, self._w, self._h * 0.55, fill=1, stroke=0)
c.setFillColor(LIGHT_BLUE)
c.rect(0, 0, self._w, self._h * 0.45, fill=1, stroke=0)
# Gold accent bar
c.setFillColor(GOLD)
c.rect(0, self._h * 0.44, self._w, 5, fill=1, stroke=0)
# Title
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 30)
c.drawCentredString(self._w / 2, self._h * 0.72, "LARYNX")
c.setFont("Helvetica", 15)
c.drawCentredString(self._w / 2, self._h * 0.64, "Complete 10-Mark Anatomy Notes")
# Subtitle box
c.setFillColor(GOLD)
c.roundRect(self._w * 0.15, self._h * 0.55, self._w * 0.70, 28, 5, fill=1, stroke=0)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 11)
c.drawCentredString(self._w / 2, self._h * 0.557,
"Ref: BD Chaurasia Human Anatomy (Dental) 5th Ed | Gray's Anatomy")
# Topics list
topics = [
"Gross Anatomy", "Cartilages", "Membranes & Ligaments",
"Muscles & Actions", "Blood Supply & Lymphatics", "Innervation",
"Clinical Notes", "Diagrams & Flowcharts"
]
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 11)
y = self._h * 0.36
for i, t in enumerate(topics):
col = 0 if i % 2 == 0 else self._w / 2
c.roundRect(col + 10, y - 3, self._w / 2 - 20, 18, 3, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica", 10)
c.drawCentredString(col + self._w / 4, y + 3, f"✦ {t}")
c.setFillColor(DARK_BLUE)
if i % 2 == 1:
y -= 24
# Footer
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica", 9)
c.setFillColor(colors.HexColor("#555555"))
c.drawCentredString(self._w / 2, 18, "Prepared by Orris AI | July 2026")
story.append(CoverPage(W, 22*cm))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 1. GROSS ANATOMY
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("1. GROSS ANATOMY OF LARYNX", bg=DARK_BLUE))
story.append(sp(4))
story.append(Paragraph(
"The <b>larynx</b> is a hollow musculoligamentous structure with a cartilaginous framework that caps the lower respiratory tract. "
"It acts simultaneously as a <b>valve (sphincter)</b> for the lower airway and as a <b>phonation organ</b>.",
BODY_STYLE))
story.append(sp(4))
# Quick-fact box
quick_data = [
[Paragraph("<b>Parameter</b>", TABLE_HDR), Paragraph("<b>Details</b>", TABLE_HDR)],
[Paragraph("Location", TABLE_CELL), Paragraph("Anterior neck, C3–C6 vertebral level", TABLE_CELL)],
[Paragraph("Superior opening", TABLE_CELL), Paragraph("Laryngeal inlet → opens into laryngopharynx", TABLE_CELL)],
[Paragraph("Inferior continuation", TABLE_CELL), Paragraph("Trachea (below cricoid cartilage)", TABLE_CELL)],
[Paragraph("Anterior relations", TABLE_CELL), Paragraph("Skin, fascia, infrahyoid (strap) muscles", TABLE_CELL)],
[Paragraph("Posterior relations", TABLE_CELL), Paragraph("Laryngopharynx, oesophagus", TABLE_CELL)],
[Paragraph("Lateral relations", TABLE_CELL), Paragraph("Lobes of thyroid gland, carotid sheath", TABLE_CELL)],
[Paragraph("Superior attachment", TABLE_CELL), Paragraph("Hyoid bone via thyrohyoid membrane", TABLE_CELL)],
[Paragraph("Inferior attachment", TABLE_CELL), Paragraph("Trachea via cricotracheal ligament", TABLE_CELL)],
[Paragraph("Dimensions (adult)", TABLE_CELL), Paragraph("Length ≈ 4 cm (♂) / 3.5 cm (♀); wider in ♂", TABLE_CELL)],
]
qt = Table(quick_data, colWidths=[W*0.28, W*0.72])
qt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("BACKGROUND", (0,1), (0,-1), LIGHT_BLUE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY_BG]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(qt)
story.append(sp(6))
story.append(sub_header("Cavity Divisions (Supraglottis / Glottis / Subglottis)"))
story.append(sp(3))
divisions = [
[Paragraph("<b>Region</b>", TABLE_HDR), Paragraph("<b>Boundaries</b>", TABLE_HDR), Paragraph("<b>Key Contents</b>", TABLE_HDR)],
[Paragraph("Supraglottis\n(Vestibule)", TABLE_CELL_C),
Paragraph("Laryngeal inlet → vestibular folds (false cords)", TABLE_CELL),
Paragraph("Epiglottis, aryepiglottic folds, vestibular folds", TABLE_CELL)],
[Paragraph("Middle Cavity", TABLE_CELL_C),
Paragraph("Vestibular folds → vocal folds", TABLE_CELL),
Paragraph("Laryngeal ventricles & saccules (Sacculus laryngis)", TABLE_CELL)],
[Paragraph("Glottis", TABLE_CELL_C),
Paragraph("Rima glottidis (opening between vocal folds)", TABLE_CELL),
Paragraph("True vocal folds + anterior/posterior commissures", TABLE_CELL)],
[Paragraph("Subglottis\n(Infraglottis)", TABLE_CELL_C),
Paragraph("Below vocal folds → lower border of cricoid", TABLE_CELL),
Paragraph("Continuation to trachea; widest part of larynx inferiorly", TABLE_CELL)],
]
dt = Table(divisions, colWidths=[W*0.17, W*0.40, W*0.43])
dt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), MED_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, GREY_BG]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(dt)
story.append(sp(4))
story.append(Paragraph("<b>Rima Glottidis:</b> The narrowest part of the adult larynx. Bounded anteriorly by the vocal folds (intermembranous part) and posteriorly by the arytenoid cartilages (intercartilaginous part). In infants, the narrowest part is the subglottis (cricoid level).", BODY_STYLE))
story.append(note("BDC exam tip: The rima glottidis is the narrowest part of adult larynx; the subglottis is narrowest in children — clinically important for croup vs. adult obstruction."))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 2. CARTILAGES
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("2. CARTILAGES OF THE LARYNX", bg=DARK_BLUE))
story.append(sp(4))
story.append(sub_header("A. Unpaired (3) Cartilages"))
story.append(sp(3))
unpaired = [
[Paragraph("<b>Cartilage</b>", TABLE_HDR),
Paragraph("<b>Type</b>", TABLE_HDR),
Paragraph("<b>Key Features</b>", TABLE_HDR),
Paragraph("<b>Clinical Note</b>", TABLE_HDR)],
[Paragraph("<b>Thyroid</b>\n(Largest)", TABLE_CELL_C),
Paragraph("Hyaline", TABLE_CELL_C),
Paragraph(
"• Two laminae fused anteriorly at 90° (♂) / 120° (♀)\n"
"• Laryngeal prominence = Adam's apple\n"
"• Superior thyroid notch (palpable)\n"
"• Oblique line on each lamina: attachment of sternothyroid, thyrohyoid, inferior constrictor\n"
"• Superior horn → lateral thyrohyoid ligament → hyoid\n"
"• Inferior horn → articulates with cricoid (cricothyroid joint)", TABLE_CELL),
Paragraph("Angle difference ♂/♀ explains deeper male voice", TABLE_CELL)],
[Paragraph("<b>Cricoid</b>\n(Only complete ring)", TABLE_CELL_C),
Paragraph("Hyaline", TABLE_CELL_C),
Paragraph(
"• Signet-ring shaped: broad posterior lamina + narrow anterior arch\n"
"• Only complete cartilaginous ring of airway\n"
"• Facets: superolateral for arytenoids; lateral for inf. horn of thyroid\n"
"• Posterior lamina: attachment of PCA muscle & oesophageal longitudinal muscle\n"
"• Cricothyroid joint (synovial) allows rotation & gliding", TABLE_CELL),
Paragraph("Cricothyrotomy: incision through cricothyroid membrane (emergency airway)", TABLE_CELL)],
[Paragraph("<b>Epiglottis</b>\n(Leaf-shaped)", TABLE_CELL_C),
Paragraph("Yellow (elastic) fibrocartilage", TABLE_CELL_C),
Paragraph(
"• Leaf-shaped plate, projects above thyroid cartilage\n"
"• Petiolus (stalk) attached to thyroid angle by thyroepiglottic ligament\n"
"• Anterior surface: hyoepiglottic ligament to hyoid; glossoepiglottic folds\n"
"• Epiglottic valleculae: spaces between tongue and epiglottis\n"
"• During swallowing: tilts back to close laryngeal inlet", TABLE_CELL),
Paragraph("Only elastic cartilage → no ossification in old age", TABLE_CELL)],
]
uct = Table(unpaired, colWidths=[W*0.14, W*0.10, W*0.50, W*0.26])
uct.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, GREY_BG, PALE_YELLOW]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(uct)
story.append(sp(8))
story.append(sub_header("B. Paired (3 pairs) Cartilages"))
story.append(sp(3))
paired = [
[Paragraph("<b>Cartilage</b>", TABLE_HDR),
Paragraph("<b>Type</b>", TABLE_HDR),
Paragraph("<b>Key Features</b>", TABLE_HDR)],
[Paragraph("<b>Arytenoid</b>\n(Most important paired)", TABLE_CELL_C),
Paragraph("Hyaline", TABLE_CELL_C),
Paragraph(
"• Pyramidal shape; base articulates with cricoid (cricoarytenoid joint, synovial)\n"
"• Apex → corniculate cartilage\n"
"• Vocal process (anterior): attachment of vocal ligament\n"
"• Muscular process (lateral): attachment of PCA, LCA, thyroarytenoid\n"
"• Movements: rotation + gliding → opens/closes rima glottidis\n"
"• Most intrinsic laryngeal muscles act on this cartilage", TABLE_CELL)],
[Paragraph("<b>Corniculate</b>\n(of Santorini)", TABLE_CELL_C),
Paragraph("Elastic fibrocartilage", TABLE_CELL_C),
Paragraph(
"• Small, cone-shaped; sits atop apex of arytenoid\n"
"• Located in aryepiglottic fold\n"
"• Seen endoscopically as corniculate tubercles", TABLE_CELL)],
[Paragraph("<b>Cuneiform</b>\n(of Wrisberg)", TABLE_CELL_C),
Paragraph("Elastic fibrocartilage", TABLE_CELL_C),
Paragraph(
"• Small, club-shaped; located in aryepiglottic fold anterior to corniculate\n"
"• Stiffens aryepiglottic fold\n"
"• Seen as cuneiform tubercles on laryngoscopy", TABLE_CELL)],
]
pct = Table(paired, colWidths=[W*0.18, W*0.12, W*0.70])
pct.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), MED_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, GREY_BG, PALE_YELLOW]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(pct)
story.append(sp(5))
story.append(note("Mnemonic (Cartilages): 'Three Crows Eat Apple Cake Carefully' → Thyroid, Cricoid, Epiglottis, Arytenoid, Corniculate, Cuneiform"))
story.append(note("Ossification: Hyaline cartilages (thyroid, cricoid, arytenoid) ossify with age. Elastic cartilages (epiglottis, corniculate, cuneiform) do NOT ossify."))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 3. MEMBRANES & LIGAMENTS
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("3. MEMBRANES & LIGAMENTS OF LARYNX", bg=DARK_BLUE))
story.append(sp(4))
story.append(sub_header("A. Extrinsic Membranes & Ligaments (connect larynx to neighbouring structures)"))
story.append(sp(3))
ext_lig = [
[Paragraph("<b>Structure</b>", TABLE_HDR),
Paragraph("<b>Connects</b>", TABLE_HDR),
Paragraph("<b>Notes</b>", TABLE_HDR)],
[Paragraph("Thyrohyoid Membrane", TABLE_CELL),
Paragraph("Upper border of thyroid cartilage → hyoid bone", TABLE_CELL),
Paragraph("• Broad fibroelastic sheet\n• Thickened posteriorly = Lateral thyrohyoid ligament (contains cartilago triticea)\n• Medially = Median thyrohyoid ligament\n• Superior laryngeal nerve & vessels pierce it laterally", TABLE_CELL)],
[Paragraph("Hyoepiglottic Ligament", TABLE_CELL),
Paragraph("Anterior surface of epiglottis → upper border of hyoid body", TABLE_CELL),
Paragraph("• Forms roof of pre-epiglottic space\n• Contains fat", TABLE_CELL)],
[Paragraph("Cricotracheal Ligament", TABLE_CELL),
Paragraph("Lower border of cricoid → 1st tracheal ring", TABLE_CELL),
Paragraph("Connects larynx to trachea inferiorly", TABLE_CELL)],
[Paragraph("Lateral Thyrohyoid Ligament", TABLE_CELL),
Paragraph("Superior horn of thyroid → tip of greater horn of hyoid", TABLE_CELL),
Paragraph("Contains cartilago triticea (sesamoid cartilage)", TABLE_CELL)],
]
elt = Table(ext_lig, colWidths=[W*0.22, W*0.30, W*0.48])
elt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, GREY_BG]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(elt)
story.append(sp(7))
story.append(sub_header("B. Intrinsic Fibroelastic Membrane (Internal Framework)"))
story.append(sp(3))
story.append(Paragraph(
"The <b>fibroelastic membrane</b> lies beneath the laryngeal mucosa forming an internal skeleton. "
"It is divided into <b>upper</b> and <b>lower</b> parts by the laryngeal ventricle:",
BODY_STYLE))
story.append(sp(3))
int_lig = [
[Paragraph("<b>Structure</b>", TABLE_HDR),
Paragraph("<b>Also Known As</b>", TABLE_HDR),
Paragraph("<b>Attachments & Notes</b>", TABLE_HDR)],
[Paragraph("<b>Quadrangular Membrane</b>\n(Upper part)", TABLE_CELL_C),
Paragraph("Aryepiglottic membrane", TABLE_CELL_C),
Paragraph(
"• Extends: lateral border of epiglottis → arytenoid cartilage\n"
"• Upper free margin = framework of aryepiglottic fold\n"
"• Lower thickened border = Vestibular ligament (false cord)\n"
"• Covered by mucosa = vestibular fold", TABLE_CELL)],
[Paragraph("<b>Conus Elasticus</b>\n(Lower part)", TABLE_CELL_C),
Paragraph("Cricovocal / Cricothyroid membrane", TABLE_CELL_C),
Paragraph(
"• Thick elastic membrane; rich in elastic fibres\n"
"• Attached below: upper border of cricoid cartilage\n"
"• Attached above (anteriorly): inner surface of thyroid angle\n"
"• Attached above (posteriorly): vocal process of arytenoid\n"
"• Free upper border = Vocal ligament (true vocal cord core)\n"
"• Anterior thickening = Median cricothyroid ligament (emergency access)", TABLE_CELL)],
[Paragraph("<b>Cricothyroid Ligament\n(Median)</b>", TABLE_CELL_C),
Paragraph("Part of Conus Elasticus", TABLE_CELL_C),
Paragraph(
"• Between lower border of thyroid and upper arch of cricoid\n"
"• Site of cricothyrotomy (emergency airway)\n"
"• No major vessels anteriorly (safe zone)", TABLE_CELL)],
]
ilt = Table(int_lig, colWidths=[W*0.22, W*0.22, W*0.56])
ilt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), MED_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, GREY_BG, PALE_YELLOW]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(ilt)
story.append(sp(5))
# Flowchart: Fibroelastic membrane
story.append(sub_header("Flowchart: Fibroelastic Membrane of Larynx"))
story.append(sp(3))
class FibroElasticFlowchart(Flowable):
def __init__(self, w):
super().__init__()
self._w = w
self.height = 200
def wrap(self, aW, aH):
return (self._w, self.height)
def draw(self):
c = self.canv
W = self._w
bw, bh, r = 180, 28, 5
def box(x, y, text, bg, fg=colors.white, w=bw, h=bh):
c.setFillColor(bg)
c.roundRect(x - w/2, y - h/2, w, h, r, fill=1, stroke=0)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", 9)
lines = text.split('\n')
for i, ln in enumerate(lines):
c.drawCentredString(x, y + (len(lines)-1)*6 - i*12 - 3, ln)
def arrow(x1, y1, x2, y2):
c.setStrokeColor(DARK_BLUE)
c.setLineWidth(1.5)
c.line(x1, y1, x2, y2)
c.setFillColor(DARK_BLUE)
# arrow head
c.setFont("Helvetica", 10)
dx, dy = x2-x1, y2-y1
length = (dx**2+dy**2)**0.5
ux, uy = dx/length, dy/length
ax1 = x2 - uy*5 - ux*8
ay1 = y2 + ux*5 - uy*8
ax2 = x2 + uy*5 - ux*8
ay2 = y2 - ux*5 - uy*8
p = c.beginPath()
p.moveTo(x2, y2); p.lineTo(ax1, ay1); p.lineTo(ax2, ay2); p.close()
c.drawPath(p, fill=1, stroke=0)
# Main box
cx = W / 2
box(cx, 185, "FIBROELASTIC MEMBRANE\n(Internal skeleton of Larynx)", DARK_BLUE, w=280)
arrow(cx, 171, cx, 155)
# Split: upper & lower
c.setStrokeColor(MED_BLUE); c.setLineWidth(1.2)
c.line(cx, 155, cx, 140)
c.line(cx - 100, 140, cx + 100, 140)
arrow(cx - 100, 140, cx - 100, 125)
arrow(cx + 100, 140, cx + 100, 125)
box(cx - 100, 113, "UPPER PART\nQuadrangular Membrane", MED_BLUE, w=170, h=36)
box(cx + 100, 113, "LOWER PART\nConus Elasticus", ACCENT_GREEN, w=170, h=36)
# Upper → borders
arrow(cx - 100, 95, cx - 180, 70)
arrow(cx - 100, 95, cx - 20, 70)
box(cx - 180, 58, "Upper border →\nAryepiglottic fold", colors.HexColor("#4A90D9"), w=155, h=30)
box(cx - 20, 58, "Lower border →\nVestibular Ligament\n(False cord)", colors.HexColor("#4A90D9"), w=155, h=36)
# Lower → borders
arrow(cx + 100, 95, cx + 20, 70)
arrow(cx + 100, 95, cx + 180, 70)
box(cx + 20, 58, "Lower border →\nCricoid upper border", ACCENT_GREEN, w=145, h=30)
box(cx + 180, 58, "Upper free border →\nVocal Ligament\n(True cord)", ACCENT_GREEN, w=145, h=36)
# Dividing label
c.setFillColor(GOLD)
c.roundRect(cx - 70, 135, 140, 18, 3, fill=1, stroke=0)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-BoldOblique", 8.5)
c.drawCentredString(cx, 140, "Divided by Laryngeal Ventricle")
story.append(FibroElasticFlowchart(W))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 4. MUSCLES
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("4. MUSCLES OF THE LARYNX", bg=DARK_BLUE))
story.append(sp(4))
story.append(sub_header("A. Extrinsic Muscles (move larynx as a whole)"))
story.append(sp(3))
ext_m = [
[Paragraph("<b>Group</b>", TABLE_HDR),
Paragraph("<b>Muscle</b>", TABLE_HDR),
Paragraph("<b>Origin → Insertion</b>", TABLE_HDR),
Paragraph("<b>Action</b>", TABLE_HDR),
Paragraph("<b>Nerve</b>", TABLE_HDR)],
# Depressors
[Paragraph("Infrahyoid\n(Depressors)", TABLE_CELL_C),
Paragraph("Sternothyroid", TABLE_CELL),
Paragraph("Manubrium → oblique line of thyroid", TABLE_CELL),
Paragraph("Depresses larynx", TABLE_CELL),
Paragraph("Ansa cervicalis (C2, C3)", TABLE_CELL)],
[Paragraph("", TABLE_CELL_C),
Paragraph("Sternohyoid", TABLE_CELL),
Paragraph("Clavicle/manubrium → body of hyoid", TABLE_CELL),
Paragraph("Depresses hyoid & larynx", TABLE_CELL),
Paragraph("Ansa cervicalis (C1-C3)", TABLE_CELL)],
[Paragraph("", TABLE_CELL_C),
Paragraph("Thyrohyoid", TABLE_CELL),
Paragraph("Oblique line of thyroid → hyoid", TABLE_CELL),
Paragraph("Elevates larynx (on fixed hyoid)", TABLE_CELL),
Paragraph("Hypoglossal (C1 root)", TABLE_CELL)],
[Paragraph("", TABLE_CELL_C),
Paragraph("Omohyoid", TABLE_CELL),
Paragraph("Scapula (superior border) → hyoid", TABLE_CELL),
Paragraph("Depresses & retracts hyoid", TABLE_CELL),
Paragraph("Ansa cervicalis (C1-C3)", TABLE_CELL)],
# Elevators
[Paragraph("Suprahyoid\n(Elevators)", TABLE_CELL_C),
Paragraph("Mylohyoid", TABLE_CELL),
Paragraph("Mylohyoid line of mandible → hyoid raphe", TABLE_CELL),
Paragraph("Elevates hyoid; forms floor of mouth", TABLE_CELL),
Paragraph("Nerve to mylohyoid (V3)", TABLE_CELL)],
[Paragraph("", TABLE_CELL_C),
Paragraph("Geniohyoid", TABLE_CELL),
Paragraph("Genial tubercle (mandible) → hyoid", TABLE_CELL),
Paragraph("Elevates & protracts hyoid", TABLE_CELL),
Paragraph("Hypoglossal (C1 root)", TABLE_CELL)],
[Paragraph("", TABLE_CELL_C),
Paragraph("Stylohyoid", TABLE_CELL),
Paragraph("Styloid process → hyoid (greater cornu)", TABLE_CELL),
Paragraph("Elevates & retracts hyoid", TABLE_CELL),
Paragraph("Facial nerve (CN VII)", TABLE_CELL)],
[Paragraph("", TABLE_CELL_C),
Paragraph("Digastric", TABLE_CELL),
Paragraph("Mastoid process / mandible → hyoid (sling)", TABLE_CELL),
Paragraph("Elevates hyoid; opens jaw", TABLE_CELL),
Paragraph("Post: Facial (VII); Ant: V3", TABLE_CELL)],
[Paragraph("Pharyngeal\n(Elevators)", TABLE_CELL_C),
Paragraph("Stylopharyngeus\nSalpingopharyngeus\nPalatopharyngeus", TABLE_CELL),
Paragraph("Styloid / Eustachian tube / Palate → thyroid cartilage", TABLE_CELL),
Paragraph("Elevate larynx during swallowing", TABLE_CELL),
Paragraph("CN IX / Pharyngeal plexus", TABLE_CELL)],
]
emt = Table(ext_m, colWidths=[W*0.12, W*0.17, W*0.30, W*0.22, W*0.19])
emt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, WHITE, WHITE, WHITE,
GREY_BG, GREY_BG, GREY_BG, GREY_BG,
PALE_YELLOW]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING",(0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
("SPAN", (0,1), (0,4)),
("SPAN", (0,5), (0,8)),
]))
story.append(emt)
story.append(sp(8))
story.append(sub_header("B. Intrinsic Muscles — Origin, Insertion, Action, Nerve"))
story.append(sp(3))
intr_m = [
[Paragraph("<b>Muscle</b>", TABLE_HDR),
Paragraph("<b>Origin</b>", TABLE_HDR),
Paragraph("<b>Insertion</b>", TABLE_HDR),
Paragraph("<b>Action</b>", TABLE_HDR),
Paragraph("<b>Nerve</b>", TABLE_HDR)],
[Paragraph("Cricothyroid\n(Only external intrinsic)", TABLE_CELL_C),
Paragraph("Arch of cricoid (anterolateral)", TABLE_CELL),
Paragraph("Lower border & inferior horn of thyroid", TABLE_CELL),
Paragraph("Tenses (lengthens) vocal cords → high-pitched voice", TABLE_CELL),
Paragraph("External branch of Superior Laryngeal N. (SLN)", TABLE_CELL)],
[Paragraph("Posterior Cricoareytenoid\n(PCA) – ONLY ABDUCTOR", TABLE_CELL_C),
Paragraph("Posterior surface of cricoid lamina", TABLE_CELL),
Paragraph("Muscular process of arytenoid", TABLE_CELL),
Paragraph("Rotates arytenoid laterally → ABDUCTS vocal cords (opens rima glottidis)", TABLE_CELL),
Paragraph("Recurrent Laryngeal N. (RLN)", TABLE_CELL)],
[Paragraph("Lateral Cricoarytenoid\n(LCA)", TABLE_CELL_C),
Paragraph("Arch of cricoid (superolateral)", TABLE_CELL),
Paragraph("Muscular process of arytenoid", TABLE_CELL),
Paragraph("Rotates arytenoid medially → ADDUCTS vocal cords (closes rima glottidis)", TABLE_CELL),
Paragraph("RLN", TABLE_CELL)],
[Paragraph("Transverse Arytenoid\n(Interarytenoid)\n(ONLY UNPAIRED)", TABLE_CELL_C),
Paragraph("Posterior & lateral surface of one arytenoid", TABLE_CELL),
Paragraph("Same surface of other arytenoid", TABLE_CELL),
Paragraph("Adducts arytenoids → closes posterior rima glottidis", TABLE_CELL),
Paragraph("RLN (bilateral)", TABLE_CELL)],
[Paragraph("Oblique Arytenoid", TABLE_CELL_C),
Paragraph("Muscular process of one arytenoid", TABLE_CELL),
Paragraph("Apex of opposite arytenoid → continues as aryepiglottic muscle", TABLE_CELL),
Paragraph("Narrows laryngeal inlet; assists adduction", TABLE_CELL),
Paragraph("RLN", TABLE_CELL)],
[Paragraph("Thyroarytenoid\n(TA)", TABLE_CELL_C),
Paragraph("Inner surface of thyroid lamina (lower half)", TABLE_CELL),
Paragraph("Anterolateral surface of arytenoid", TABLE_CELL),
Paragraph("Relaxes (shortens) vocal cord; adducts; sphincter of vestibule", TABLE_CELL),
Paragraph("RLN", TABLE_CELL)],
[Paragraph("Vocalis\n(Medial TA)", TABLE_CELL_C),
Paragraph("Thyroid angle (lower)", TABLE_CELL),
Paragraph("Vocal process & vocal ligament", TABLE_CELL),
Paragraph("Fine-tune tension of vocal cord (register changes)", TABLE_CELL),
Paragraph("RLN", TABLE_CELL)],
[Paragraph("Thyroepiglottic\n(Lateral TA)", TABLE_CELL_C),
Paragraph("Inner surface of thyroid lamina", TABLE_CELL),
Paragraph("Margin of epiglottis & aryepiglottic fold", TABLE_CELL),
Paragraph("Widens laryngeal inlet; depresses epiglottis", TABLE_CELL),
Paragraph("RLN", TABLE_CELL)],
]
imt = Table(intr_m, colWidths=[W*0.17, W*0.17, W*0.21, W*0.28, W*0.17])
imt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),
[PALE_RED, PALE_GREEN, WHITE, GREY_BG, WHITE, GREY_BG, WHITE, GREY_BG]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 4),
]))
story.append(imt)
story.append(sp(5))
story.append(note("Key exam fact: Posterior Cricoarytenoid (PCA) is the ONLY abductor of vocal cords. Paralysis of RLN (bilateral) causes both cords to adduct → respiratory obstruction (stridor). Cricothyroid is the only intrinsic muscle supplied by SLN (external branch), NOT RLN."))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 4C. ACTIONS FLOWCHART
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("4C. VOCAL CORD MOVEMENTS – MUSCLE ACTIONS FLOWCHART", bg=MED_BLUE))
story.append(sp(5))
class ActionFlowchart(Flowable):
def __init__(self, w):
super().__init__()
self._w = w
self.height = 260
def wrap(self, aW, aH):
return (self._w, self.height)
def draw(self):
c = self.canv
W = self._w
def box(x, y, text, bg, fg=colors.white, bw=165, bh=28, r=5):
c.setFillColor(bg)
c.roundRect(x - bw/2, y - bh/2, bw, bh, r, fill=1, stroke=0)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", 8.5)
lines = text.split('\n')
for i, l in enumerate(lines):
c.drawCentredString(x, y + (len(lines)-1)*7 - i*13 - 3, l)
def arr(x1,y1,x2,y2):
c.setStrokeColor(DARK_BLUE); c.setLineWidth(1.2)
c.line(x1,y1,x2,y2)
c.setFillColor(DARK_BLUE)
dx,dy=x2-x1,y2-y1
L=(dx**2+dy**2)**0.5
if L==0: return
ux,uy=dx/L,dy/L
pts=[(x2,y2),(x2-uy*4-ux*8,y2+ux*4-uy*8),(x2+uy*4-ux*8,y2-ux*4-uy*8)]
p=c.beginPath()
p.moveTo(*pts[0]); p.lineTo(*pts[1]); p.lineTo(*pts[2]); p.close()
c.drawPath(p,fill=1,stroke=0)
def label(x,y,text,fg=GOLD):
c.setFillColor(fg)
c.setFont("Helvetica-BoldOblique",7.5)
c.drawCentredString(x,y,text)
cx = W/2
# Root
box(cx, 248, "INTRINSIC LARYNGEAL MUSCLES", DARK_BLUE, bw=260)
arr(cx, 234, cx, 220)
# Branch point
c.setStrokeColor(DARK_BLUE); c.setLineWidth(1.5)
c.line(cx, 220, cx, 210)
c.line(cx - 160, 210, cx + 160, 210)
arr(cx - 160, 210, cx - 160, 192)
arr(cx, 210, cx, 192)
arr(cx + 160, 210, cx + 160, 192)
box(cx - 160, 178, "ABDUCTION\n(open glottis)", ACCENT_GREEN, bw=148)
box(cx, 178, "ADDUCTION\n(close glottis)", ACCENT_RED, bw=148)
box(cx + 160, 178, "TENSION / RELAXATION\n(pitch control)", MED_BLUE, bw=160)
arr(cx-160, 164, cx-160, 150)
arr(cx, 164, cx-50, 145)
arr(cx, 164, cx+50, 145)
arr(cx+160, 164, cx+70, 145)
arr(cx+160, 164, cx+250, 145)
box(cx-160, 137, "PCA\n(only abductor)", ACCENT_GREEN, bw=145, bh=30)
box(cx-50, 133, "LCA", colors.HexColor("#B03030"), bw=80, bh=22)
box(cx+50, 133, "Trans. Arytenoid\n(Interaryt.)", colors.HexColor("#B03030"), bw=130, bh=28)
box(cx+70, 133, "Thyroarytenoid\n+ Vocalis", MED_BLUE, bw=130, bh=28)
box(cx+250, 133, "Cricothyroid\n(lengthens / tenses)", colors.HexColor("#0F5E90"), bw=155, bh=28)
# Note box
c.setFillColor(PALE_YELLOW)
c.roundRect(10, 68, W-20, 55, 5, fill=1, stroke=0)
c.setStrokeColor(GOLD); c.setLineWidth(1.5)
c.roundRect(10, 68, W-20, 55, 5, fill=0, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(W/2, 113, "IMPORTANT POINTS")
c.setFont("Helvetica", 8.5)
notes = [
"• PCA = ONLY abductor of vocal cord; supplied by RLN",
"• Cricothyroid = ONLY intrinsic muscle supplied by External branch of SLN (not RLN)",
"• Transverse Arytenoid = ONLY unpaired intrinsic muscle",
"• RLN supplies ALL other intrinsic muscles (LCA, PCA, TA, Vocalis, Oblique arytenoid)",
]
for i, n in enumerate(notes):
c.drawString(20, 103 - i*12, n)
story.append(ActionFlowchart(W))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 5. BLOOD SUPPLY & LYMPHATICS
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("5. BLOOD SUPPLY & LYMPHATIC DRAINAGE", bg=DARK_BLUE))
story.append(sp(4))
story.append(sub_header("A. Arterial Supply"))
story.append(sp(3))
art = [
[Paragraph("<b>Artery</b>", TABLE_HDR),
Paragraph("<b>Origin</b>", TABLE_HDR),
Paragraph("<b>Region Supplied</b>", TABLE_HDR),
Paragraph("<b>Accompanies</b>", TABLE_HDR)],
[Paragraph("Superior Laryngeal A.", TABLE_CELL),
Paragraph("Superior thyroid artery (branch of external carotid A.)", TABLE_CELL),
Paragraph("Supraglottis (epiglottis, false cords, upper larynx)", TABLE_CELL),
Paragraph("Internal branch of SLN; pierces thyrohyoid membrane", TABLE_CELL)],
[Paragraph("Inferior Laryngeal A.", TABLE_CELL),
Paragraph("Inferior thyroid artery (branch of thyrocervical trunk → subclavian)", TABLE_CELL),
Paragraph("Subglottis & posterior laryngeal wall", TABLE_CELL),
Paragraph("Recurrent Laryngeal N. (enters larynx under inferior constrictor)", TABLE_CELL)],
[Paragraph("Cricothyroid A. (small)", TABLE_CELL),
Paragraph("Superior thyroid artery", TABLE_CELL),
Paragraph("Cricothyroid region (anastomoses across midline)", TABLE_CELL),
Paragraph("Lies on cricothyroid membrane — risk in cricothyrotomy", TABLE_CELL)],
]
at = Table(art, colWidths=[W*0.20, W*0.25, W*0.28, W*0.27])
at.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, GREY_BG, PALE_YELLOW]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(at)
story.append(sp(6))
story.append(sub_header("B. Venous Drainage"))
story.append(sp(3))
vein_data = [
[Paragraph("<b>Vein</b>", TABLE_HDR),
Paragraph("<b>Drains into</b>", TABLE_HDR)],
[Paragraph("Superior Laryngeal Vein", TABLE_CELL),
Paragraph("Superior thyroid vein → internal jugular vein", TABLE_CELL)],
[Paragraph("Inferior Laryngeal Vein", TABLE_CELL),
Paragraph("Inferior thyroid vein → brachiocephalic vein", TABLE_CELL)],
]
vt = Table(vein_data, colWidths=[W*0.35, W*0.65])
vt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), MED_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, GREY_BG]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(vt)
story.append(sp(6))
story.append(sub_header("C. Lymphatic Drainage (Clinically Important for Cancer Spread)"))
story.append(sp(3))
lymph_data = [
[Paragraph("<b>Region</b>", TABLE_HDR),
Paragraph("<b>Lymphatic Route</b>", TABLE_HDR),
Paragraph("<b>Level of Cervical Nodes</b>", TABLE_HDR)],
[Paragraph("Supraglottis\n(above vocal cords)", TABLE_CELL_C),
Paragraph("Accompany superior laryngeal vessels through thyrohyoid membrane → upper deep cervical nodes\n(RICH lymphatic supply)", TABLE_CELL),
Paragraph("Level II, III (Upper + Mid deep cervical)", TABLE_CELL)],
[Paragraph("Glottis\n(vocal cords)", TABLE_CELL_C),
Paragraph("VERY SPARSE lymphatics → minimal early spread\n(Glottic tumours stay localized longest)", TABLE_CELL),
Paragraph("Level III, IV (if spread occurs)", TABLE_CELL)],
[Paragraph("Subglottis\n(below cords)", TABLE_CELL_C),
Paragraph("Anterior: through cricothyroid membrane → pretracheal (Delphian) nodes\nPosterior: along inferior laryngeal vessels → paratracheal nodes", TABLE_CELL),
Paragraph("Level VI (pretracheal/paratracheal) + Level IV (lower deep cervical)", TABLE_CELL)],
]
lt = Table(lymph_data, colWidths=[W*0.17, W*0.52, W*0.31])
lt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, PALE_GREEN, GREY_BG]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(lt)
story.append(sp(4))
story.append(note("Exam key: Glottic cancers have the BEST prognosis because lymphatics are sparse → late metastasis. Supraglottic cancers spread EARLY to bilateral neck nodes. Subglottic cancers spread to pretracheal (Delphian) nodes."))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 6. INNERVATION
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("6. INNERVATION OF THE LARYNX", bg=DARK_BLUE))
story.append(sp(4))
story.append(Paragraph(
"All innervation of the larynx is by the <b>Vagus Nerve (CN X)</b> via two branches:",
BODY_STYLE))
story.append(sp(4))
inn_data = [
[Paragraph("<b>Nerve</b>", TABLE_HDR),
Paragraph("<b>Fibres</b>", TABLE_HDR),
Paragraph("<b>Distribution</b>", TABLE_HDR),
Paragraph("<b>Clinical Notes</b>", TABLE_HDR)],
[Paragraph("Superior Laryngeal Nerve\n(SLN)\nBranch of vagus at nodose ganglion", TABLE_CELL_C),
Paragraph("", TABLE_CELL_C),
Paragraph("", TABLE_CELL),
Paragraph("", TABLE_CELL)],
[Paragraph(" → Internal branch of SLN", TABLE_CELL),
Paragraph("Sensory\n+ Autonomic", TABLE_CELL_C),
Paragraph("• Mucosa of larynx ABOVE vocal cords (epiglottis, aryepiglottic folds, vestibule, false cords)\n• Afferent for cough reflex above cords", TABLE_CELL),
Paragraph("Block here for awake intubation (topicalises supraglottis); pierces thyrohyoid membrane", TABLE_CELL)],
[Paragraph(" → External branch of SLN", TABLE_CELL),
Paragraph("Motor", TABLE_CELL_C),
Paragraph("• Cricothyroid muscle ONLY\n(the only intrinsic muscle NOT supplied by RLN)", TABLE_CELL),
Paragraph("Runs close to superior thyroid vessels → at risk in thyroidectomy → loss of pitch variation (high notes)", TABLE_CELL)],
[Paragraph("Recurrent Laryngeal Nerve\n(RLN)\nLoop: right – around subclavian A.\nleft – around arch of aorta", TABLE_CELL_C),
Paragraph("Mixed\n(Motor +\nSensory)", TABLE_CELL_C),
Paragraph("Motor: ALL intrinsic muscles EXCEPT cricothyroid (PCA, LCA, TA, thyroarytenoid, vocalis, oblique arytenoid)\nSensory: Mucosa BELOW vocal cords (subglottis, trachea)", TABLE_CELL),
Paragraph("Most vulnerable nerve in thyroid surgery. Unilateral palsy → hoarseness. Bilateral palsy → stridor/respiratory obstruction. Left RLN longer course → more vulnerable to mediastinal pathology (aortic aneurysm, lung cancer, mediastinal nodes)", TABLE_CELL)],
]
it = Table(inn_data, colWidths=[W*0.22, W*0.11, W*0.37, W*0.30])
it.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("BACKGROUND", (0,1), (-1,1), colors.HexColor("#2979B0")),
("ROWBACKGROUNDS",(0,2),(-1,-1),[WHITE, GREY_BG, PALE_YELLOW]),
("GRID", (0,0), (-1,-1), 0.5, BORDER_GREY),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("SPAN", (0,1), (-1,1)),
("TEXTCOLOR", (0,1), (-1,1), WHITE),
("FONTNAME", (0,1), (-1,1), "Helvetica-Bold"),
("ALIGNMENT", (0,1), (-1,1), "CENTER"),
]))
story.append(it)
story.append(sp(6))
# Innervation Flowchart
story.append(sub_header("Flowchart: Laryngeal Innervation"))
story.append(sp(3))
class InnervationFlowchart(Flowable):
def __init__(self, w):
super().__init__()
self._w = w
self.height = 230
def wrap(self, aW, aH):
return (self._w, self.height)
def draw(self):
c = self.canv
W = self._w
def box(x, y, text, bg, fg=colors.white, bw=170, bh=28, r=5):
c.setFillColor(bg)
c.roundRect(x - bw/2, y - bh/2, bw, bh, r, fill=1, stroke=0)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", 8.5)
lines = text.split('\n')
for i, l in enumerate(lines):
c.drawCentredString(x, y + (len(lines)-1)*6 - i*12 - 3, l)
def arr(x1,y1,x2,y2):
c.setStrokeColor(DARK_BLUE); c.setLineWidth(1.2)
c.line(x1,y1,x2,y2)
c.setFillColor(DARK_BLUE)
dx,dy=x2-x1,y2-y1
L=(dx**2+dy**2)**0.5
if L==0: return
ux,uy=dx/L,dy/L
pts=[(x2,y2),(x2-uy*4-ux*8,y2+ux*4-uy*8),(x2+uy*4-ux*8,y2-ux*4-uy*8)]
p=c.beginPath()
p.moveTo(*pts[0]); p.lineTo(*pts[1]); p.lineTo(*pts[2]); p.close()
c.drawPath(p,fill=1,stroke=0)
cx = W/2
box(cx, 218, "VAGUS NERVE (CN X)", DARK_BLUE, bw=220)
arr(cx, 204, cx, 190)
box(cx, 178, "Superior Laryngeal Nerve (SLN)\n(at nodose ganglion)", MED_BLUE, bw=240, bh=32)
# Branch right and left
c.setStrokeColor(MED_BLUE); c.setLineWidth(1.2)
c.line(cx, 162, cx, 152)
c.line(cx - 120, 152, cx + 120, 152)
arr(cx - 120, 152, cx - 120, 135)
arr(cx + 120, 152, cx + 120, 135)
box(cx-120, 122, "Internal Branch\n(SENSORY)", ACCENT_GREEN, bw=160, bh=32)
box(cx+120, 122, "External Branch\n(MOTOR)", colors.HexColor("#E65100"), bw=160, bh=32)
arr(cx-120, 106, cx-120, 90)
arr(cx+120, 106, cx+120, 90)
box(cx-120, 78, "Mucosa ABOVE vocal cords\n(epiglottis → false cords)", ACCENT_GREEN, bw=185, bh=32)
box(cx+120, 78, "Cricothyroid muscle ONLY\n(pitch control)", colors.HexColor("#E65100"), bw=185, bh=32)
# RLN
arr(cx, 162, cx, 55)
box(cx, 44, "Recurrent Laryngeal Nerve (RLN)", colors.HexColor("#6A1B9A"), bw=260)
c.setStrokeColor(colors.HexColor("#6A1B9A")); c.setLineWidth(1.2)
c.line(cx, 30, cx, 22)
c.line(cx - 120, 22, cx + 120, 22)
arr(cx-120, 22, cx-120, 8)
arr(cx+120, 22, cx+120, 8)
# end boxes (bottom area just outside visible — show label)
c.setFillColor(PALE_RED)
c.roundRect(10, -8, 165, 22, 4, fill=1, stroke=0)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica", 8)
c.drawCentredString(92, -1, "Motor: All intrinsic muscles except CT")
c.setFillColor(PALE_GREEN)
c.roundRect(W-175, -8, 165, 22, 4, fill=1, stroke=0)
c.setFillColor(DARK_BLUE)
c.drawCentredString(W-92, -1, "Sensory: Mucosa BELOW vocal cords")
story.append(InnervationFlowchart(W))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 7. ANATOMICAL DIAGRAMS (ASCII-art style schematic with labels)
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("7. SCHEMATIC DIAGRAMS", bg=DARK_BLUE))
story.append(sp(4))
story.append(sub_header("Diagram A: Cartilaginous Framework of Larynx (Anterior View)"))
story.append(sp(3))
class LarynxDiagram(Flowable):
def __init__(self, w):
super().__init__()
self._w = w
self.height = 300
def wrap(self, aW, aH):
return (self._w, self.height)
def draw(self):
c = self.canv
W = self._w
cx = W / 2
# Draw Hyoid Bone
c.setFillColor(colors.HexColor("#795548"))
c.setStrokeColor(colors.HexColor("#795548"))
c.setLineWidth(4)
c.arc(cx - 45, 263, cx + 45, 295, startAng=0, extent=180)
c.setFillColor(colors.black)
c.setFont("Helvetica-Bold", 8)
c.drawString(cx + 55, 275, "Hyoid Bone")
c.setLineWidth(1); c.setStrokeColor(BORDER_GREY)
c.line(cx + 55, 278, cx + 46, 278)
# Thyrohyoid membrane
c.setFillColor(LIGHT_BLUE)
c.setStrokeColor(MED_BLUE)
c.setLineWidth(1)
c.rect(cx - 42, 244, 84, 22, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica", 7.5)
c.drawCentredString(cx, 252, "Thyrohyoid Membrane")
# Thyroid Cartilage
from reportlab.graphics.shapes import Polygon as RLPoly
c.setFillColor(colors.HexColor("#4FC3F7"))
c.setStrokeColor(DARK_BLUE); c.setLineWidth(1.5)
# V shape
p = c.beginPath()
p.moveTo(cx - 48, 244)
p.lineTo(cx + 48, 244)
p.lineTo(cx + 48, 175)
p.lineTo(cx + 10, 152)
p.lineTo(cx - 10, 152)
p.lineTo(cx - 48, 175)
p.close()
c.drawPath(p, fill=1, stroke=1)
# Adam's apple notch
c.setFillColor(colors.white)
p2 = c.beginPath()
p2.moveTo(cx - 8, 244); p2.lineTo(cx, 238); p2.lineTo(cx + 8, 244); p2.close()
c.drawPath(p2, fill=1, stroke=0)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 8.5)
c.drawCentredString(cx, 205, "Thyroid Cartilage")
c.setFont("Helvetica", 7.5)
c.drawCentredString(cx, 194, "(Largest; two laminae)")
# Labels for thyroid
c.setFont("Helvetica", 7.5)
c.setFillColor(DARK_BLUE)
c.drawString(cx + 55, 240, "Superior notch")
c.line(cx + 55, 243, cx + 9, 243)
c.drawString(cx + 55, 175, "Oblique line")
c.line(cx + 55, 178, cx + 48, 193)
c.drawString(cx - 130, 175, "Superior horn")
c.line(cx - 75, 178, cx - 48, 184)
c.drawString(cx - 125, 155, "Inferior horn")
c.line(cx - 70, 158, cx - 40, 162)
# Cricothyroid membrane
c.setFillColor(PALE_YELLOW)
c.setStrokeColor(GOLD); c.setLineWidth(1.5)
c.rect(cx - 35, 138, 70, 16, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 7.5)
c.drawCentredString(cx, 143, "Cricothyroid Membrane")
# Cricoid cartilage
c.setFillColor(colors.HexColor("#80DEEA"))
c.setStrokeColor(DARK_BLUE); c.setLineWidth(1.5)
p3 = c.beginPath()
p3.moveTo(cx - 40, 138)
p3.lineTo(cx + 40, 138)
p3.lineTo(cx + 40, 108)
p3.lineTo(cx - 40, 108)
p3.close()
c.drawPath(p3, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 8.5)
c.drawCentredString(cx, 121, "Cricoid Cartilage")
c.setFont("Helvetica", 7.5)
c.drawCentredString(cx, 110, "(Only complete ring)")
c.drawString(cx + 45, 125, "Arch (anterior)")
c.drawString(cx - 125, 125, "← Lamina (posterior)")
# Tracheal rings
c.setFillColor(GREY_BG)
c.setStrokeColor(BORDER_GREY); c.setLineWidth(1)
for i in range(3):
c.rect(cx - 30, 90 - i*14, 60, 10, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica", 7.5)
c.drawString(cx + 38, 88, "Tracheal rings")
# Epiglottis (leaf shape on upper left)
c.setFillColor(colors.HexColor("#FFD54F"))
c.setStrokeColor(colors.HexColor("#F57F17")); c.setLineWidth(1.2)
p4 = c.beginPath()
p4.moveTo(cx, 265)
p4.curveTo(cx - 30, 290, cx - 45, 310, cx, 310)
p4.curveTo(cx + 45, 310, cx + 30, 290, cx, 265)
c.drawPath(p4, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica", 7.5)
c.drawCentredString(cx, 290, "Epiglottis")
c.drawCentredString(cx, 280, "(behind hyoid)")
story.append(LarynxDiagram(W))
story.append(sp(6))
story.append(sub_header("Diagram B: Arytenoid Cartilage & Vocal Cord Positions"))
story.append(sp(3))
class VocalCordDiagram(Flowable):
def __init__(self, w):
super().__init__()
self._w = w
self.height = 180
def wrap(self, aW, aH):
return (self._w, self.height)
def draw(self):
c = self.canv
W = self._w
def draw_larynx_view(cx, cy, label, abduct=True):
r = 55
# thyroid cartilage outline
c.setFillColor(LIGHT_BLUE)
c.setStrokeColor(DARK_BLUE); c.setLineWidth(1.5)
c.circle(cx, cy, r, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(cx, cy + r + 10, label)
# Epiglottis (top arc)
c.setFillColor(colors.HexColor("#FFD54F"))
c.setStrokeColor(colors.HexColor("#F57F17")); c.setLineWidth(1)
c.arc(cx - 25, cy + 15, cx + 25, cy + r - 5, startAng=0, extent=180)
if abduct:
# Vocal cords wide open (V shape)
c.setStrokeColor(ACCENT_RED); c.setLineWidth(2)
c.line(cx, cy - 5, cx - 35, cy + 20)
c.line(cx, cy - 5, cx + 35, cy + 20)
# Arytenoids (triangles)
c.setFillColor(colors.HexColor("#80DEEA"))
p = c.beginPath(); p.moveTo(cx-35, cy+20); p.lineTo(cx-25, cy+30); p.lineTo(cx-45, cy+30); p.close()
c.drawPath(p, fill=1, stroke=1)
p = c.beginPath(); p.moveTo(cx+35, cy+20); p.lineTo(cx+25, cy+30); p.lineTo(cx+45, cy+30); p.close()
c.drawPath(p, fill=1, stroke=1)
c.setFillColor(ACCENT_GREEN)
c.setFont("Helvetica", 7); c.drawCentredString(cx, cy - 25, "Rima glottidis")
c.drawCentredString(cx, cy - 35, "(wide open)")
c.setFont("Helvetica", 6.5)
c.drawString(cx - 78, cy + 22, "PCA muscle")
else:
# Vocal cords closed
c.setStrokeColor(ACCENT_RED); c.setLineWidth(2)
c.line(cx - 30, cy + 15, cx, cy + 15)
c.line(cx + 30, cy + 15, cx, cy + 15)
# Arytenoids close together
c.setFillColor(colors.HexColor("#80DEEA"))
p = c.beginPath(); p.moveTo(cx-5, cy+15); p.lineTo(cx-12, cy+28); p.lineTo(cx-0, cy+28); p.close()
c.drawPath(p, fill=1, stroke=1)
p = c.beginPath(); p.moveTo(cx+5, cy+15); p.lineTo(cx+12, cy+28); p.lineTo(cx+0, cy+28); p.close()
c.drawPath(p, fill=1, stroke=1)
c.setFillColor(ACCENT_RED)
c.setFont("Helvetica", 7); c.drawCentredString(cx, cy - 25, "Rima glottidis")
c.drawCentredString(cx, cy - 35, "(CLOSED)")
c.setFont("Helvetica", 6.5)
c.drawString(cx - 75, cy + 22, "LCA + TA muscles")
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica", 6.5)
c.drawCentredString(cx, cy - r - 12, "Thyroid Cartilage (anterior)")
draw_larynx_view(W * 0.27, 85, "ABDUCTION (Inspiration)", abduct=True)
draw_larynx_view(W * 0.73, 85, "ADDUCTION (Phonation/Swallowing)", abduct=False)
# Legend
c.setFillColor(PALE_YELLOW)
c.roundRect(W*0.1, 5, W*0.8, 22, 4, fill=1, stroke=0)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica", 8)
c.drawCentredString(W/2, 12,
"LEFT: Vocal cords abducted by PCA (only abductor) | RIGHT: Cords adducted by LCA + Transverse Arytenoid + Thyroarytenoid")
story.append(VocalCordDiagram(W))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 8. CLINICAL NOTES
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("8. CLINICAL NOTES & EXAM PEARLS", bg=ACCENT_RED, fg=WHITE))
story.append(sp(5))
clinical = [
("Cricothyrotomy",
"Emergency airway access through the median cricothyroid ligament (conus elasticus). "
"Safe because no major vessels lie anteriorly (small cricothyroid artery runs superiorly). "
"Enter below thyroid, above cricoid. Used when intubation fails (cannot intubate, cannot ventilate)."),
("RLN Palsy – Thyroidectomy",
"The RLN runs in the tracheoesophageal groove and enters the larynx under the inferior constrictor. "
"Unilateral RLN injury → hoarseness (ipsilateral cord adducted medially). "
"Bilateral injury → both cords adduct → stridor, respiratory distress, may need tracheostomy."),
("External SLN Injury",
"The external branch of SLN runs close to the superior thyroid vessels → at risk during ligation. "
"Supplies cricothyroid (pitch control). Injury → loss of high notes, monotone voice."),
("Rima Glottidis – Narrowest Part",
"In adults: rima glottidis is the narrowest part of the larynx. "
"In infants/children: subglottis (cricoid level) is narrowest → croup affects subglottis causing 'barking' cough and stridor."),
("Laryngeal Cancer Spread",
"Glottic (vocal cord) cancer: Best prognosis, sparse lymphatics, late spread. "
"Supraglottic cancer: Early bilateral node spread (levels II-III). "
"Subglottic cancer: Spreads to pretracheal (Delphian) nodes (level VI) → often present late."),
("Epiglottitis",
"Bacterial (H. influenzae type b) infection of epiglottis. Causes oedema of supraglottic structures. "
"Risk of sudden airway obstruction. 'Thumb sign' on lateral X-ray. "
"Do NOT examine mouth in conscious child (risk of spasm). Secure airway in theatre."),
("Laryngoscopy",
"Indirect laryngoscopy (mirror) or flexible nasendoscopy used to examine larynx. "
"Structures seen from above: epiglottis, aryepiglottic folds, corniculate/cuneiform tubercles, false cords, true cords, interarytenoid region, subglottis."),
("Dental Relevance",
"Laryngeal anatomy is relevant in dental practice for: airway management under GA, "
"understanding aspiration of foreign bodies (falls into RIGHT main bronchus as it is more vertical), "
"recognising signs of airway obstruction, and safe use of local anaesthetic blocks near SLN."),
]
for title, body in clinical:
story.append(KeepTogether([
Paragraph(f"<font color='#{ACCENT_RED.hexval()[2:].upper()}'><b>▶ {title}</b></font>", H3_STYLE),
Paragraph(body, BODY_STYLE),
sp(4),
]))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 9. QUICK-REVISION SUMMARY FLOWCHART
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("9. QUICK-REVISION SUMMARY FLOWCHART", bg=DARK_BLUE))
story.append(sp(5))
class SummaryFlowchart(Flowable):
def __init__(self, w):
super().__init__()
self._w = w
self.height = 350
def wrap(self, aW, aH):
return (self._w, self.height)
def draw(self):
c = self.canv
W = self._w
cx = W / 2
def box(x, y, text, bg, fg=colors.white, bw=180, bh=28, r=5):
c.setFillColor(bg)
c.roundRect(x - bw/2, y - bh/2, bw, bh, r, fill=1, stroke=0)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", 8.5)
lines = text.split('\n')
for i, l in enumerate(lines):
c.drawCentredString(x, y + (len(lines)-1)*6 - i*12 - 3, l)
def arr(x1,y1,x2,y2):
c.setStrokeColor(BORDER_GREY); c.setLineWidth(1.2)
c.line(x1,y1,x2,y2)
c.setFillColor(BORDER_GREY)
dx,dy=x2-x1,y2-y1
L=(dx**2+dy**2)**0.5
if L==0: return
ux,uy=dx/L,dy/L
pts=[(x2,y2),(x2-uy*4-ux*8,y2+ux*4-uy*8),(x2+uy*4-ux*8,y2-ux*4-uy*8)]
p=c.beginPath(); p.moveTo(*pts[0]); p.lineTo(*pts[1]); p.lineTo(*pts[2]); p.close()
c.drawPath(p,fill=1,stroke=0)
# Top
box(cx, 340, "LARYNX (C3-C6)", DARK_BLUE, bw=200, bh=30)
# 6 branches
c.setStrokeColor(BORDER_GREY); c.setLineWidth(1)
c.line(cx, 325, cx, 312)
# spread out
xs = [cx-215, cx-130, cx-45, cx+45, cx+130, cx+215]
c.line(xs[0], 312, xs[-1], 312)
labels = ["Cartilages\n(3+3)", "Membranes &\nLigaments", "Muscles\n(Extrinsic)", "Muscles\n(Intrinsic)", "Blood Supply\n& Lymphatics", "Innervation\n(CN X)"]
clrs = [MED_BLUE, ACCENT_GREEN, colors.HexColor("#7B1FA2"),
colors.HexColor("#E65100"), ACCENT_RED, colors.HexColor("#0277BD")]
for x, lbl, clr in zip(xs, labels, clrs):
arr(x, 312, x, 295)
box(x, 283, lbl, clr, bw=110, bh=30)
# Sub-details row
details = [
"Thy, Cric,\nEpiglottis\nAry, Corn, Cun",
"Conus Elasticus\nQuadrangular\nThyrohyoid M.",
"Sternothyroid\nThyrohyoid\nSuprahyoid gp",
"CT (SLN-ext)\nPCA (only abd)\nLCA, TA, Voc",
"Sup + Inf\nLaryngeal A.\nDrains to IJV",
"SLN (int + ext)\n+ RLN\n(vagus CN X)"
]
for x, det, clr in zip(xs, details, clrs):
arr(x, 268, x, 252)
c.setFillColor(colors.HexColor("#E3F2FD"))
c.roundRect(x - 55, 228, 110, 50, 4, fill=1, stroke=0)
c.setStrokeColor(clr); c.setLineWidth(1.2)
c.roundRect(x - 55, 228, 110, 50, 4, fill=0, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica", 7.5)
lines = det.split('\n')
for i, l in enumerate(lines):
c.drawCentredString(x, 268 - i*12, l)
# Bottom key facts
c.setFillColor(PALE_YELLOW)
c.roundRect(10, 20, W - 20, 150, 6, fill=1, stroke=0)
c.setStrokeColor(GOLD); c.setLineWidth(1.5)
c.roundRect(10, 20, W - 20, 150, 6, fill=0, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 10)
c.drawCentredString(W/2, 158, "⭐ HIGH-YIELD EXAM FACTS ⭐")
c.setFont("Helvetica", 8.5)
facts = [
"1. Cricoid cartilage = ONLY complete ring of airway | Epiglottis = ONLY elastic cartilage (no ossification)",
"2. PCA muscle = ONLY abductor of vocal cords | Cricothyroid = ONLY muscle by external SLN (not RLN)",
"3. Transverse Arytenoid = ONLY unpaired intrinsic muscle of larynx",
"4. Glottis has LEAST lymphatics → best prognosis for cancer | Supraglottis → richest → worst spread",
"5. RLN runs in tracheoesophageal groove; Left RLN longer (loops under aortic arch)",
"6. Narrowest part: Adults = rima glottidis; Children = subglottis (cricoid level) – important in croup/intubation",
"7. Median cricothyroid ligament: safe emergency access (cricothyrotomy); no major anterior vessels",
"8. Internal SLN pierces thyrohyoid membrane; carries sensory supply to supraglottis (afferent for cough reflex)",
"9. Superior laryngeal A. accompanies internal branch of SLN through thyrohyoid membrane",
"10. Cartilago triticea: sesamoid cartilage in lateral thyrohyoid ligament (may be mistaken for foreign body on X-ray)",
]
for i, f in enumerate(facts):
c.drawString(20, 146 - i*12, f)
story.append(SummaryFlowchart(W))
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════════════
# 10. MNEMONICS & LAST-MINUTE REVISION
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("10. MNEMONICS & LAST-MINUTE REVISION", bg=ACCENT_GREEN))
story.append(sp(5))
mnemonics = [
("Cartilages (6 total)",
"\"Three Crows Eat Apples, Cats Curl\"\n"
"→ Thyroid, Cricoid, Epiglottis | Arytenoid, Corniculate, Cuneiform"),
("Unpaired cartilages",
"\"T.C.E\" → Thyroid, Cricoid, Epiglottis"),
("Intrinsic muscles supplied by RLN",
"\"PLAT + VO\" → PCA, LCA, Arytenoids (transverse + oblique), Thyroarytenoid, VOcalis\n"
"(Exception: Cricothyroid → External SLN)"),
("Only abductor of vocal cord",
"\"PCA = Please Clear Airway\" → Posterior CricOARytenoid is ONLY Abductor"),
("Narrowest part (age difference)",
"Children: Sub-glottis (Cricoid) — 'C for Children, C for Cricoid'\n"
"Adults: Rima Glottidis — 'Adults Reach the top = Glottis is top/narrowest'"),
("Lymphatics by region – prognosis",
"Glottis = Good prognosis (sparse lymphatics)\n"
"Supraglottis = Spreads Swiftly (rich bilateral lymphatics)\n"
"Sub-glottis = Spreads to pretracheal/paratracheal nodes"),
("Nerve supply summary",
"SLN (external branch) → Cricothyroid ONLY\n"
"SLN (internal branch) → Sensory ABOVE cords\n"
"RLN → ALL other intrinsic + Sensory BELOW cords"),
]
for title, content in mnemonics:
story.append(KeepTogether([
ColorBox(title, W, bg=ACCENT_GREEN, fg=WHITE, height=18,
style=S("mn", fontSize=9.5, textColor=WHITE)),
sp(2),
Paragraph(content, S("Normal", fontSize=9, leading=14, leftIndent=10)),
sp(5),
]))
# ────────────────────────────────
# Final reference line
story.append(hline(DARK_BLUE, 1))
story.append(sp(4))
story.append(Paragraph(
"<b>References:</b> BD Chaurasia's Human Anatomy for Dental Students, 5th Edition (Head & Neck, Chapter: Larynx) | "
"Gray's Anatomy for Students, 5th Ed. (Chapter 8 – Head & Neck) | "
"Scott-Brown's Otorhinolaryngology Head & Neck Surgery, 8th Ed. | "
"Miller's Anesthesia, 10th Ed. (Laryngeal Anatomy section)",
SMALL_STYLE))
story.append(sp(3))
story.append(Paragraph(
"Compiled by <b>Orris AI</b> · July 2026 · For educational purposes only",
FOOT_STYLE))
# ════════════════════════════════════════════════════════════════════════════
# BUILD PDF
# ════════════════════════════════════════════════════════════════════════════
doc.build(story)
print(f"PDF generated: {OUTPUT_PATH}")
cd /tmp/workspace/larynx-pdf && python generate_larynx_pdf.py 2>&1
~/larynx-pdf/generate_larynx_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/larynx-pdf/generate_larynx_pdf.py'
cd /tmp/workspace/larynx-pdf && python generate_larynx_pdf.py 2>&1
ls -lh /tmp/workspace/larynx-pdf/
Give me pdf foR 10 mark on Larynx that includes Gross anatomy, cartilages, membrane,Ligaments Muscles, action drainage the innervation with diagram tables Flowchart and points By Refer BD Chaurasia's Human Anatomy for dental Students 5ᵗʰ edition & add extra Points if needed supply
Download the Larynx PDF I just created for you