Make an exam oriented notes on the given source and separate exam oriented notes on support of uterus from the given source
Note on Support section: The dedicated "Support of Uterus" chapter was not in the provided pages, so the ligament details from the source were supplemented with standard Gynecology textbook anatomy (Dutta's framework). All references directly from your source are clearly marked.
Generate a PDF with formatted exam notes for easy printing
ls -la /home/daytona/workspace/ && mkdir -p /home/daytona/workspace/gynae-notes
~/gynae-notes/generate_notes.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import ListFlowable, ListItem
# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE = colors.HexColor("#1a3c5e")
MED_BLUE = colors.HexColor("#2563a8")
ACCENT_RED = colors.HexColor("#c0392b")
ACCENT_TEAL = colors.HexColor("#0d7377")
YELLOW_HL = colors.HexColor("#fff9c4")
LIGHT_BLUE = colors.HexColor("#e8f0fb")
LIGHT_GRAY = colors.HexColor("#f4f4f4")
TABLE_HEAD = colors.HexColor("#1a3c5e")
TABLE_ALT = colors.HexColor("#dce8f5")
BOX_BORDER = colors.HexColor("#2563a8")
WHITE = colors.white
BLACK = colors.black
PAGE_W, PAGE_H = A4
MARGIN = 1.8 * cm
# ── Document ─────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
"/home/daytona/workspace/gynae-notes/Gynae_Exam_Notes.pdf",
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=2 * cm, bottomMargin=2 * cm,
title="Gynecology Exam Notes – Female Pelvic Organs",
author="Exam Notes"
)
styles = getSampleStyleSheet()
# ── Custom Styles ─────────────────────────────────────────────────────────────
def S(name, **kw):
return ParagraphStyle(name, **kw)
st_cover_title = S("CoverTitle", fontName="Helvetica-Bold", fontSize=26,
textColor=WHITE, alignment=TA_CENTER, leading=32)
st_cover_sub = S("CoverSub", fontName="Helvetica", fontSize=13,
textColor=colors.HexColor("#cce4ff"), alignment=TA_CENTER, leading=18)
st_cover_src = S("CoverSrc", fontName="Helvetica-Oblique", fontSize=10,
textColor=colors.HexColor("#99ccff"), alignment=TA_CENTER, leading=14)
st_part = S("Part", fontName="Helvetica-Bold", fontSize=16,
textColor=WHITE, alignment=TA_CENTER, leading=20,
backColor=DARK_BLUE, borderPadding=(6,10,6,10))
st_h1 = S("H1", fontName="Helvetica-Bold", fontSize=13,
textColor=WHITE, backColor=MED_BLUE,
leftIndent=0, leading=18, borderPadding=(4,8,4,8))
st_h2 = S("H2", fontName="Helvetica-Bold", fontSize=11,
textColor=DARK_BLUE, leading=15, spaceBefore=8)
st_h3 = S("H3", fontName="Helvetica-Bold", fontSize=10,
textColor=ACCENT_TEAL, leading=14, spaceBefore=5)
st_body = S("Body", fontName="Helvetica", fontSize=9.5,
leading=14, alignment=TA_JUSTIFY)
st_bullet = S("Bullet", fontName="Helvetica", fontSize=9.5,
leading=13, leftIndent=16, bulletIndent=6)
st_highlight = S("Highlight", fontName="Helvetica-Bold", fontSize=9.5,
textColor=ACCENT_RED, leading=13, backColor=YELLOW_HL,
borderPadding=(3,6,3,6))
st_note = S("Note", fontName="Helvetica-Oblique", fontSize=9,
textColor=colors.HexColor("#555555"), leading=13,
backColor=LIGHT_GRAY, borderPadding=(3,6,3,6))
st_qa_q = S("QAQ", fontName="Helvetica-Bold", fontSize=9.5,
textColor=DARK_BLUE, leading=13)
st_qa_a = S("QAA", fontName="Helvetica", fontSize=9.5,
textColor=colors.HexColor("#1a4a1a"), leading=13, leftIndent=12)
def h1(text): return Paragraph(text, st_h1)
def h2(text): return Paragraph(text, st_h2)
def h3(text): return Paragraph(text, st_h3)
def body(text): return Paragraph(text, st_body)
def hl(text): return Paragraph(f"⚡ {text}", st_highlight)
def note(text): return Paragraph(f"📝 {text}", st_note)
def sp(n=6): return Spacer(1, n)
def hr(): return HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#bbbbbb"), spaceAfter=4, spaceBefore=4)
def bullets(items, indent=16):
return ListFlowable(
[ListItem(Paragraph(i, st_bullet), leftIndent=indent, bulletColor=MED_BLUE) for i in items],
bulletType='bullet', bulletFontSize=8, leftIndent=indent
)
def make_table(headers, rows, col_widths=None):
data = [headers] + rows
if col_widths is None:
avail = PAGE_W - 2*MARGIN
col_widths = [avail / len(headers)] * len(headers)
t = Table(data, colWidths=col_widths, repeatRows=1)
style = TableStyle([
('BACKGROUND', (0,0), (-1,0), TABLE_HEAD),
('TEXTCOLOR', (0,0), (-1,0), WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,0), 9),
('ALIGN', (0,0), (-1,0), 'CENTER'),
('FONTNAME', (0,1), (-1,-1), 'Helvetica'),
('FONTSIZE', (0,1), (-1,-1), 8.5),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, TABLE_ALT]),
('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#aaaaaa")),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 6),
])
t.setStyle(style)
return t
def box(flowables, bg=LIGHT_BLUE, border=BOX_BORDER):
inner = Table([[f] for f in flowables],
colWidths=[PAGE_W - 2*MARGIN - 12])
inner.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), bg),
('BOX', (0,0), (-1,-1), 1, border),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 8),
]))
return inner
# ═══════════════════════════════════════════════════════════════════════════
# COVER PAGE
# ═══════════════════════════════════════════════════════════════════════════
story = []
# Cover background via a full-width table
cover_data = [[Paragraph("GYNECOLOGY", st_cover_title)],
[Paragraph("EXAM-ORIENTED NOTES", st_cover_title)],
[Spacer(1, 10)],
[Paragraph("Anatomy of Female Pelvic Organs", st_cover_sub)],
[Spacer(1, 6)],
[Paragraph("The Uterus · Fallopian Tube · Ovary · Female Urethra · Urinary Bladder", st_cover_src)],
[Spacer(1, 6)],
[Paragraph("+ Support of the Uterus — Separate Exam Notes", st_cover_src)],
[Spacer(1, 20)],
[Paragraph("Source: Textbook of Gynecology, Chapter 1", st_cover_src)],
]
cover_table = Table(cover_data, colWidths=[PAGE_W - 2*MARGIN])
cover_table.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), DARK_BLUE),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('LEFTPADDING', (0,0), (-1,-1), 20),
('RIGHTPADDING', (0,0), (-1,-1), 20),
]))
story.append(cover_table)
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# PART 1 HEADER
# ═══════════════════════════════════════════════════════════════════════════
story.append(Paragraph("PART 1 — ANATOMY OF FEMALE PELVIC ORGANS", st_part))
story.append(sp(10))
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 1: THE UTERUS
# ═══════════════════════════════════════════════════════════════════════════
story.append(h1("THE UTERUS"))
story.append(sp(4))
story.append(body("Hollow, <b>pyriform (pear-shaped) muscular organ</b> situated in the pelvis between the bladder (front) and rectum (behind)."))
story.append(sp(6))
# Position
story.append(h2("Position"))
story.append(bullets([
"<b>Normal position:</b> Anteverted + Anteflexed",
"Usually inclined to the <b>right (dextrorotation)</b>",
"Cervix directed to the <b>LEFT (levorotation)</b>",
"In close relation with the <b>left ureter</b>",
]))
story.append(sp(6))
# Measurements
story.append(h2("Measurements and Parts"))
story.append(make_table(
["Parameter", "Value"],
[["Length", "~8 cm"], ["Width (at fundus)", "~5 cm"], ["Wall thickness", "~1.25 cm"], ["Weight", "50–80 g"]],
col_widths=[8*cm, 8.6*cm]
))
story.append(sp(8))
story.append(h3("Three Parts:"))
story.append(bullets([
"<b>Body/Corpus</b> — triangular; lies between openings of uterine tubes; cornua at superolateral angles",
"<b>Isthmus</b> — constricted, <b>0.5 cm</b>; between anatomical internal os (above) and histological internal os of Aschoff (below)",
"<b>Cervix</b> — <b>2.5 cm</b>; extends from histological internal os to external os; divided into supravaginal (1.25 cm) + portio vaginalis (1.25 cm)",
]))
story.append(sp(4))
story.append(hl("Nulliparous cervix = conical; Parous cervix = cylindrical with bilateral slits (anterior + posterior lips)"))
story.append(sp(8))
# Cavity
story.append(h2("Cavity"))
story.append(make_table(
["Cavity", "Shape", "Size"],
[["Uterine body", "Triangular (coronal section)", "~3.5 cm"],
["Cervical canal", "Fusiform", "~2.5 cm"],
["Total uterine cavity length", "—", "6–7 cm"]],
col_widths=[5.5*cm, 6*cm, 5.1*cm]
))
story.append(sp(8))
# Relations
story.append(h2("Relations of the Uterus"))
story.append(make_table(
["Direction", "Relation"],
[["Anteriorly (above internal os)", "Posterior wall of uterovesical pouch"],
["Anteriorly (below internal os)", "Separated from bladder by loose areolar tissue"],
["Posteriorly", "Peritoneum → Pouch of Douglas (coils of intestine)"],
["Laterally", "Broad ligament; uterine artery; Mackenrodt's ligament (from internal os to supravaginal cervix)"]],
col_widths=[6*cm, 10.6*cm]
))
story.append(sp(6))
story.append(hl("Uterine artery crosses the ureter ANTERIORLY ~1.5 cm lateral to the level of internal os — 'Water under the bridge'"))
story.append(sp(8))
# Wall layers
story.append(h2("Wall of the Body — 3 Layers (Outside → Inside)"))
story.append(sp(4))
story.append(h3("1. Perimetrium (Serous)"))
story.append(body("Serous coat; invests entire organ except on lateral borders; intimately adherent to underlying muscles."))
story.append(sp(4))
story.append(h3("2. Myometrium (Muscular)"))
story.append(body("Thick bundles of smooth muscle held by connective tissue. During pregnancy, 3 distinct layers:"))
story.append(bullets([
"<b>Outer longitudinal</b>",
"<b>Middle interlacing (oblique)</b> — most important; obliterates blood vessels post-delivery (living ligatures)",
"<b>Inner circular</b>",
]))
story.append(sp(4))
story.append(h3("3. Endometrium (Mucous Membrane)"))
story.append(bullets([
"No submucous layer — directly apposed to muscle coat",
"Surface epithelium: single layer of <b>ciliated columnar epithelium</b>",
"Lamina propria: stromal cells, endometrial glands, vessels, nerves",
"Glands: simple tubular, lined by mucus-secreting non-ciliated columnar epithelium",
"All components change during menstrual cycle",
"Changed to <b>decidua</b> during pregnancy",
]))
story.append(sp(8))
# Cervix structure
story.append(h2("Cervix — Structure"))
story.append(bullets([
"Mainly <b>fibrous connective tissue</b>; smooth muscle only <b>10–15%</b>",
"Posterior surface has peritoneal coat",
]))
story.append(sp(4))
story.append(h3("Epithelial Lining"))
story.append(bullets([
"<b>Endocervical canal:</b> 'Arbor vitae uteri' folds; lined by tall columnar epithelium (ciliated on top, basal/reserve cells below); reserve cells can undergo squamous metaplasia",
"<b>Portio vaginalis:</b> Stratified squamous epithelium; extends to external os",
]))
story.append(sp(6))
story.append(box([
Paragraph("<b>Transformation Zone (T-Zone) — HIGH YIELD</b>", S("TZHead", fontName="Helvetica-Bold", fontSize=10, textColor=ACCENT_RED, leading=14)),
Paragraph("• 1–10 mm wide; variable histological features", st_bullet),
Paragraph("• Endocervical stroma + glands covered by squamous epithelium", st_bullet),
Paragraph("• Zone is NOT static — changes with estrogen levels", st_bullet),
Paragraph("• Constantly irritated by hormones, infection, trauma", st_bullet),
Paragraph("⚠ <b>More chance of severe dysplasia, carcinoma in situ, or invasive carcinoma at this zone</b>", st_highlight),
], bg=colors.HexColor("#fff3f3"), border=ACCENT_RED))
story.append(sp(6))
story.append(h3("Cervical Secretion"))
story.append(bullets([
"Mucus: alkaline, <b>pH 7.8</b>; contains fructose (nutrition for sperm), glycoprotein, mucopolysaccharides, NaCl",
"<b>Estrogen:</b> glycoprotein arranged parallel → facilitates sperm ascent",
"<b>Progesterone:</b> interlacing bridges → prevents sperm penetration",
"<b>Mucus plug</b> — functionally closes cervical canal; bacteriolytic property",
]))
story.append(sp(8))
# Blood supply
story.append(h2("Blood Supply"))
story.append(h3("Arterial Supply"))
story.append(bullets([
"<b>Uterine artery</b> (main) — arises from anterior division of internal iliac OR common with superior vesical artery; one on each side",
"Other sources: ovarian + vaginal arteries (anastomose with uterine)",
"Ascending branch runs in lateral border of uterus between leaves of broad ligament",
]))
story.append(h3("Venous Drainage"))
story.append(bullets([
"Corresponds to arterial course → drains into <b>internal iliac veins</b>",
]))
story.append(sp(8))
# Nerve supply
story.append(h2("Nerve Supply"))
story.append(make_table(
["Type", "Segments", "Function"],
[["Sympathetic", "T₅ and T₁₀ (motor); T₁₀–L₁ (sensory)", "Motor + sensory to body"],
["Parasympathetic", "Pelvic nerve S₂, S₃, S₄", "Motor + sensory; ends in ganglia of Frankenhauser"],
["Somatic pain distribution", "T₁₀ to L₁", "Referred pain area in abdomen"]],
col_widths=[4.5*cm, 7.5*cm, 4.6*cm]
))
story.append(sp(4))
story.append(note("Cervix is insensitive to touch, heat, and incision — sparse somatic sensory supply. This is why cervical procedures can be done without anaesthesia."))
story.append(sp(8))
# Age changes
story.append(h2("Changes of Uterus with Age"))
story.append(make_table(
["Age/Stage", "Cervix : Body Ratio", "Notes"],
[["Birth", "Cervix >> Body", "Uterus lies in false pelvis"],
["Childhood", "2 : 1", "Proportion maintained"],
["Puberty", "1 : 2", "Body grows under estrogen"],
["After childbirth", "1 : 3", "Further body enlargement"],
["Menopause", "Atrophy", "Thinner walls, less muscular, more fibrous"]],
col_widths=[4.5*cm, 4.5*cm, 7.6*cm]
))
story.append(sp(6))
story.append(h3("Position Angles"))
story.append(bullets([
"<b>Anteversion angle:</b> Long axis of cervix to long axis of vagina = <b>~90°</b>",
"<b>Anteflexion angle:</b> Long axis of body to long axis of cervix = <b>~120°</b>",
"15–20% of women: retroverted uterus (normal variant)",
"In erect posture: internal os at level of symphysis pubis upper border; external os at level of ischial spines",
]))
story.append(sp(10))
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 2: FALLOPIAN TUBE
# ═══════════════════════════════════════════════════════════════════════════
story.append(h1("FALLOPIAN TUBE (SYN: UTERINE TUBE)"))
story.append(sp(4))
story.append(bullets([
"Paired muscular structures; <b>~10 cm (4\") long</b>",
"Situated in medial ¾ of upper free margin of broad ligament",
"Two openings: uterine end (1 mm diameter) and abdominal ostium (2 mm diameter)",
]))
story.append(sp(6))
story.append(h2("Parts — Medial to Lateral (4 Parts)"))
story.append(make_table(
["Part", "Length", "Diameter", "Features"],
[["Intramural / Interstitial", "1.25 cm (½\")", "1 mm", "Lies within uterine wall"],
["Isthmus", "2.5 cm (1\")", "2.5 mm", "Almost straight"],
["Ampulla", "5 cm (2\")", "Up to 6 mm", "Tortuous; site of fertilization"],
["Infundibulum", "1.25 cm (½\")", "Up to 6 mm", "Ends in fimbriae; ovarian fimbria is longest"]],
col_widths=[4.5*cm, 3*cm, 2.8*cm, 6.3*cm]
))
story.append(sp(6))
story.append(h2("Structure — 3 Layers"))
story.append(bullets([
"<b>Serous:</b> peritoneum on all sides except mesosalpinx attachment",
"<b>Muscular:</b> outer longitudinal + inner circular",
"<b>Mucous membrane:</b> longitudinal folds; partly ciliated + secretory ('Peg cells'); <b>no submucous layer; no glands; NO shedding</b> during menstrual cycle",
]))
story.append(sp(6))
story.append(h2("Functions"))
story.append(bullets([
"Transport of gametes",
"Facilitate fertilization (mainly in ampulla)",
"Survival of zygote through secretion",
]))
story.append(sp(6))
story.append(h2("Blood Supply & Nerve Supply"))
story.append(bullets([
"<b>Arterial:</b> uterine + ovarian arteries",
"<b>Venous:</b> pampiniform plexus → ovarian veins",
"<b>Nerve supply:</b> very sensitive to handling (from uterine and ovarian nerves)",
]))
story.append(sp(10))
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 3: OVARY
# ═══════════════════════════════════════════════════════════════════════════
story.append(h1("THE OVARY"))
story.append(sp(4))
story.append(bullets([
"Paired sex glands / gonads",
"Functions: (i) Germ cell maturation, storage + release; (ii) Steroidogenesis",
"Size: <b>3 cm × 2 cm × 1 cm</b>; oval; pinkish gray; scarred surface in reproductive period",
"<b>Intraperitoneal</b> structure (lies in ovarian fossa on lateral pelvic wall in nulliparae)",
]))
story.append(sp(6))
story.append(h2("Relations"))
story.append(make_table(
["Border/Surface", "Relation"],
[["Mesovarium (anterior border)", "Fold from posterior leaf of broad ligament; vessels + nerves enter hilum"],
["Posterior border", "Free; related to tubal ampulla; separated from ureter and internal iliac artery by peritoneum"],
["Medial surface", "Fimbrial part of fallopian tube"],
["Lateral surface", "Ovarian fossa on lateral pelvic wall"]],
col_widths=[5.5*cm, 11.1*cm]
))
story.append(sp(4))
story.append(note("Ovarian fossa: Superior = external iliac vein; Posterior = ureter + internal iliac vessels; Lateral = peritoneum over obturator vessels and nerves"))
story.append(sp(6))
story.append(h2("Structure"))
story.append(h3("Germinal Epithelium"))
story.append(body("Single layer of cuboid cells — <b>misnomer</b>: germ cells are NOT derived from this layer."))
story.append(sp(4))
story.append(h3("Cortex"))
story.append(bullets([
"Stromal cells thickened beneath germinal epithelium → <b>tunica albuginea</b>",
"Studded with follicular structures: primordial follicles → maturing follicles → Graafian follicles → corpus luteum",
"Atresia → atretic follicles / corpus albicans",
"Related to sex hormone production and ovulation",
]))
story.append(sp(4))
story.append(h3("Medulla"))
story.append(bullets([
"Loose connective tissue, few unstriped muscles, blood vessels, nerves",
"<b>Hilus cells</b> — homologous to interstitial cells of testes",
]))
story.append(sp(6))
story.append(h2("Blood Supply & Nerve Supply"))
story.append(bullets([
"<b>Arterial:</b> ovarian artery — branch of abdominal aorta",
"<b>Venous:</b> pampiniform plexus → Right ovarian vein → IVC; Left ovarian vein → Left renal vein",
"Placental site blood → ovarian veins → <b>thrombophlebitis in puerperium</b>",
"<b>Nerve:</b> sympathetic from T₁₀ (along ovarian artery); sensitive to manual squeezing",
]))
story.append(sp(10))
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 4: FEMALE URETHRA
# ═══════════════════════════════════════════════════════════════════════════
story.append(h1("FEMALE URETHRA"))
story.append(sp(4))
story.append(bullets([
"Length: <b>~4 cm</b>; Diameter: <b>~6 mm</b>",
"Extends from bladder neck to external urethral meatus",
"Runs downward + forward close to anterior vaginal wall",
"~1 cm from lower end: pierces triangular ligament",
"Opens into vestibule <b>~2.5 cm below clitoris</b>",
"<b>Posterior urethrovesical (PUV) angle = 100°</b> (bladder base to posterior urethral wall)",
]))
story.append(sp(6))
story.append(h2("Relations"))
story.append(make_table(
["Direction", "Relation"],
[["Posteriorly", "Anterior vaginal wall (loosely separated upper 2/3; firmly adherent lower 1/3)"],
["Anteriorly", "Posterior symphysis pubis (upper 2/3 by loose areolar tissue; lower 1/3 by pubourethral ligament)"],
["Laterally", "Compressor urethra in triangular ligament; possible puborectalis attachment"]],
col_widths=[3.5*cm, 13.1*cm]
))
story.append(sp(6))
story.append(h2("Glands & Sphincters"))
story.append(bullets([
"<b>Paraurethral glands</b> open through ducts",
"<b>Skene's glands (ducts)</b> — two longer glands opening on posterior wall just inside external meatus or vestibule; <b>homologous to the prostate in the male</b>",
"<b>Involuntary internal sphincter (lissosphincter)</b> at urethrovesical junction: intricate decussation of involuntary muscles → anterior + posterior slings; detrusor contraction → slings relax → funnel bladder neck → urine flows into urethra",
]))
story.append(sp(10))
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 5: URINARY BLADDER
# ═══════════════════════════════════════════════════════════════════════════
story.append(h1("URINARY BLADDER"))
story.append(sp(4))
story.append(bullets([
"Hollow muscular organ; considerable power of distension",
"Capacity: <b>~450 mL (15 oz)</b>; can retain up to <b>3–4 litres</b>",
"Ovoid when distended",
"Parts: (1) apex, (2) superior surface, (3) base, (4) two inferolateral surfaces, (5) neck",
]))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# PART 2 HEADER
# ═══════════════════════════════════════════════════════════════════════════
story.append(Paragraph("PART 2 — SUPPORT OF THE UTERUS", st_part))
story.append(sp(8))
story.append(box([
Paragraph(
"The dedicated Support of Uterus chapter is not included in the source pages provided. "
"All references to uterine supports explicitly mentioned in the source have been compiled below, "
"supplemented with standard Gynecology textbook anatomy (Dutta's framework) for completeness.",
S("NoteInBox", fontName="Helvetica-Oblique", fontSize=9, textColor=colors.HexColor("#444444"), leading=13)
)
], bg=YELLOW_HL, border=colors.HexColor("#b8860b")))
story.append(sp(10))
# Intro
story.append(h1("SUPPORT OF THE UTERUS — OVERVIEW"))
story.append(sp(4))
story.append(body("The uterus is maintained in its normal anteverted-anteflexed position by:"))
story.append(bullets([
"<b>Ligaments</b> (primary and accessory)",
"<b>Pelvic floor muscles</b>",
"<b>Pelvic fascia</b>",
]))
story.append(note("The pelvic floor provides the FOUNDATION; the ligaments maintain POSITION."))
story.append(sp(8))
# Primary ligaments
story.append(h1("I. PRIMARY (CARDINAL) SUPPORTS"))
story.append(sp(6))
story.append(h2("1. Transverse Cervical Ligament (Mackenrodt's / Cardinal Ligament)"))
story.append(box([
Paragraph("⭐ MOST IMPORTANT SUPPORT OF THE UTERUS", S("Star", fontName="Helvetica-Bold", fontSize=10, textColor=ACCENT_RED, leading=14)),
Paragraph("• Extends from internal os → supravaginal cervix + lateral vaginal wall → lateral pelvic wall", st_bullet),
Paragraph("• Condensation of pelvic fascia at base of broad ligament", st_bullet),
Paragraph("• Contains: uterine artery + veins, ureter, nerve fibres", st_bullet),
Paragraph("• <b>From source:</b> 'Mackenrodt's ligament extends from the internal os down to the supravaginal cervix and lateral vaginal wall'", st_bullet),
Paragraph("• Prevents lateral displacement and DESCENT of the uterus (main anti-prolapse ligament)", st_bullet),
], bg=LIGHT_BLUE, border=MED_BLUE))
story.append(sp(6))
story.append(h2("2. Uterosacral Ligament"))
story.append(bullets([
"Passes <b>posteriorly</b> from cervix/upper vagina → sacrum (S₂, S₃)",
"Keeps the cervix pulled posteriorly",
"Maintains anteversion by pulling cervix back",
"Palpable on rectal examination",
]))
story.append(sp(6))
story.append(h2("3. Pubocervical Ligament"))
story.append(bullets([
"Passes <b>anteriorly</b> from cervix → pubic symphysis",
"Anterior support of the uterus",
"Continuous with pubovesical ligament",
]))
story.append(sp(6))
story.append(h2("4. Levator Ani (Pelvic Diaphragm)"))
story.append(bullets([
"Forms the main <b>muscular support</b> (pelvic floor)",
"Provides the platform on which the uterus rests",
"Damage during childbirth = primary cause of uterine prolapse",
"Components: pubococcygeus, iliococcygeus, ischiococcygeus",
]))
story.append(sp(10))
# Secondary ligaments
story.append(h1("II. ACCESSORY (SECONDARY) SUPPORTS"))
story.append(sp(6))
story.append(h2("5. Broad Ligament"))
story.append(bullets([
"Double fold of peritoneum on each side of uterus",
"Contents: fallopian tube, round ligament, ovarian ligament, uterine vessels, ureter, parametrium, ovary (mesovarium)",
"Keeps uterus in <b>midline</b>",
"<b>Does NOT prevent prolapse</b>",
]))
story.append(sp(6))
story.append(h2("6. Round Ligament"))
story.append(bullets([
"Extends from uterine cornua → inguinal canal → labium majus",
"Maintains <b>anteversion</b> only",
"Becomes lax in retroverted uterus",
"Made of smooth muscle + fibrous tissue",
"<b>Does NOT prevent prolapse</b>",
]))
story.append(sp(6))
story.append(h2("7. Ovarian Ligament & Infundibulopelvic Ligament"))
story.append(bullets([
"<b>Ovarian ligament:</b> medial pole of ovary → uterine cornua; maintains ovarian position relative to uterus",
"<b>Infundibulopelvic (suspensory) ligament:</b> ovary → lateral pelvic wall; contains ovarian vessels + nerves",
]))
story.append(sp(8))
# Quick table
story.append(h1("III. QUICK REVISION TABLE — ALL LIGAMENTS"))
story.append(sp(4))
story.append(make_table(
["Ligament", "Attachment", "Function", "Prevents Prolapse?"],
[["Mackenrodt's (Cardinal)", "Cervix+vagina → lateral pelvic wall", "Main support; prevents descent", "✓ YES — Primary"],
["Uterosacral", "Cervix → sacrum (S₂–S₃)", "Maintains anteversion; posterior support", "✓ YES — Primary"],
["Pubocervical", "Cervix → pubic symphysis", "Anterior support", "Partial"],
["Round ligament", "Cornua → inguinal canal → labium", "Maintains anteversion only", "✗ NO"],
["Broad ligament", "Lateral uterus → pelvic wall", "Midline positioning", "✗ NO"],
["Levator ani", "Pelvic diaphragm (bony pelvis)", "Muscular platform/floor", "✓ YES — Primary"]],
col_widths=[4.2*cm, 4.8*cm, 4.8*cm, 2.8*cm]
))
story.append(sp(8))
# Uterine artery-ureter
story.append(h1("IV. UTERINE ARTERY & URETER — HIGH YIELD"))
story.append(sp(4))
story.append(box([
Paragraph("<b>From source (verbatim concept):</b>", S("Src", fontName="Helvetica-Bold", fontSize=9.5, textColor=DARK_BLUE, leading=13)),
Paragraph(
"The uterine artery crosses the ureter <b>anteriorly about 1.5 cm away at the level of the internal os</b> "
"before it ascends up along the lateral border of the uterus in between the leaves of broad ligament.",
S("SrcBody", fontName="Helvetica", fontSize=9.5, leading=13)
),
Spacer(1, 6),
Paragraph("⚡ Mnemonic: <b>'WATER UNDER THE BRIDGE'</b> — ureter (water) passes under the uterine artery (bridge)", st_highlight),
Spacer(1, 4),
Paragraph("⚡ Clinical: Risk of ureteric injury when clamping uterine vessels during hysterectomy at the level of the internal os", st_highlight),
], bg=LIGHT_BLUE, border=MED_BLUE))
story.append(sp(8))
# Clinical Q&A
story.append(h1("V. CLINICAL Q&A FOR EXAMS / VIVA"))
story.append(sp(6))
qa_pairs = [
("Q: What is the most important ligament supporting the uterus?",
"A: Transverse cervical / Mackenrodt's / Cardinal ligament"),
("Q: Which ligament maintains anteversion?",
"A: Round ligament (and uterosacral ligament pulls cervix posteriorly)"),
("Q: What provides the main muscular support?",
"A: Levator ani (pelvic diaphragm)"),
("Q: Which ligament damage in childbirth most commonly causes prolapse?",
"A: Mackenrodt's ligament + levator ani injury"),
("Q: What maintains the cervix in its posterior position?",
"A: Uterosacral ligament"),
("Q: Where does the uterine artery cross the ureter?",
"A: Anteriorly, ~1.5 cm lateral to cervix at the level of internal os"),
("Q: What are the contents of the broad ligament?",
"A: Fallopian tube (mesosalpinx), ovary (mesovarium), round ligament, ovarian ligament, uterine vessels, ureter, lymphatics, parametrial tissue"),
("Q: Why is the cervix insensitive to touch?",
"A: Sparse somatic sensory nerve supply — mainly autonomic innervation"),
("Q: What is Mackenrodt's ligament synonymous with?",
"A: Transverse cervical ligament / Cardinal ligament / Base of broad ligament"),
("Q: Which ligament does NOT prevent prolapse?",
"A: Round ligament and broad ligament — only support anteversion and midline position respectively"),
]
for q, a in qa_pairs:
story.append(KeepTogether([
Paragraph(q, st_qa_q),
Paragraph(a, st_qa_a),
sp(4),
]))
story.append(sp(8))
# Age changes table
story.append(h1("VI. FACTORS AFFECTING UTERINE SUPPORT"))
story.append(sp(4))
story.append(make_table(
["Condition", "Effect on Support"],
[["Childbirth injuries", "Damage to levator ani + ligaments → uterine prolapse"],
["Menopause", "Uterine atrophy; ligaments become lax; walls thinner and less muscular"],
["Estrogen deficiency", "Weaker pelvic floor; reduced collagen in ligaments"],
["Retroverted uterus (15–20%)", "Round ligament lax; uterosacral ligament less effective; may be normal variant"],
["Multiparity", "Repeated stretching → progressive ligament laxity"]],
col_widths=[6*cm, 10.6*cm]
))
story.append(sp(8))
# Peritoneal supports
story.append(h1("VII. PERITONEAL SPACES IN RELATION TO UTERINE SUPPORT"))
story.append(sp(4))
story.append(make_table(
["Space/Structure", "Location", "Clinical Relevance"],
[["Uterovesical pouch", "Between uterus and bladder (anteriorly)", "Bladder injury risk in anterior prolapse"],
["Pouch of Douglas (Rectouterine pouch)", "Between uterus and rectum (posteriorly)", "Site of fluid/blood collection; culdocentesis"],
["Broad ligament", "Lateral to uterus", "Contains supporting structures; haematoma site after hysterectomy"],
["Parametrium", "Connective tissue in base of broad ligament", "Contains Mackenrodt's ligament"]],
col_widths=[4.5*cm, 5*cm, 7.1*cm]
))
story.append(sp(6))
story.append(note("Note: Peritoneal folds define anatomical spaces but do NOT provide significant structural support against uterine prolapse."))
# Build
doc.build(story)
print("PDF generated successfully!")
cd /home/daytona/workspace/gynae-notes && python generate_notes.py 2>&1
ls -lh /home/daytona/workspace/gynae-notes/Gynae_Exam_Notes.pdf
Gynae Exam Notes
PDF Document · PDF