Viva ans.
| Feature | Parotid | Submandibular | Sublingual |
|---|---|---|---|
| Type | Purely serous | Mixed (predominantly serous) | Mixed (predominantly mucous) |
| Acini | Serous only | Serous + mucous with serous demilunes | Mucous + few serous demilunes |
| Intercalated ducts | Long, well-developed | Shorter | Virtually absent |
| Striated ducts | Prominent | Well developed | Short/few |
| Excretory duct | Long (Stensen's duct ~5 cm) | Wharton's duct | Multiple ducts of Rivinus |
| Serous cells | Contain zymogen granules | Contain zymogen + mucous granules | Mainly mucous cells |
| Fat cells | Common in adults (increase with age) | Less | Less |
| Q | Key Point |
|---|---|
| 5 | Inside parotid: Facial N, Ext. carotid A, Retromandibular V, Parotid LN, Auriculotemporal N |
| 6 | Parotid duct opens opposite upper 2nd molar |
| 7 | 2 capsules: true (own CT) + false (investing deep cervical fascia) |
| 8 | Painful: tight capsule. Orchitis: hematogenous spread of mumps virus |
| 12 | Superior = external laryngeal N; Inferior = recurrent laryngeal N + parathyroid supply |
| 13 | Pretracheal fascia binds thyroid to larynx/trachea → moves with swallowing |
| 15 | Ectopic thyroid = failed descent; lingual thyroid most common |
| 16 | Thyroglossal cyst = thyroglossal duct remnant; moves on swallowing + tongue protrusion |
| 19 | Tract = axonal (ADH, OT): supraoptic/paraventricular → posterior pituitary |
| 20 | Portal system = hypothalamic releasing hormones → anterior pituitary |
| 21 | BBB absent: fenestrated capillaries, neurohaemal organ, CVO - needed for hormone release |
Make a pdf with complete visualisation
mkdir -p /tmp/workspace/glands-viva && ls /tmp/workspace/glands-viva/
~/glands-viva/make_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, PageBreak, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus.flowables import Flowable
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle, Polygon
from reportlab.graphics import renderPDF
import math
# ─── COLOUR PALETTE ────────────────────────────────────────────────
NAVY = colors.HexColor("#1a2e4a")
TEAL = colors.HexColor("#1abc9c")
GOLD = colors.HexColor("#f39c12")
LIGHT_BLUE = colors.HexColor("#d6eaf8")
LIGHT_TEAL = colors.HexColor("#d1f2eb")
LIGHT_GOLD = colors.HexColor("#fef9e7")
LIGHT_GREY = colors.HexColor("#f4f6f7")
MID_GREY = colors.HexColor("#bdc3c7")
DARK_GREY = colors.HexColor("#5d6d7e")
RED = colors.HexColor("#e74c3c")
LIGHT_RED = colors.HexColor("#fadbd8")
PURPLE = colors.HexColor("#8e44ad")
LIGHT_PURPLE = colors.HexColor("#f5eef8")
GREEN = colors.HexColor("#27ae60")
LIGHT_GREEN = colors.HexColor("#eafaf1")
ORANGE = colors.HexColor("#e67e22")
LIGHT_ORANGE = colors.HexColor("#fdebd0")
WHITE = colors.white
BLACK = colors.black
PAGE_W, PAGE_H = A4
MARGIN = 18 * mm
# ─── STYLES ────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
base = styles.get(name, styles["Normal"])
return ParagraphStyle(name + str(id(kw)), parent=base, **kw)
title_style = S("Normal",
fontSize=28, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=34)
subtitle_style = S("Normal",
fontSize=13, textColor=colors.HexColor("#aed6f1"),
alignment=TA_CENTER, fontName="Helvetica", leading=18)
q_style = S("Normal",
fontSize=13, textColor=WHITE, fontName="Helvetica-Bold",
leading=17, leftIndent=4)
h1_style = S("Normal",
fontSize=11, textColor=NAVY, fontName="Helvetica-Bold",
leading=15, spaceBefore=4, spaceAfter=2)
body_style = S("Normal",
fontSize=9.5, textColor=colors.HexColor("#2c3e50"),
fontName="Helvetica", leading=14, spaceAfter=2,
leftIndent=8, alignment=TA_JUSTIFY)
bullet_style = S("Normal",
fontSize=9.5, textColor=colors.HexColor("#2c3e50"),
fontName="Helvetica", leading=14, leftIndent=14,
bulletIndent=6, spaceAfter=1)
key_style = S("Normal",
fontSize=9, textColor=NAVY, fontName="Helvetica-Bold",
leading=13, leftIndent=8, spaceAfter=1)
note_style = S("Normal",
fontSize=8.5, textColor=DARK_GREY, fontName="Helvetica-Oblique",
leading=12, leftIndent=8)
cell_style = S("Normal",
fontSize=8.5, textColor=colors.HexColor("#2c3e50"),
fontName="Helvetica", leading=12)
cell_bold = S("Normal",
fontSize=8.5, textColor=NAVY, fontName="Helvetica-Bold",
leading=12)
# ─── HELPER FLOWABLES ──────────────────────────────────────────────
def spacer(h=4):
return Spacer(1, h * mm)
def hr(color=TEAL, thickness=0.5):
return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=2*mm, spaceBefore=1*mm)
def section_header(num, question, color=NAVY, bg=LIGHT_BLUE):
"""Returns a styled question-number + question block."""
badge_text = f"Q{num}"
data = [[
Paragraph(f'<font color="white"><b>{badge_text}</b></font>',
S("Normal", fontSize=11, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=14)),
Paragraph(question,
S("Normal", fontSize=10.5, fontName="Helvetica-Bold",
textColor=NAVY, leading=14))
]]
t = Table(data, colWidths=[14*mm, PAGE_W - 2*MARGIN - 14*mm - 4*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), TEAL),
("BACKGROUND", (1,0), (1,0), bg),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("ROWBACKGROUNDS", (0,0), (-1,-1), [None]),
("ROUNDEDCORNERS", [3]),
]))
return t
def bullet(text, indent=0):
return Paragraph(f"• {text}", S("Normal",
fontSize=9.5, textColor=colors.HexColor("#2c3e50"),
fontName="Helvetica", leading=14,
leftIndent=14+indent, bulletIndent=6+indent, spaceAfter=1))
def sub_bullet(text):
return Paragraph(f" – {text}", S("Normal",
fontSize=9, textColor=DARK_GREY,
fontName="Helvetica", leading=13,
leftIndent=22, spaceAfter=1))
def key_point(label, text):
return Paragraph(f'<font color="#1a2e4a"><b>{label}:</b></font> {text}', body_style)
def info_box(text, bg=LIGHT_TEAL, border=TEAL):
data = [[Paragraph(text, S("Normal", fontSize=9, fontName="Helvetica",
textColor=colors.HexColor("#1a5276"),
leading=13, leftIndent=2))]]
t = Table(data, colWidths=[PAGE_W - 2*MARGIN - 4*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("BOX", (0,0), (-1,-1), 1.2, border),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
]))
return t
def warning_box(text):
return info_box(f"⚠ <b>Clinical Pearl:</b> {text}", bg=LIGHT_GOLD, border=GOLD)
def make_table(headers, rows, col_widths=None, header_bg=NAVY):
data = [[Paragraph(h, S("Normal", fontSize=8.5, fontName="Helvetica-Bold",
textColor=WHITE, leading=11, alignment=TA_CENTER)) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), S("Normal", fontSize=8, fontName="Helvetica",
textColor=colors.HexColor("#2c3e50"),
leading=11)) for c in row])
w = col_widths or [(PAGE_W - 2*MARGIN - 4*mm) / len(headers)] * len(headers)
t = Table(data, colWidths=w)
style = [
("BACKGROUND", (0,0), (-1,0), header_bg),
("ROWBACKGROUNDS", (0,1), (-1,-1), [LIGHT_GREY, WHITE]),
("GRID", (0,0), (-1,-1), 0.4, MID_GREY),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("ALIGN", (0,0), (-1,-1), "LEFT"),
]
t.setStyle(TableStyle(style))
return t
# ─── DIAGRAM FLOWABLES ─────────────────────────────────────────────
class ParotidDiagram(Flowable):
"""Schematic of parotid gland showing contents from superficial to deep."""
def __init__(self, w=170*mm, h=90*mm):
super().__init__()
self.width = w
self.height = h
def draw(self):
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle, Polygon, Path
c = self.canv
W, H = self.width, self.height
# Background
c.setFillColor(colors.HexColor("#eaf4fb"))
c.roundRect(0, 0, W, H, 6, fill=1, stroke=0)
# Title
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 10)
c.drawCentredString(W/2, H-10*mm, "Structures Inside the Parotid Gland (Superficial → Deep)")
# Gland outline (ellipse)
cx, cy = W*0.38, H*0.45
rx, ry = W*0.25, H*0.36
c.setStrokeColor(colors.HexColor("#f39c12"))
c.setFillColor(colors.HexColor("#fef5e7"))
c.setLineWidth(2)
c.ellipse(cx-rx, cy-ry, cx+rx, cy+ry, fill=1, stroke=1)
c.setFillColor(colors.HexColor("#e67e22"))
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(cx, cy + ry + 4*mm, "PAROTID GLAND")
# Layers from superficial to deep (as horizontal bands inside ellipse)
layers = [
(0.85, colors.HexColor("#f9e79f"), "Parotid Lymph Nodes"),
(0.62, colors.HexColor("#a9cce3"), "Facial Nerve [VII] & branches"),
(0.42, colors.HexColor("#f1948a"), "Retromandibular Vein"),
(0.22, colors.HexColor("#a9dfbf"), "External Carotid Artery"),
]
for frac, col, label in layers:
y_pos = cy - ry + frac * 2 * ry
half_w = rx * math.sqrt(max(0, 1 - ((y_pos - cy)/ry)**2)) * 0.9
c.setFillColor(col)
c.setStrokeColor(WHITE)
c.setLineWidth(0.5)
c.rect(cx - half_w, y_pos - 5, half_w*2, 10, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica", 7.5)
c.drawCentredString(cx, y_pos - 2.5, label)
# Legend / arrows on right side
legend_x = W * 0.70
legend_y = H * 0.82
entries = [
(colors.HexColor("#f9e79f"), "Lymph Nodes (superficial)"),
(colors.HexColor("#a9cce3"), "Facial N. [VII]"),
(colors.HexColor("#f1948a"), "Retromandibular Vein"),
(colors.HexColor("#a9dfbf"), "Ext. Carotid Artery (deep)"),
]
c.setFont("Helvetica-Bold", 8)
c.setFillColor(NAVY)
c.drawString(legend_x, legend_y + 4*mm, "Contents (S→D):")
for i, (col, lbl) in enumerate(entries):
y = legend_y - i * 9*mm
c.setFillColor(col)
c.rect(legend_x, y - 3, 8, 8, fill=1, stroke=0)
c.setFillColor(DARK_GREY)
c.setFont("Helvetica", 7.5)
c.drawString(legend_x + 10*mm, y - 2, lbl)
# Mnemonic
c.setFillColor(LIGHT_TEAL)
c.roundRect(W*0.02, 2*mm, W*0.44, 10*mm, 4, fill=1, stroke=0)
c.setFillColor(TEAL)
c.setFont("Helvetica-Bold", 8)
c.drawString(W*0.04, 5*mm, "Mnemonic: Some Teenagers Are Really Playful")
c.setFont("Helvetica", 7)
c.setFillColor(DARK_GREY)
c.drawString(W*0.04, 2.5*mm, "Skin · Trunk(Facial N) · Artery(Ext Carotid) · Retromandibular V · Parotid nodes")
class ThyroidDiagram(Flowable):
"""Schematic of thyroid gland anatomy."""
def __init__(self, w=170*mm, h=100*mm):
super().__init__()
self.width = w
self.height = h
def draw(self):
c = self.canv
W, H = self.width, self.height
c.setFillColor(colors.HexColor("#e8f8f5"))
c.roundRect(0, 0, W, H, 6, fill=1, stroke=0)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 10)
c.drawCentredString(W/2, H - 9*mm, "Thyroid Gland – Anatomy & Blood Supply")
# Trachea (central cylinder)
tc_x, tc_y = W*0.42, H*0.22
tc_w, tc_h = 24*mm, 40*mm
c.setFillColor(colors.HexColor("#d5d8dc"))
c.setStrokeColor(MID_GREY)
c.setLineWidth(1)
c.roundRect(tc_x, tc_y, tc_w, tc_h, 4, fill=1, stroke=1)
c.setFillColor(DARK_GREY)
c.setFont("Helvetica", 7)
for i in range(4):
yy = tc_y + 8*mm + i*8*mm
if yy < tc_y + tc_h - 4*mm:
c.setStrokeColor(MID_GREY)
c.setLineWidth(0.7)
c.line(tc_x + 2*mm, yy, tc_x + tc_w - 2*mm, yy)
c.setFillColor(DARK_GREY)
c.setFont("Helvetica", 7.5)
c.drawCentredString(tc_x + tc_w/2, tc_y - 5*mm, "Trachea")
# Thyroid lobes
lobe_h = 32*mm
lobe_w = 20*mm
# Right lobe
rl_x = tc_x - lobe_w - 1*mm
rl_y = tc_y + 4*mm
c.setFillColor(colors.HexColor("#a9dfbf"))
c.setStrokeColor(GREEN)
c.setLineWidth(1.5)
c.roundRect(rl_x, rl_y, lobe_w, lobe_h, 6, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 7.5)
c.drawCentredString(rl_x + lobe_w/2, rl_y + lobe_h/2 - 3, "Right")
c.drawCentredString(rl_x + lobe_w/2, rl_y + lobe_h/2 - 11, "Lobe")
# Left lobe
ll_x = tc_x + tc_w + 1*mm
ll_y = tc_y + 4*mm
c.setFillColor(colors.HexColor("#a9dfbf"))
c.setStrokeColor(GREEN)
c.setLineWidth(1.5)
c.roundRect(ll_x, ll_y, lobe_w, lobe_h, 6, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 7.5)
c.drawCentredString(ll_x + lobe_w/2, ll_y + lobe_h/2 - 3, "Left")
c.drawCentredString(ll_x + lobe_w/2, ll_y + lobe_h/2 - 11, "Lobe")
# Isthmus
ist_y = tc_y + 12*mm
ist_h = 8*mm
c.setFillColor(colors.HexColor("#7dcea0"))
c.setStrokeColor(GREEN)
c.setLineWidth(1)
c.rect(tc_x, ist_y, tc_w, ist_h, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(tc_x + tc_w/2, ist_y + 2.5*mm, "Isthmus")
# Pyramidal lobe
pyr_x = tc_x + tc_w/2 - 4*mm
pyr_y = ist_y + ist_h
c.setFillColor(colors.HexColor("#58d68d"))
c.setStrokeColor(GREEN)
path = c.beginPath()
path.moveTo(pyr_x, pyr_y)
path.lineTo(pyr_x + 8*mm, pyr_y)
path.lineTo(pyr_x + 4*mm, pyr_y + 14*mm)
path.close()
c.drawPath(path, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica", 6.5)
c.drawCentredString(pyr_x + 4*mm, pyr_y + 15*mm, "Pyramidal lobe")
# Superior thyroid arteries
c.setStrokeColor(RED)
c.setLineWidth(1.5)
# Right STA
c.line(rl_x + lobe_w/2, rl_y + lobe_h, rl_x + lobe_w/2, rl_y + lobe_h + 12*mm)
c.setFillColor(RED)
c.setFont("Helvetica", 7)
c.drawCentredString(rl_x + lobe_w/2, rl_y + lobe_h + 13*mm, "Sup. Thyroid A.")
# Left STA
c.setStrokeColor(RED)
c.line(ll_x + lobe_w/2, ll_y + lobe_h, ll_x + lobe_w/2, ll_y + lobe_h + 12*mm)
c.drawCentredString(ll_x + lobe_w/2, ll_y + lobe_h + 13*mm, "Sup. Thyroid A.")
# Inferior thyroid arteries
c.setStrokeColor(colors.HexColor("#c0392b"))
c.setLineWidth(1.2)
c.line(rl_x + lobe_w/2, rl_y, rl_x + lobe_w/2, rl_y - 8*mm)
c.setFillColor(colors.HexColor("#c0392b"))
c.setFont("Helvetica", 7)
c.drawCentredString(rl_x + lobe_w/2, rl_y - 10*mm, "Inf. Thyroid A.")
c.setStrokeColor(colors.HexColor("#c0392b"))
c.line(ll_x + lobe_w/2, ll_y, ll_x + lobe_w/2, ll_y - 8*mm)
c.drawCentredString(ll_x + lobe_w/2, ll_y - 10*mm, "Inf. Thyroid A.")
# RLN labels
c.setFillColor(PURPLE)
c.setFont("Helvetica-BoldOblique", 7)
c.drawString(rl_x - 18*mm, rl_y + 10*mm, "RLN →")
c.drawString(ll_x + lobe_w + 2*mm, ll_y + 10*mm, "← RLN")
# Parathyroid dots
for (px, py) in [(rl_x + 2, rl_y + 22*mm), (rl_x + 2, rl_y + 10*mm),
(ll_x + lobe_w - 6, ll_y + 22*mm), (ll_x + lobe_w - 6, ll_y + 10*mm)]:
c.setFillColor(colors.HexColor("#f39c12"))
c.circle(px + 2, py, 3*mm, fill=1, stroke=0)
c.setFillColor(GOLD)
c.setFont("Helvetica-Bold", 7)
c.drawString(W*0.01, H*0.38, "● Parathyroid")
c.drawString(W*0.01, H*0.33, " glands (×4)")
# Pretracheal fascia label
c.setFillColor(colors.HexColor("#7fb3d3"))
c.setFont("Helvetica-Oblique", 7)
c.drawString(W*0.68, H*0.42, "Pretracheal fascia")
c.drawString(W*0.68, H*0.37, "→ moves with")
c.drawString(W*0.68, H*0.32, " deglutition")
class SalivaryHistoDiagram(Flowable):
"""Comparison diagram of histology of 3 major salivary glands."""
def __init__(self, w=170*mm, h=70*mm):
super().__init__()
self.width = w
self.height = h
def draw(self):
c = self.canv
W, H = self.width, self.height
c.setFillColor(colors.HexColor("#f8f9fa"))
c.roundRect(0, 0, W, H, 5, fill=1, stroke=0)
c.setFont("Helvetica-Bold", 9.5)
c.setFillColor(NAVY)
c.drawCentredString(W/2, H - 8*mm, "Histological Comparison of Major Salivary Glands")
panels = [
("Parotid", colors.HexColor("#d6eaf8"), colors.HexColor("#2980b9"),
"Purely SEROUS", ["Serous acini only", "Long intercalated ducts",
"Prominent striated ducts", "↑ Fat with age"]),
("Submandibular", colors.HexColor("#d5f5e3"), colors.HexColor("#1e8449"),
"Mixed (Pred. SEROUS)", ["Serous + mucous acini", "Serous demilunes",
"Shorter intercalated ducts", "Well-developed ducts"]),
("Sublingual", colors.HexColor("#fdebd0"), colors.HexColor("#d35400"),
"Mixed (Pred. MUCOUS)", ["Mucous acini dominant", "Few serous demilunes",
"Absent intercalated ducts", "Short striated ducts"]),
]
pw = (W - 6*mm) / 3
for i, (name, bg, hdr_col, type_text, bullets) in enumerate(panels):
px = 2*mm + i * pw
py = 2*mm
ph = H - 12*mm
c.setFillColor(bg)
c.roundRect(px, py, pw - 1*mm, ph, 5, fill=1, stroke=0)
c.setFillColor(hdr_col)
c.roundRect(px, py + ph - 14*mm, pw - 1*mm, 14*mm, 5, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(px + (pw - 1*mm)/2, py + ph - 8*mm, name)
c.setFont("Helvetica-BoldOblique", 7)
c.drawCentredString(px + (pw - 1*mm)/2, py + ph - 13*mm, type_text)
c.setFillColor(NAVY)
c.setFont("Helvetica", 7.5)
for j, bl in enumerate(bullets):
yy = py + ph - 18*mm - j*7.5*mm
c.drawString(px + 3*mm, yy, f"• {bl}")
# Simple acinar diagram
acini_x = px + (pw-1*mm)/2
acini_y = py + 12*mm
if i == 0: # parotid - all serous (blue dots)
for dx, dy in [(-6,4), (0,8), (6,4), (-3,-2), (3,-2)]:
c.setFillColor(colors.HexColor("#5dade2"))
c.circle(acini_x + dx*mm, acini_y + dy*mm, 2.5*mm, fill=1, stroke=0)
elif i == 1: # submandibular - mixed
for dx, dy in [(-6,4), (6,4), (-3,-2)]:
c.setFillColor(colors.HexColor("#5dade2"))
c.circle(acini_x + dx*mm, acini_y + dy*mm, 2.5*mm, fill=1, stroke=0)
for dx, dy in [(0,8), (3,-2)]:
c.setFillColor(colors.HexColor("#f0b27a"))
c.circle(acini_x + dx*mm, acini_y + dy*mm, 2.5*mm, fill=1, stroke=0)
else: # sublingual - mostly mucous
for dx, dy in [(-6,4), (0,8), (6,4), (3,-2)]:
c.setFillColor(colors.HexColor("#f0b27a"))
c.circle(acini_x + dx*mm, acini_y + dy*mm, 2.5*mm, fill=1, stroke=0)
for dx, dy in [(-3,-2)]:
c.setFillColor(colors.HexColor("#5dade2"))
c.circle(acini_x + dx*mm, acini_y + dy*mm, 2.5*mm, fill=1, stroke=0)
# Legend
legend_y = 0.5*mm
c.setFillColor(colors.HexColor("#5dade2"))
c.rect(W*0.3, legend_y, 6, 6, fill=1, stroke=0)
c.setFillColor(DARK_GREY)
c.setFont("Helvetica", 7)
c.drawString(W*0.3 + 8, legend_y + 1, "Serous acini")
c.setFillColor(colors.HexColor("#f0b27a"))
c.rect(W*0.5, legend_y, 6, 6, fill=1, stroke=0)
c.drawString(W*0.5 + 8, legend_y + 1, "Mucous acini")
class ThyroglosalDiagram(Flowable):
"""Thyroglossal cyst development diagram."""
def __init__(self, w=170*mm, h=80*mm):
super().__init__()
self.width = w
self.height = h
def draw(self):
c = self.canv
W, H = self.width, self.height
c.setFillColor(colors.HexColor("#fdfefe"))
c.roundRect(0, 0, W, H, 5, fill=1, stroke=0)
c.setFont("Helvetica-Bold", 10)
c.setFillColor(NAVY)
c.drawCentredString(W/2, H - 8*mm, "Thyroid Development & Thyroglossal Cyst")
# Midline sagittal view
mid_x = W * 0.45
# Foramen cecum (tongue base)
c.setFillColor(colors.HexColor("#fdebd0"))
c.roundRect(mid_x - 18*mm, H*0.75, 36*mm, 12*mm, 5, fill=1, stroke=0)
c.setStrokeColor(ORANGE)
c.roundRect(mid_x - 18*mm, H*0.75, 36*mm, 12*mm, 5, fill=0, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(mid_x, H*0.75 + 6*mm, "Tongue Base")
c.setFillColor(ORANGE)
c.setFont("Helvetica", 7)
c.drawCentredString(mid_x, H*0.75 + 2*mm, "Foramen Cecum (origin)")
# Descent path
c.setStrokeColor(colors.HexColor("#85c1e9"))
c.setLineWidth(2)
c.setDash([3,3])
c.line(mid_x, H*0.75, mid_x, H*0.20)
c.setDash([])
# Hyoid bone
hyoid_y = H * 0.58
c.setFillColor(colors.HexColor("#d5d8dc"))
c.setStrokeColor(MID_GREY)
c.setLineWidth(1)
c.roundRect(mid_x - 14*mm, hyoid_y - 3*mm, 28*mm, 6*mm, 3, fill=1, stroke=1)
c.setFillColor(DARK_GREY)
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(mid_x, hyoid_y - 0.5*mm, "Hyoid Bone")
# Thyroid cartilage
thyc_y = H * 0.42
c.setFillColor(colors.HexColor("#eaf2ff"))
c.setStrokeColor(colors.HexColor("#5dade2"))
c.roundRect(mid_x - 16*mm, thyc_y - 3*mm, 32*mm, 6*mm, 3, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 7)
c.drawCentredString(mid_x, thyc_y - 0.5*mm, "Thyroid Cartilage")
# Final thyroid position
c.setFillColor(colors.HexColor("#a9dfbf"))
c.setStrokeColor(GREEN)
c.setLineWidth(1.5)
c.roundRect(mid_x - 18*mm, H*0.12, 36*mm, 14*mm, 5, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(mid_x, H*0.12 + 7.5*mm, "Final Position of Thyroid")
c.setFont("Helvetica", 7)
c.drawCentredString(mid_x, H*0.12 + 3*mm, "Anterior to trachea, below cricoid")
# Cyst possibilities
positions = [
(H*0.70, colors.HexColor("#f9ebea"), RED, "Lingual thyroid"),
(H*0.60, colors.HexColor("#f9ebea"), RED, "Sublingual cyst"),
(H*0.50, colors.HexColor("#f9ebea"), RED, "Suprahyoid cyst"),
(H*0.42, colors.HexColor("#f9ebea"), RED, "At hyoid"),
(H*0.30, colors.HexColor("#f9ebea"), RED, "Infrahyoid (most common 65%)"),
]
for yy, bg, bc, lbl in positions:
cx2 = mid_x + 28*mm
c.setFillColor(bg)
c.setStrokeColor(bc)
c.setLineWidth(0.7)
c.roundRect(cx2, yy - 3*mm, 38*mm, 7*mm, 3, fill=1, stroke=1)
c.setFillColor(RED)
c.setFont("Helvetica", 7)
c.drawString(cx2 + 2*mm, yy - 0.5*mm, lbl)
c.setStrokeColor(RED)
c.setLineWidth(0.5)
c.setDash([2,2])
c.line(mid_x, yy + 0.5*mm, cx2, yy + 0.5*mm)
c.setDash([])
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 8)
c.drawString(mid_x + 28*mm, H*0.76, "Sites of Ectopic/Cysts:")
# Sistrunk note
c.setFillColor(LIGHT_TEAL)
c.roundRect(1*mm, 0.5*mm, 38*mm, 10*mm, 3, fill=1, stroke=0)
c.setFillColor(TEAL)
c.setFont("Helvetica-Bold", 7)
c.drawString(3*mm, 7*mm, "Sistrunk Operation:")
c.setFillColor(DARK_GREY)
c.setFont("Helvetica", 6.5)
c.drawString(3*mm, 3.5*mm, "Cyst + central hyoid + tract to foramen cecum")
class PituitaryDiagram(Flowable):
"""Pituitary gland – divisions and tracts diagram."""
def __init__(self, w=170*mm, h=85*mm):
super().__init__()
self.width = w
self.height = h
def draw(self):
c = self.canv
W, H = self.width, self.height
c.setFillColor(colors.HexColor("#f5eef8"))
c.roundRect(0, 0, W, H, 5, fill=1, stroke=0)
c.setFont("Helvetica-Bold", 10)
c.setFillColor(NAVY)
c.drawCentredString(W/2, H - 8*mm, "Pituitary Gland – Divisions, Tracts & Portal System")
# Hypothalamus box
c.setFillColor(colors.HexColor("#d2b4de"))
c.setStrokeColor(PURPLE)
c.setLineWidth(1.5)
c.roundRect(W*0.28, H*0.72, W*0.44, 14*mm, 5, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(W/2, H*0.72 + 9*mm, "HYPOTHALAMUS")
c.setFont("Helvetica", 7.5)
c.drawCentredString(W/2, H*0.72 + 4*mm, "Supraoptic & Paraventricular nuclei")
# Stalk
stalk_x = W/2 - 5*mm
stalk_y_top = H*0.72
stalk_y_bot = H*0.46
c.setFillColor(colors.HexColor("#d7bde2"))
c.rect(stalk_x, stalk_y_bot, 10*mm, stalk_y_top - stalk_y_bot, fill=1, stroke=0)
c.setFillColor(PURPLE)
c.setFont("Helvetica-Oblique", 7)
c.drawCentredString(W/2 + 14*mm, (stalk_y_top + stalk_y_bot)/2, "Infundibular stalk")
# Anterior pituitary
c.setFillColor(colors.HexColor("#aed6f1"))
c.setStrokeColor(colors.HexColor("#2980b9"))
c.setLineWidth(1.5)
c.roundRect(W*0.08, H*0.15, W*0.37, H*0.30, 6, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 8.5)
c.drawCentredString(W*0.08 + W*0.37/2, H*0.15 + H*0.30*0.72, "ANTERIOR PITUITARY")
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(colors.HexColor("#1a5276"))
c.drawCentredString(W*0.08 + W*0.37/2, H*0.15 + H*0.30*0.52, "Adenohypophysis")
hormones_ant = ["TSH LH FSH", "GH ACTH Prolactin"]
c.setFont("Helvetica", 7)
c.setFillColor(DARK_GREY)
for j, h_text in enumerate(hormones_ant):
c.drawCentredString(W*0.08 + W*0.37/2, H*0.15 + H*0.30*0.30 - j*8*mm, h_text)
# Posterior pituitary
c.setFillColor(colors.HexColor("#a9dfbf"))
c.setStrokeColor(GREEN)
c.setLineWidth(1.5)
c.roundRect(W*0.55, H*0.15, W*0.37, H*0.30, 6, fill=1, stroke=1)
c.setFillColor(NAVY)
c.setFont("Helvetica-Bold", 8.5)
c.drawCentredString(W*0.55 + W*0.37/2, H*0.15 + H*0.30*0.72, "POSTERIOR PITUITARY")
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(colors.HexColor("#1e8449"))
c.drawCentredString(W*0.55 + W*0.37/2, H*0.15 + H*0.30*0.52, "Neurohypophysis")
c.setFont("Helvetica", 7)
c.setFillColor(DARK_GREY)
c.drawCentredString(W*0.55 + W*0.37/2, H*0.15 + H*0.30*0.30, "ADH + Oxytocin")
c.setFont("Helvetica-BoldOblique", 6.5)
c.setFillColor(RED)
c.drawCentredString(W*0.55 + W*0.37/2, H*0.15 + H*0.30*0.12, "No BBB (CVO)")
# Portal system arrows (left)
c.setStrokeColor(colors.HexColor("#2980b9"))
c.setLineWidth(1.5)
portal_x = W*0.08 + W*0.37/2
c.line(portal_x, stalk_y_bot, portal_x, H*0.15 + H*0.30)
# Arrow head
c.setFillColor(colors.HexColor("#2980b9"))
path = c.beginPath()
path.moveTo(portal_x - 3*mm, H*0.15 + H*0.30 + 0.5*mm)
path.lineTo(portal_x + 3*mm, H*0.15 + H*0.30 + 0.5*mm)
path.lineTo(portal_x, H*0.15 + H*0.30 - 3*mm)
path.close()
c.drawPath(path, fill=1, stroke=0)
c.setFillColor(colors.HexColor("#2980b9"))
c.setFont("Helvetica-Bold", 7)
c.drawString(W*0.03, (stalk_y_bot + H*0.15 + H*0.30)/2, "Portal")
c.drawString(W*0.03, (stalk_y_bot + H*0.15 + H*0.30)/2 - 7, "system")
# Tract arrows (right)
c.setStrokeColor(GREEN)
c.setLineWidth(1.5)
tract_x = W*0.55 + W*0.37/2
c.line(tract_x, stalk_y_bot, tract_x, H*0.15 + H*0.30)
c.setFillColor(GREEN)
path2 = c.beginPath()
path2.moveTo(tract_x - 3*mm, H*0.15 + H*0.30 + 0.5*mm)
path2.lineTo(tract_x + 3*mm, H*0.15 + H*0.30 + 0.5*mm)
path2.lineTo(tract_x, H*0.15 + H*0.30 - 3*mm)
path2.close()
c.drawPath(path2, fill=1, stroke=0)
c.setFillColor(GREEN)
c.setFont("Helvetica-Bold", 7)
c.drawString(W*0.93, (stalk_y_bot + H*0.15 + H*0.30)/2, "Tract")
c.drawString(W*0.88, (stalk_y_bot + H*0.15 + H*0.30)/2 - 7, "(axons)")
# Labels at bottom
c.setFillColor(colors.HexColor("#2980b9"))
c.setFont("Helvetica", 6.5)
c.drawCentredString(W*0.08 + W*0.37/2, H*0.06, "Releasing hormones via portal → ant. pituitary")
c.setFillColor(GREEN)
c.drawCentredString(W*0.55 + W*0.37/2, H*0.06, "ADH/OT transported via axons → released")
# ─── COVER PAGE ────────────────────────────────────────────────────
def make_cover():
elements = []
# Big colour banner
data = [[Paragraph("GLANDS OF HEAD & NECK", title_style)]]
t = Table(data, colWidths=[PAGE_W - 2*MARGIN])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 18),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [6]),
]))
elements.append(t)
elements.append(spacer(3))
data2 = [[Paragraph("Complete Viva Answers with Visualisations", subtitle_style)]]
t2 = Table(data2, colWidths=[PAGE_W - 2*MARGIN])
t2.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#2471a3")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("ROUNDEDCORNERS", [4]),
]))
elements.append(t2)
elements.append(spacer(5))
# Index table
index_data = [
[Paragraph("<b>Q#</b>", cell_bold), Paragraph("<b>Topic</b>", cell_bold), Paragraph("<b>Key Concept</b>", cell_bold)],
["Q1-3", "Gland Names & Salivary Glands", "Major + Minor salivary glands"],
["Q4", "Endocrine Glands in Neck", "Thyroid, Parathyroid, Pituitary, Pineal"],
["Q5", "Parotid Contents", "Facial N, Ext Carotid A, Retromandibular V"],
["Q6", "Parotid Duct", "Opens near upper 2nd molar"],
["Q7", "Parotid Capsule", "True (own) + False (investing fascia)"],
["Q8", "Parotid Swelling Pain & Orchitis", "Tight capsule; hematogenous mumps virus"],
["Q9", "Salivary Gland Histology", "Serous vs mucous; duct systems"],
["Q10-11", "Thyroid Location & Blood Supply", "Parts, arteries, veins, lymphatics"],
["Q12", "Thyroid Arteries (surgical imp.)", "Ext laryngeal N; RLN; parathyroid supply"],
["Q13", "Thyroid Moves with Deglutition", "Pretracheal fascia → bound to larynx/trachea"],
["Q14-16", "Thyroid Development & Anomalies", "Thyroglossal duct, ectopic thyroid, cysts"],
["Q17-18", "Para/Pituitary Location", "Parathyroid on thyroid; Pituitary in sella"],
["Q19-21", "Pituitary Tracts & BBB", "Hypothalamo-hypophyseal tract/portal; CVO"],
]
iw = [15*mm, 60*mm, 80*mm]
it = Table(index_data, colWidths=iw)
it.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [LIGHT_BLUE, WHITE]),
("GRID", (0,0), (-1,-1), 0.4, MID_GREY),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("LEFTPADDING", (0,0), (-1,-1), 6),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("FONTNAME", (0,0), (-1,-1), "Helvetica"),
("FONTSIZE", (0,0), (-1,-1), 9),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 9),
("TEXTCOLOR", (0,1), (-1,-1), NAVY),
]))
elements.append(it)
elements.append(spacer(4))
elements.append(info_box(
"📚 References: Gray's Anatomy for Students | BD Chaurasia | Dutta | Langman's Embryology | Snell's Neuroanatomy | Vishram Singh | Junqueira's Histology",
bg=LIGHT_GOLD, border=GOLD
))
elements.append(PageBreak())
return elements
# ─── BUILD PDF ────────────────────────────────────────────────────
def build_pdf(path):
doc = SimpleDocTemplate(
path, pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=16*mm, bottomMargin=16*mm,
title="Glands of Head and Neck – Viva Answers",
author="Orris Medical"
)
def on_page(canvas, doc):
canvas.saveState()
# Header bar
canvas.setFillColor(NAVY)
canvas.rect(0, PAGE_H - 10*mm, PAGE_W, 10*mm, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica-Bold", 8)
canvas.drawString(MARGIN, PAGE_H - 7*mm, "Glands of Head & Neck – Viva Answers")
canvas.setFont("Helvetica", 8)
canvas.drawRightString(PAGE_W - MARGIN, PAGE_H - 7*mm, f"Page {doc.page}")
# Footer bar
canvas.setFillColor(TEAL)
canvas.rect(0, 0, PAGE_W, 7*mm, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica", 7)
canvas.drawCentredString(PAGE_W/2, 2.5*mm, "Orris Medical | ITEM Book 2nd Edition Viva Series")
canvas.restoreState()
story = []
story += make_cover()
# ── Q1: Gland Names ──────────────────────────────────────────
story.append(section_header(1, "Tell me the names of the glands of head and neck region"))
story.append(spacer(2))
gland_data = [
[Paragraph("<b>Gland</b>", cell_bold), Paragraph("<b>Type</b>", cell_bold), Paragraph("<b>Location</b>", cell_bold)],
["Pituitary", "Endocrine", "Sella turcica, sphenoid bone"],
["Thyroid", "Endocrine", "Anterior neck below thyroid cartilage"],
["Parathyroid (×4)", "Endocrine", "Posterior surface of thyroid lobes"],
["Pineal", "Endocrine", "Epithalamus, between superior colliculi"],
["Parotid", "Exocrine (salivary)", "Preauricular, below EAM"],
["Submandibular", "Exocrine (salivary)", "Submandibular triangle, below mylohyoid"],
["Sublingual", "Exocrine (salivary)", "Floor of mouth, above mylohyoid"],
["Minor salivary glands", "Exocrine", "Mucosa of lips, cheeks, palate, tongue"],
]
story.append(make_table([], gland_data, col_widths=[45*mm, 45*mm, 65*mm]))
story.append(spacer(3))
# ── Q2 & Q3: Salivary Glands ─────────────────────────────────
story.append(section_header(2, "What are the major salivary glands? [Gray's 40th/520,522]"))
story.append(spacer(2))
story.append(key_point("Definition", "Three PAIRED glands that drain into the oral cavity via named ducts"))
story.append(spacer(2))
major_data = [
[Paragraph("<b>Gland</b>", cell_bold), Paragraph("<b>Size</b>", cell_bold),
Paragraph("<b>Type</b>", cell_bold), Paragraph("<b>Duct</b>", cell_bold), Paragraph("<b>Opens</b>", cell_bold)],
["Parotid", "Largest", "Purely SEROUS", "Stensen's duct (~5 cm)", "Opposite upper 2nd molar"],
["Submandibular", "Intermediate", "Mixed (pred. serous 70%)", "Wharton's duct", "Sublingual caruncle beside frenulum"],
["Sublingual", "Smallest", "Mixed (pred. mucous 70%)", "Ducts of Rivinus (×8-20)", "Sublingual fold"],
]
story.append(make_table([], major_data, col_widths=[28*mm, 20*mm, 34*mm, 34*mm, 39*mm]))
story.append(spacer(3))
story.append(section_header(3, "Tell me some names of minor salivary glands. [Gray's 40th/520,522]"))
story.append(spacer(2))
minor_items = [
"Labial glands (lips) – most numerous",
"Buccal glands (cheeks)",
"Palatine glands (hard & soft palate)",
"Anterior lingual glands of Blandin-Nuhn (tip of tongue)",
"Posterior lingual mucous glands",
"Serous glands of von Ebner (around circumvallate papillae – clean taste buds)",
"Molar glands (retromolar region)",
"Glossopalatine glands",
]
for item in minor_items:
story.append(bullet(item))
story.append(spacer(2))
story.append(warning_box("Von Ebner's glands are the only PURELY SEROUS minor glands – they secrete lingual lipase and clean circumvallate papillae for repeated taste testing."))
story.append(spacer(3))
# ── Q4 ───────────────────────────────────────────────────────
story.append(section_header(4, "What are the endocrine glands located in our neck?"))
story.append(spacer(2))
endo_items = [
"<b>Pituitary gland</b> – hypophysis; in sella turcica of sphenoid (technically base of brain/skull)",
"<b>Thyroid gland</b> – anterior neck, below thyroid cartilage",
"<b>Parathyroid glands (×4)</b> – posterior surface of thyroid lobes",
"<b>Endocrine part of hypothalamus</b> – releases TRH, GnRH, GHRH, CRH, dopamine",
"<b>Pineal gland</b> – melatonin secretion; between superior colliculi",
]
for item in endo_items:
story.append(bullet(item))
story.append(spacer(4))
# ── Q5 + Parotid Diagram ─────────────────────────────────────
story.append(section_header(5, "What are the structures present within the parotid gland? [BD 8th/117]"))
story.append(spacer(2))
story.append(info_box("<b>Mnemonic: \"Some Teenagers Are Really Playful\"</b><br/>"
"Skin → Facial N. (Trunk) → Arteries (Ext Carotid) → Retromandibular V → Parotid nodes"))
story.append(spacer(2))
parotid_data = [
[Paragraph("<b>Structure</b>", cell_bold), Paragraph("<b>Details</b>", cell_bold)],
["Facial Nerve [VII]", "Enters via stylomastoid foramen → divides into upper & lower trunks → 5 terminal branches (Temporal, Zygomatic, Buccal, Marginal mandibular, Cervical)"],
["External Carotid Artery", "Enters inferior border → gives posterior auricular A → divides into Maxillary A + Superficial temporal A"],
["Retromandibular Vein", "Formed by superficial temporal V + maxillary V within gland; divides into anterior (→ facial V) and posterior (→ EJV) divisions"],
["Parotid Lymph Nodes", "Preauricular (superficial) and deep nodes; drain scalp, face, auricle, parotid; efferents → upper deep cervical nodes"],
["Auriculotemporal Nerve", "Carries parasympathetic secretomotor fibres from otic ganglion (via IX → tympanic plexus → lesser petrosal → otic ganglion)"],
]
story.append(make_table([], parotid_data, col_widths=[42*mm, 113*mm]))
story.append(spacer(3))
story.append(ParotidDiagram())
story.append(spacer(3))
# ── Q6 ───────────────────────────────────────────────────────
story.append(section_header(6, "Where does the parotid duct open? [Dutta 6th/119]"))
story.append(spacer(2))
story.append(key_point("Opening", "Into the oral cavity opposite/adjacent to the <b>crown of the upper 2nd molar tooth</b> on the buccal mucosa"))
story.append(spacer(1))
story.append(key_point("Course", "Leaves anterior edge of gland → crosses masseter → turns medially at anterior border → passes through buccal fat pad → pierces buccinator → opens into vestibule"))
story.append(spacer(1))
story.append(key_point("Length", "~5 cm; also called Stensen's duct"))
story.append(warning_box("Stensen's duct is palpable across the masseter muscle. Parotid calculi (sialoliths) are LESS common than submandibular calculi because parotid saliva is more serous and less calcium-rich."))
story.append(spacer(3))
# ── Q7 ───────────────────────────────────────────────────────
story.append(section_header(7, "What are the capsules of the parotid gland? [Dutta 6th/116]"))
story.append(spacer(2))
cap_data = [
[Paragraph("<b>Capsule</b>", cell_bold), Paragraph("<b>Origin</b>", cell_bold), Paragraph("<b>Features</b>", cell_bold)],
["True capsule (inner)", "Gland's own CT stroma", "Thin, incomplete; invests gland lobules"],
["False capsule (outer)", "Investing layer of deep cervical fascia (splits to enclose gland)", "Dense, unyielding – especially superior & posterior; DEFICIENT inferomedially (parotid notch) → deep part communicates with parapharyngeal space"],
]
story.append(make_table([], cap_data, col_widths=[38*mm, 40*mm, 77*mm]))
story.append(spacer(2))
story.append(warning_box("The tough, inextensible false capsule is why parotitis is so painful – it cannot expand with the swollen gland."))
story.append(spacer(3))
# ── Q8 ───────────────────────────────────────────────────────
story.append(section_header(8, "Why is parotid swelling painful? How can parotitis lead to orchitis? [Vishram 2nd/112]"))
story.append(spacer(2))
story.append(Paragraph("<b>Why Painful:</b>", h1_style))
for item in [
"The parotid gland is enclosed in a <b>tough, inextensible fibrous capsule</b> (investing layer of deep cervical fascia)",
"When the gland swells (infection/inflammation), pressure builds within this rigid compartment",
"Increased pressure stimulates <b>pain receptors</b> and compresses parotid contents (nerves)",
"Chewing (masseter contraction) worsens pain by <b>compressing</b> the gland against the capsule",
"Auriculotemporal nerve transmits pain → temporal region (referred otalgia possible)",
]:
story.append(bullet(item))
story.append(spacer(2))
story.append(Paragraph("<b>Parotitis → Orchitis Mechanism (Mumps):</b>", h1_style))
mech_data = [
["Step 1", "Mumps paramyxovirus infects parotid gland epithelium via respiratory droplets → parotitis"],
["Step 2", "Virus replicates → enters bloodstream → PRIMARY VIREMIA"],
["Step 3", "Secondary viremia → hematogenous spread to distant organs"],
["Step 4", "Virus reaches testicular tissue → orchitis (20-30% of post-pubertal males)"],
["Step 5", "Inflammation + pressure in tunica albuginea → seminiferous tubule damage"],
["Outcome", "Testicular atrophy + potentially infertility if bilateral orchitis (rare: ~1-2%)"],
]
story.append(make_table(["Step", "Event"], mech_data, col_widths=[18*mm, 137*mm]))
story.append(spacer(2))
story.append(info_box("⚡ Key: It is HEMATOGENOUS spread, NOT anatomical/lymphatic – the parotid and testis are not directly connected.", bg=LIGHT_GOLD, border=GOLD))
story.append(spacer(3))
# ── Q9 + Histo Diagram ───────────────────────────────────────
story.append(section_header(9, "Histological differences among parotid, submandibular and sublingual glands"))
story.append(spacer(2))
histo_data = [
[Paragraph("<b>Feature</b>", cell_bold), Paragraph("<b>Parotid</b>", cell_bold),
Paragraph("<b>Submandibular</b>", cell_bold), Paragraph("<b>Sublingual</b>", cell_bold)],
["Acini type", "Purely serous", "Mixed (pred. serous ~70%)", "Mixed (pred. mucous ~70%)"],
["Serous demilunes", "N/A", "Present (on mucous acini)", "Present but sparse"],
["Intercalated ducts", "Long, well-developed", "Shorter", "Virtually ABSENT"],
["Striated ducts", "Prominent", "Well developed", "Short/few"],
["Excretory duct", "Stensen's (~5 cm)", "Wharton's (5 cm)", "Ducts of Rivinus (×8-20)"],
["Fat cells", "Many (↑ with age)", "Fewer", "Fewer"],
["Capsule", "Well defined", "Well defined", "Poorly defined"],
["Unique feature", "Purely serous; fat lobules", "Serous demilunes on mucous tubules", "No single main duct; opens along sublingual fold"],
]
story.append(make_table([], histo_data, col_widths=[36*mm, 38*mm, 38*mm, 43*mm]))
story.append(spacer(3))
story.append(SalivaryHistoDiagram())
story.append(spacer(3))
story.append(PageBreak())
# ── Q10 ──────────────────────────────────────────────────────
story.append(section_header(10, "Tell me the location and parts of the thyroid gland. [Dutta 6th/134]"))
story.append(spacer(2))
story.append(Paragraph("<b>Location:</b>", h1_style))
for item in [
"Anterior neck, <b>below and lateral to the thyroid cartilage</b>",
"Lies in the <b>visceral compartment</b> of the neck (with pharynx, trachea, oesophagus)",
"Enclosed within the <b>pretracheal fascia</b>",
"Deep to sternohyoid, sternothyroid and omohyoid muscles",
"Covers anterolateral surfaces of trachea, cricoid cartilage, lower thyroid cartilage",
]:
story.append(bullet(item))
story.append(spacer(2))
story.append(Paragraph("<b>Parts:</b>", h1_style))
parts_data = [
["Right lobe", "Larger of the two lateral lobes"],
["Left lobe", "Slightly smaller"],
["Isthmus", "Connects two lobes; crosses anterior surface of 2nd and 3rd tracheal rings"],
["Pyramidal lobe", "Present in ~50%; finger-like projection from isthmus (usually left); remnant of thyroglossal duct; attached to hyoid by levator glandulae thyroideae"],
]
story.append(make_table(["Part", "Description"], parts_data, col_widths=[35*mm, 120*mm]))
story.append(spacer(3))
# ── Q11 + Thyroid Diagram ─────────────────────────────────────
story.append(section_header(11, "Tell me the blood supply of the thyroid gland. [Dutta 6th/136]"))
story.append(spacer(2))
bs_data = [
[Paragraph("<b>Vessel</b>", cell_bold), Paragraph("<b>Origin/Drain to</b>", cell_bold), Paragraph("<b>Supplies/Notes</b>", cell_bold)],
["Superior thyroid artery", "1st branch external carotid A", "Superior pole; ant & post glandular branches"],
["Inferior thyroid artery", "Thyrocervical trunk (1st part subclavian A)", "Inferior pole + parathyroid glands (ascending branch)"],
["Thyroid ima artery (occasional ~3-10%)", "Brachiocephalic trunk or aortic arch", "Ascends on anterior trachea → isthmus; surgical importance"],
["Superior thyroid vein", "→ Internal jugular vein", "Drains area of STA territory"],
["Middle thyroid vein", "→ Internal jugular vein", "Short, crosses to IJV directly; no corresponding artery"],
["Inferior thyroid vein", "→ Brachiocephalic veins (R&L)", "Crosses trachea – at risk in tracheostomy"],
["Lymphatics", "→ Paratracheal nodes → deep cervical (inf.) nodes", "Along internal jugular vein below omohyoid"],
]
story.append(make_table([], bs_data, col_widths=[42*mm, 50*mm, 63*mm]))
story.append(spacer(3))
story.append(ThyroidDiagram())
story.append(spacer(3))
# ── Q12 ──────────────────────────────────────────────────────
story.append(section_header(12, "Why are superior and inferior thyroid arteries important to neck surgeons? [Vishram 2nd]"))
story.append(spacer(2))
story.append(Paragraph("<b>Superior Thyroid Artery:</b>", h1_style))
for item in [
"Runs closely alongside the <b>External Laryngeal Nerve</b> (branch of superior laryngeal N from vagus)",
"The external laryngeal nerve innervates the <b>cricothyroid muscle</b> – the 'tensor' of vocal cord",
"Injury during high ligation → loss of high-pitched phonation, fatigue during prolonged speaking",
"Called <b>'nerve of the opera singer'</b> (Amelita Galli-Curci case)",
"Artery must be ligated <b>close to the gland</b> (not near its origin from ECA) to protect the nerve",
]:
story.append(bullet(item))
story.append(spacer(2))
story.append(Paragraph("<b>Inferior Thyroid Artery:</b>", h1_style))
for item in [
"Intimately related to the <b>Recurrent Laryngeal Nerve (RLN)</b>",
"RLN may pass <b>anterior, posterior, or between branches</b> of the inferior thyroid artery",
"Injury to RLN → <b>unilateral hoarseness</b>; bilateral → <b>respiratory distress/stridor</b> (adductor paralysis)",
"Provides sole blood supply to <b>parathyroid glands</b> via ascending branch – accidental ligation → hypoparathyroidism → hypocalcaemia → tetany",
"Must identify and preserve both RLN and parathyroid supply during thyroidectomy",
]:
story.append(bullet(item))
story.append(spacer(2))
story.append(warning_box("Inferior thyroid vein crosses the trachea – at risk during emergency tracheostomy if incision is too high/midline."))
story.append(spacer(3))
# ── Q13 ──────────────────────────────────────────────────────
story.append(section_header(13, "Explain – Why does the thyroid gland move with deglutition? [Vishram 2nd/157]"))
story.append(spacer(2))
story.append(info_box(
"<b>Mechanism:</b> The thyroid gland is enclosed within the <b>pretracheal fascia</b>, "
"which is attached superiorly to the <b>thyroid and cricoid cartilages of the larynx</b>. "
"During swallowing, the larynx and trachea are pulled <b>superiorly</b> by the suprahyoid and "
"thyrohyoid muscles. Since the thyroid is bound to the larynx/trachea via this fascial sheath, "
"it <b>moves upward with them</b>."
))
story.append(spacer(2))
move_data = [
["Any thyroid swelling (goitre)", "Moves UP on swallowing", "YES"],
["Thyroglossal cyst", "Moves UP on swallowing + on tongue protrusion", "YES (pathognomonic)"],
["Cervical lymphadenopathy", "Does NOT move on swallowing", "NO"],
["Branchial cyst", "Does NOT move on swallowing", "NO"],
["Sebaceous cyst", "Does NOT move on swallowing", "NO"],
]
story.append(make_table(["Structure", "Movement", "Moves on swallowing?"], move_data,
col_widths=[52*mm, 72*mm, 31*mm]))
story.append(spacer(3))
# ── Q14 ──────────────────────────────────────────────────────
story.append(section_header(14, "Tell me the development of the thyroid gland. [Langman's 12th/292]"))
story.append(spacer(2))
dev_steps = [
("<b>4th week (24th day)</b>", "Median endodermal thickening on floor of pharynx, between 1st & 2nd pharyngeal pouches → <b>thyroid primordium</b>"),
("<b>Foramen cecum</b>", "Site of origin – persists in adults as a small pit on the dorsal surface of tongue, junction of anterior 2/3 and posterior 1/3"),
("<b>Descent</b>", "Grows downward as bilobed diverticulum (thyroglossal duct), passing <b>anterior to hyoid bone</b> and thyroid cartilage"),
("<b>7th week</b>", "Reaches final position anterior to trachea in root of neck; connected to foramen cecum by thyroglossal duct"),
("<b>8th-10th week</b>", "Thyroglossal duct normally <b>involutes and disappears</b>"),
("<b>Parafollicular C cells</b>", "Derived from <b>4th pharyngeal pouch / ultimobranchial body</b> (neural crest origin); migrate into thyroid; secrete <b>calcitonin</b>"),
("<b>Functional onset</b>", "Thyroid begins secreting colloid ~12th week; iodine uptake starts ~11th week"),
]
for step, text in dev_steps:
story.append(key_point(step, text))
story.append(spacer(3))
# ── Q15 ──────────────────────────────────────────────────────
story.append(section_header(15, "What is ectopic thyroid? [Dutta 6th/136]"))
story.append(spacer(2))
story.append(key_point("Definition", "Thyroid tissue found at an abnormal location due to failed/aberrant migration during embryological development"))
story.append(spacer(2))
ect_data = [
["Lingual thyroid", "Base of tongue (foramen cecum)", "Most common (90%); may cause dysphagia, dysphonia, dyspnoea"],
["Sublingual thyroid", "Above hyoid bone", "Uncommon"],
["Intratracheal thyroid", "Tracheal wall", "Rare; causes haemoptysis"],
["Mediastinal/substernal", "Superior mediastinum", "Extension of goitre or true ectopic"],
["Lateral aberrant thyroid", "Lateral neck nodes", "Usually = lymph node metastasis of well-diff. thyroid Ca"],
["Along thyroglossal tract", "Anywhere between base of tongue and neck", "Associated with thyroglossal duct remnants"],
]
story.append(make_table(["Type", "Location", "Notes"], ect_data, col_widths=[38*mm, 42*mm, 75*mm]))
story.append(spacer(2))
story.append(warning_box("ALWAYS perform radioiodine (Tc-99m) scan BEFORE removing a lingual/ectopic thyroid mass – it may be the ONLY functioning thyroid tissue in the patient."))
story.append(spacer(3))
# ── Q16 + Thyroglossal Diagram ───────────────────────────────
story.append(section_header(16, "What is a thyroglossal cyst? [Langman's 12th/292]"))
story.append(spacer(2))
story.append(key_point("Definition", "A cystic remnant of the thyroglossal duct that forms when the duct fails to involute after thyroid descent"))
story.append(spacer(2))
story.append(Paragraph("<b>Key Features:</b>", h1_style))
tg_features = [
"Most common <b>congenital neck mass</b> in children",
"Midline or just left of midline (pyramidal lobe tends left)",
"Most common site: <b>below hyoid bone (infrahyoid) – 65%</b>",
"Surface is smooth, soft, fluctuant",
"<b>Moves UPWARD on both swallowing AND tongue protrusion</b> – pathognomonic (attached to foramen cecum via duct remnant)",
"May get infected → discharge via thyroglossal fistula",
"Rarely: carcinoma (papillary type) may arise within the cyst (~1%)",
]
for f in tg_features:
story.append(bullet(f))
story.append(spacer(2))
story.append(info_box("<b>Sistrunk's Operation (treatment):</b> Excision of cyst + central part of hyoid bone + complete tract up to foramen cecum. Removal of hyoid prevents recurrence (duct passes through/around hyoid)."))
story.append(spacer(3))
story.append(ThyroglosalDiagram())
story.append(spacer(3))
story.append(PageBreak())
# ── Q17 ──────────────────────────────────────────────────────
story.append(section_header(17, "Tell me the location of the parathyroid gland. [Dutta 6th/139]"))
story.append(spacer(2))
story.append(key_point("Number", "4 glands – 2 superior + 2 inferior (may rarely have 3-6)"))
story.append(key_point("General", "Located on the posterior surface (deep surface) of the lateral lobes of the thyroid gland, within the thyroid capsule but outside the parenchyma"))
story.append(spacer(2))
pt_data = [
[Paragraph("<b>Gland</b>", cell_bold), Paragraph("<b>Embryological origin</b>", cell_bold),
Paragraph("<b>Position</b>", cell_bold), Paragraph("<b>Constancy</b>", cell_bold)],
["Superior parathyroid (×2)", "4th pharyngeal pouch", "Junction of upper 1/3 & lower 2/3 of posterior thyroid lobe, near entry of inferior thyroid artery", "More constant"],
["Inferior parathyroid (×2)", "3rd pharyngeal pouch (with thymus)", "Near inferior pole of thyroid, thyrothymic ligament, or upper mediastinum", "MORE variable; anywhere carotid bifurcation to mediastinum"],
]
story.append(make_table([], pt_data, col_widths=[38*mm, 36*mm, 60*mm, 21*mm]))
story.append(spacer(2))
story.append(key_point("Blood supply", "Inferior thyroid artery (ascending branch) supplies both superior and inferior parathyroids predominantly"))
story.append(warning_box("The 3rd pouch descends further than 4th pouch (paradox): inferior parathyroid (from 3rd pouch) ends up below the superior parathyroid (from 4th pouch)."))
story.append(spacer(3))
# ── Q18 ──────────────────────────────────────────────────────
story.append(section_header(18, "Tell me the location of the pituitary gland. [Dutta 6th/177]"))
story.append(spacer(2))
pit_data = [
["Bone", "Sella turcica (hypophyseal fossa) of the sphenoid bone"],
["Cranial fossa", "Middle cranial fossa, at base of brain"],
["Superior", "Optic chiasma (above) – tumour → bitemporal hemianopia by upward pressure"],
["Lateral (both sides)", "Cavernous sinuses – contain CN III, IV, V1, V2, VI and internal carotid artery"],
["Superior covering", "Diaphragma sellae (dural fold) – pituitary stalk passes through its aperture"],
["Connected to", "Hypothalamus via pituitary stalk (infundibulum)"],
["Size/weight", "~8 × 12 × 6 mm; weight ~500–600 mg (↑ in pregnancy up to 1g)"],
]
story.append(make_table(["Relation", "Structure"], pit_data, col_widths=[42*mm, 113*mm]))
story.append(spacer(3))
# ── Q19 ──────────────────────────────────────────────────────
story.append(section_header(19, "What is the hypothalamo-hypophyseal tract? [Snell's Neuro 7th/388]"))
story.append(spacer(2))
story.append(key_point("Definition",
"A bundle of UNMYELINATED nerve axons running from the hypothalamus → posterior pituitary (neurohypophysis)"))
story.append(spacer(2))
tract_data = [
["Cell bodies", "Magnocellular neurons in <b>supraoptic nucleus</b> (mainly ADH/vasopressin) and <b>paraventricular nucleus</b> (mainly oxytocin) of hypothalamus"],
["Axons", "Travel through infundibular stalk as the hypothalamo-hypophyseal tract"],
["Terminals", "Axon terminals in the pars nervosa (posterior pituitary) – bulbous endings called <b>Herring bodies</b>"],
["Hormones", "<b>ADH (vasopressin)</b> – water reabsorption in collecting ducts, vasoconstriction; <b>Oxytocin</b> – uterine contractions, milk ejection (Ferguson reflex)"],
["Type of secretion", "NEUROSECRETION – NOT portal system; hormones travel down axons as neurosecretory granules"],
["Release", "Into fenestrated capillaries of posterior pituitary → systemic circulation"],
]
story.append(make_table(["Component", "Details"], tract_data, col_widths=[30*mm, 125*mm]))
story.append(spacer(3))
# ── Q20 ──────────────────────────────────────────────────────
story.append(section_header(20, "What is the hypothalamo-hypophyseal portal system? [Snell's Neuro 7th/389]"))
story.append(spacer(2))
story.append(key_point("Definition",
"A portal circulation (capillary-to-capillary system) connecting hypothalamus to the ANTERIOR pituitary (adenohypophysis)"))
story.append(spacer(2))
portal_steps = [
("Primary capillary plexus", "Hypothalamic neurons (arcuate, periventricular nuclei) release releasing/inhibiting hormones into capillaries in the <b>median eminence</b>"),
("Portal vessels", "Hypophyseal portal veins run down the pituitary stalk"),
("Secondary capillary plexus", "Portal veins break into a secondary plexus in the anterior pituitary – fenestrated capillaries"),
("Action", "Releasing hormones act on specific anterior pituitary cells to stimulate (or inhibit) release of their hormones"),
("Hormones released", "TRH → TSH; GnRH → LH, FSH; GHRH/Somatostatin → GH; CRH → ACTH; Dopamine → ↓Prolactin"),
("Clinical significance", "Stalk section → loss of anterior pituitary function (all except Prolactin which ↑ due to loss of dopamine inhibition)"),
]
story.append(make_table(["Component", "Details"], portal_steps, col_widths=[38*mm, 117*mm]))
story.append(spacer(3))
# ── Q21 + Pituitary Diagram ───────────────────────────────────
story.append(section_header(21, "Why is BBB absent in the posterior pituitary gland?"))
story.append(spacer(2))
story.append(info_box(
"<b>Blood Brain Barrier (BBB):</b> Formed by tight junctions between cerebral capillary endothelial cells + pericytes + astrocyte end-feet. "
"It prevents free passage of large molecules between blood and brain tissue."
))
story.append(spacer(2))
story.append(Paragraph("<b>Reasons BBB is absent in posterior pituitary:</b>", h1_style))
bbb_reasons = [
"<b>Neurohaemal organ function</b> – The posterior pituitary is a site of neurohormone (ADH, oxytocin) release directly into bloodstream; a BBB would block this",
"<b>Fenestrated capillaries</b> – Unlike CNS capillaries, posterior pituitary capillaries have PORES (fenestrations) allowing free passage of large peptide hormones",
"<b>Circumventricular organ (CVO)</b> – Posterior pituitary is one of 7 CVOs that lack BBB to allow blood-brain communication",
"<b>No astrocyte end-feet</b> covering these capillaries (different from rest of CNS)",
]
for r in bbb_reasons:
story.append(bullet(r))
story.append(spacer(2))
cvo_data = [
["Area postrema", "Vomiting centre; detects blood-borne toxins"],
["Subfornical organ", "Detects angiotensin II → regulates thirst & ADH release"],
["OVLT (organum vasculosum lamina terminalis)", "Detects osmolarity changes, cytokines (fever)"],
["Median eminence", "Releases hypothalamic hormones into portal blood"],
["Posterior pituitary (neurohypophysis)", "Releases ADH and oxytocin"],
["Subcommissural organ", "Secretes glycoproteins into CSF"],
["Pineal gland", "Releases melatonin into bloodstream"],
]
story.append(Paragraph("<b>The 7 Circumventricular Organs (CVOs) – all lack BBB:</b>", h1_style))
story.append(make_table(["CVO", "Function"], cvo_data, col_widths=[75*mm, 80*mm]))
story.append(spacer(2))
story.append(warning_box(
"Posterior pituitary = Pars nervosa + Infundibular stalk + Median eminence. "
"It secretes ADH (water reabsorption, vasoconstriction) and Oxytocin (uterine contraction, milk ejection). "
"SIADH (↑ADH) = hyponatremia; Diabetes Insipidus (↓ADH) = polyuria + polydipsia."
))
story.append(spacer(3))
story.append(PituitaryDiagram())
story.append(spacer(3))
story.append(PageBreak())
# ── QUICK REVISION SUMMARY ────────────────────────────────────
summary_title = Paragraph("QUICK REVISION SUMMARY TABLE", S("Normal",
fontSize=14, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=18))
title_table = Table([[summary_title]], colWidths=[PAGE_W - 2*MARGIN])
title_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [5]),
]))
story.append(title_table)
story.append(spacer(3))
summary_data = [
[Paragraph("<b>Q</b>", cell_bold), Paragraph("<b>Topic</b>", cell_bold), Paragraph("<b>One-liner Key Answer</b>", cell_bold)],
["1", "Gland names", "Pituitary, Thyroid, Parathyroid, Pineal + Parotid, Submandibular, Sublingual + Minor glands"],
["2", "Major salivary glands", "Parotid (serous/Stensen's), Submandibular (mixed/Wharton's), Sublingual (mucous/Rivinus)"],
["3", "Minor salivary glands", "Labial, Buccal, Palatine, Lingual (Blandin-Nuhn, von Ebner), Molar, Glossopalatine"],
["4", "Endocrine neck glands", "Pituitary, Thyroid, Parathyroid, Hypothalamus, Pineal"],
["5", "Parotid contents", "Facial N VII + Ext Carotid A + Retromandibular V + Parotid LN + Auriculotemporal N"],
["6", "Parotid duct opening", "Opposite crown of upper 2nd molar tooth (Stensen's duct ~5cm, pierces buccinator)"],
["7", "Parotid capsules", "True (own CT) + False (investing deep cervical fascia – tough, inextensible)"],
["8", "Why painful/orchitis", "Tight inextensible capsule → pressure pain; Orchitis via hematogenous spread of mumps virus"],
["9", "Histo differences", "Parotid=serous; Submandibular=mixed serous(+demilunes); Sublingual=mixed mucous; ↓ducts sublingual"],
["10", "Thyroid parts/location", "Visceral compartment neck; Right lobe + Left lobe + Isthmus (2nd-3rd tracheal rings) + Pyramidal lobe"],
["11", "Thyroid blood supply", "Sup. thyroid A (ECA) + Inf. thyroid A (thyrocervical trunk); 3 venous pairs; paratracheal LN"],
["12", "Surgical importance", "STA → Ext laryngeal N (cricothyroid); ITA → RLN (hoarseness) + parathyroid supply"],
["13", "Moves on swallowing", "Pretracheal fascia binds thyroid to larynx/trachea → moves superiorly with deglutition"],
["14", "Thyroid development", "Median endodermal outgrowth, foramen cecum (4th wk) → descends → 7th wk final position; C cells from 4th pouch"],
["15", "Ectopic thyroid", "Failed descent; lingual (most common); SCAN before removal – may be only thyroid tissue"],
["16", "Thyroglossal cyst", "Thyroglossal duct remnant; midline; infrahyoid (65%); moves on swallowing + tongue protrusion; Sistrunk op."],
["17", "Parathyroid location", "Posterior thyroid lobe; Superior (from 4th pouch) + Inferior (from 3rd pouch); ITA supply"],
["18", "Pituitary location", "Sella turcica of sphenoid; middle cranial fossa; Lat = cavernous sinus; Sup = optic chiasma"],
["19", "Hypothalamo-hypophyseal tract", "Axons SON/PVN → posterior pituitary; ADH + oxytocin; Herring bodies; neurosecretion"],
["20", "Hypothalamo-hypophyseal portal", "Portal vessels median eminence → ant. pituitary; releasing hormones; stalk section → ↑prolactin only"],
["21", "BBB absent post. pituitary", "Neurohaemal organ; fenestrated capillaries; CVO (one of 7); needed for ADH/OT release"],
]
story.append(make_table([], summary_data, col_widths=[8*mm, 45*mm, 102*mm]))
story.append(spacer(4))
# Mnemonic box
story.append(info_box(
"<b>🧠 Master Mnemonics</b><br/>"
"Parotid contents: <b>S-T-A-R-P</b> = Skin/Superficial fascia → Trunk of Facial N → Artery (Ext Carotid) → Retromandibular V → Parotid LN<br/>"
"5 branches Facial N: <b>Two Zebras Bit My Cat</b> = Temporal, Zygomatic, Buccal, Marginal mandibular, Cervical<br/>"
"Thyroid blood supply arteries: <b>SIT</b> = Superior thyroid + Inferior thyroid + (Thyroid ima)<br/>"
"CVOs: <b>OVLT-MSPA-P</b> = OVLT, ME, SFO, Pineal, AP, SCO, Posterior pituitary<br/>"
"Pharyngeal pouches: 1st→Middle ear; 2nd→Palatine tonsil; 3rd→Inferior PTH+Thymus; 4th→Superior PTH+C cells",
bg=LIGHT_PURPLE, border=PURPLE
))
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print("PDF built successfully!")
build_pdf("/tmp/workspace/glands-viva/Glands_Head_Neck_Viva.pdf")
cd /tmp/workspace/glands-viva && python make_pdf.py 2>&1
~/glands-viva/make_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/glands-viva/make_pdf.py'
cd /tmp/workspace/glands-viva && python make_pdf.py 2>&1
~/glands-viva/make_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/glands-viva/make_pdf.py'
~/glands-viva/make_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/glands-viva/make_pdf.py'
~/glands-viva/make_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/glands-viva/make_pdf.py'
cd /tmp/workspace/glands-viva && python make_pdf.py 2>&1
~/glands-viva/make_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/glands-viva/make_pdf.py'
~/glands-viva/make_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/glands-viva/make_pdf.py'
cd /tmp/workspace/glands-viva && python make_pdf.py 2>&1
~/glands-viva/make_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/glands-viva/make_pdf.py'
cd /tmp/workspace/glands-viva && python make_pdf.py 2>&1
ls -lh /tmp/workspace/glands-viva/Glands_Head_Neck_Viva.pdf
Glands Head Neck Viva
PDF Document · PDF
| Section | Content |
|---|---|
| Cover page | Title banner + full topic index table + reference list |
| Q1-4 | Gland names, major/minor salivary glands, endocrine glands – formatted tables |
| Q5 + Diagram | Parotid contents table + custom colour diagram showing structures S→D |
| Q6-8 | Duct opening, capsules, parotitis pain & orchitis mechanism table |
| Q9 + Diagram | Histology comparison table + 3-panel acinar diagram (Parotid / Submandibular / Sublingual) |
| Q10-13 + Diagram | Thyroid location, blood supply table, surgical importance, deglutition mechanism + labelled thyroid diagram |
| Q14-16 + Diagram | Development, ectopic thyroid, thyroglossal cyst + descent pathway diagram with Sistrunk note |
| Q17-18 | Parathyroid & pituitary location tables |
| Q19-21 + Diagram | Hypothalamo-hypophyseal tract, portal system, BBB/CVO table + pituitary diagram |
| Summary page | Two rapid-revision tables covering all 21 Qs + Master Mnemonics box |