Paper presentation on2) Uterine Fibroids Impact on Women’s Health and Quality of Life for gynec resident
uterine fibroids quality of life women
uterine leiomyoma symptoms burden treatment outcomes
mkdir -p /home/daytona/workspace/fibroid-presentation && ls /home/daytona/workspace/fibroid-presentation/
~/fibroid-presentation/build_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.graphics.shapes import Drawing, Rect, String, Line
from reportlab.graphics import renderPDF
from reportlab.platypus.flowables import Flowable
import reportlab.lib.colors as c
# ── Color palette ──────────────────────────────────────────
DEEP_PURPLE = colors.HexColor("#4A235A")
MED_PURPLE = colors.HexColor("#7B3F8C")
LIGHT_PURPLE = colors.HexColor("#C39BD3")
BLUSH = colors.HexColor("#F9EBFF")
ACCENT_TEAL = colors.HexColor("#117A65")
ACCENT_RED = colors.HexColor("#C0392B")
ACCENT_ORANGE = colors.HexColor("#D68910")
DARK_GRAY = colors.HexColor("#2C3E50")
MID_GRAY = colors.HexColor("#5D6D7E")
LIGHT_GRAY = colors.HexColor("#EAF0F1")
WHITE = colors.white
BLACK = colors.black
W, H = A4 # 595.27, 841.89
# ── Document ───────────────────────────────────────────────
OUTPUT = "/home/daytona/workspace/fibroid-presentation/Uterine_Fibroids_QoL.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2.2*cm, bottomMargin=2*cm,
title="Uterine Fibroids: Impact on Women's Health and Quality of Life",
author="Gynecology Residency Grand Rounds"
)
# ── Styles ─────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
SLIDE_TITLE = S("SlideTitle",
fontName="Helvetica-Bold", fontSize=22,
textColor=WHITE, alignment=TA_LEFT,
spaceAfter=6, leading=28)
SLIDE_SUBTITLE = S("SlideSubtitle",
fontName="Helvetica", fontSize=13,
textColor=BLUSH, alignment=TA_LEFT,
spaceAfter=4, leading=17)
SECTION_LABEL = S("SectionLabel",
fontName="Helvetica-Bold", fontSize=9,
textColor=LIGHT_PURPLE, alignment=TA_LEFT,
spaceBefore=0, spaceAfter=2)
BODY = S("Body",
fontName="Helvetica", fontSize=11,
textColor=DARK_GRAY, alignment=TA_JUSTIFY,
spaceAfter=7, leading=16)
BODY_SM = S("BodySm",
fontName="Helvetica", fontSize=10,
textColor=DARK_GRAY, alignment=TA_LEFT,
spaceAfter=5, leading=14)
BULLET = S("Bullet",
fontName="Helvetica", fontSize=10.5,
textColor=DARK_GRAY, alignment=TA_LEFT,
leftIndent=14, firstLineIndent=-14,
spaceAfter=5, leading=15)
BULLET_BOLD = S("BulletBold",
fontName="Helvetica-Bold", fontSize=10.5,
textColor=DEEP_PURPLE, alignment=TA_LEFT,
leftIndent=14, firstLineIndent=-14,
spaceAfter=3, leading=15)
CAPTION = S("Caption",
fontName="Helvetica-Oblique", fontSize=8.5,
textColor=MID_GRAY, alignment=TA_CENTER,
spaceAfter=4)
REF = S("Ref",
fontName="Helvetica-Oblique", fontSize=7.5,
textColor=MID_GRAY, alignment=TA_LEFT,
spaceAfter=2, leading=10)
FOOTSTYLE = S("Foot",
fontName="Helvetica", fontSize=7.5,
textColor=LIGHT_GRAY, alignment=TA_CENTER)
NUMBER_STYLE = S("Num",
fontName="Helvetica-Bold", fontSize=7.5,
textColor=MID_GRAY, alignment=TA_RIGHT)
TABLE_HDR = S("TblHdr",
fontName="Helvetica-Bold", fontSize=9.5,
textColor=WHITE, alignment=TA_CENTER)
TABLE_CELL = S("TblCell",
fontName="Helvetica", fontSize=9,
textColor=DARK_GRAY, alignment=TA_LEFT,
leading=13)
# ── Custom Flowables ───────────────────────────────────────
class ColorBanner(Flowable):
"""Full-width header banner for each slide."""
def __init__(self, title, subtitle="", slide_num="", color=DEEP_PURPLE, height=68):
Flowable.__init__(self)
self.title = title
self.subtitle = subtitle
self.slide_num = slide_num
self.color = color
self.banner_h = height
self.width = W - 4*cm # content width
def wrap(self, availW, availH):
self.width = availW
return availW, self.banner_h
def draw(self):
c_obj = self.canv
w = self.width
# main bar
c_obj.setFillColor(self.color)
c_obj.roundRect(0, 0, w, self.banner_h, 8, fill=1, stroke=0)
# accent stripe
c_obj.setFillColor(MED_PURPLE)
c_obj.roundRect(0, 0, 6, self.banner_h, 3, fill=1, stroke=0)
# slide number badge
if self.slide_num:
c_obj.setFillColor(MED_PURPLE)
c_obj.roundRect(w-36, self.banner_h-22, 30, 16, 4, fill=1, stroke=0)
c_obj.setFont("Helvetica-Bold", 8)
c_obj.setFillColor(WHITE)
c_obj.drawCentredString(w-21, self.banner_h-13, self.slide_num)
# title
c_obj.setFont("Helvetica-Bold", 19 if len(self.title) < 40 else 16)
c_obj.setFillColor(WHITE)
c_obj.drawString(14, self.banner_h - 30, self.title)
# subtitle
if self.subtitle:
c_obj.setFont("Helvetica", 10.5)
c_obj.setFillColor(BLUSH)
c_obj.drawString(14, self.banner_h - 46, self.subtitle)
class AccentBox(Flowable):
"""Colored left-accent highlight box."""
def __init__(self, text, bg=BLUSH, accent=MED_PURPLE, height=None):
Flowable.__init__(self)
self.text = text
self.bg = bg
self.accent = accent
self._height = height or 32
self.width = 0
def wrap(self, availW, availH):
self.width = availW
return availW, self._height
def draw(self):
c_obj = self.canv
w = self.width
c_obj.setFillColor(self.bg)
c_obj.roundRect(0, 0, w, self._height, 5, fill=1, stroke=0)
c_obj.setFillColor(self.accent)
c_obj.roundRect(0, 0, 5, self._height, 3, fill=1, stroke=0)
c_obj.setFont("Helvetica-Bold", 9.5)
c_obj.setFillColor(DEEP_PURPLE)
c_obj.drawString(12, self._height/2 - 5, self.text)
class StatBox(Flowable):
"""A small KPI-style stat box."""
def __init__(self, number, label, color=MED_PURPLE, w=120, h=56):
Flowable.__init__(self)
self._w = w
self._h = h
self.number = number
self.label = label
self.color = color
def wrap(self, availW, availH):
return self._w, self._h
def draw(self):
c_obj = self.canv
c_obj.setFillColor(self.color)
c_obj.roundRect(0, 0, self._w, self._h, 6, fill=1, stroke=0)
c_obj.setFont("Helvetica-Bold", 20)
c_obj.setFillColor(WHITE)
c_obj.drawCentredString(self._w/2, self._h - 28, self.number)
c_obj.setFont("Helvetica", 8)
c_obj.setFillColor(BLUSH)
# wrap label
words = self.label.split()
line1 = " ".join(words[:4])
line2 = " ".join(words[4:]) if len(words) > 4 else ""
c_obj.drawCentredString(self._w/2, self._h - 40, line1)
if line2:
c_obj.drawCentredString(self._w/2, self._h - 50, line2)
def divider(color=LIGHT_PURPLE, thickness=1):
return HRFlowable(width="100%", thickness=thickness, color=color,
spaceAfter=6, spaceBefore=2)
def sp(n=6):
return Spacer(1, n)
def bullet(text, bold_prefix=""):
if bold_prefix:
return Paragraph(f"<b>● {bold_prefix}</b> {text}", BULLET)
return Paragraph(f"● {text}", BULLET)
def sub_bullet(text):
s = ParagraphStyle("sub", parent=BULLET, leftIndent=28, firstLineIndent=-14,
fontSize=9.5, textColor=MID_GRAY)
return Paragraph(f"◦ {text}", s)
# ══════════════════════════════════════════════════════════
# SLIDE CONTENT
# ══════════════════════════════════════════════════════════
story = []
# ──────────────────────────────────────────────────────────
# TITLE SLIDE
# ──────────────────────────────────────────────────────────
class TitleSlide(Flowable):
def wrap(self, availW, availH):
self.width = availW
return availW, 340
def draw(self):
c_obj = self.canv
w = self.width
# Background gradient-like blocks
c_obj.setFillColor(DEEP_PURPLE)
c_obj.roundRect(0, 0, w, 340, 10, fill=1, stroke=0)
c_obj.setFillColor(MED_PURPLE)
c_obj.roundRect(0, 0, w*0.45, 340, 10, fill=1, stroke=0)
# decorative circles
c_obj.setFillColor(colors.HexColor("#8E44AD"))
c_obj.circle(w*0.8, 280, 60, fill=1, stroke=0)
c_obj.setFillColor(colors.HexColor("#6C3483"))
c_obj.circle(w*0.9, 320, 40, fill=1, stroke=0)
# Uterus icon (simplified)
c_obj.setFillColor(BLUSH)
c_obj.setStrokeColor(LIGHT_PURPLE)
c_obj.setLineWidth(2)
c_obj.roundRect(w*0.12, 240, 50, 40, 8, fill=1, stroke=1)
# Main title
c_obj.setFont("Helvetica-Bold", 24)
c_obj.setFillColor(WHITE)
c_obj.drawString(18, 300, "Uterine Fibroids:")
c_obj.setFont("Helvetica-Bold", 20)
c_obj.setFillColor(LIGHT_PURPLE)
c_obj.drawString(18, 272, "Impact on Women's Health &")
c_obj.drawString(18, 248, "Quality of Life")
# Divider
c_obj.setStrokeColor(LIGHT_PURPLE)
c_obj.setLineWidth(1.5)
c_obj.line(18, 234, w*0.8, 234)
# Subtitles
c_obj.setFont("Helvetica", 11)
c_obj.setFillColor(BLUSH)
c_obj.drawString(18, 216, "Grand Rounds | Department of Obstetrics & Gynecology")
c_obj.setFont("Helvetica-Oblique", 10)
c_obj.drawString(18, 198, "Paper Presentation for Gynecology Residents")
# Footer
c_obj.setFont("Helvetica", 9)
c_obj.setFillColor(LIGHT_PURPLE)
c_obj.drawString(18, 24, "Source: Berek & Novak's Gynecology | AAGL 2025 | PubMed Evidence 2021-2026")
story.append(TitleSlide())
story.append(sp(16))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 2 – LEARNING OBJECTIVES
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Learning Objectives", "What you will take away today", "02"))
story.append(sp(10))
objectives = [
("Define", "uterine fibroids and understand their classification (FIGO/PALM-COEIN)"),
("Quantify", "the epidemiological burden across race and age groups"),
("Recognize", "the full spectrum of symptoms and their impact on quality of life"),
("Identify", "diagnostic modalities and their comparative accuracy"),
("Evaluate", "evidence-based medical and surgical management options"),
("Apply", "a patient-centered approach to individualized treatment decisions"),
]
for verb, rest in objectives:
story.append(Paragraph(f"<font color='#7B3F8C'><b>✔ {verb}</b></font> {rest}", BULLET))
story.append(sp(3))
story.append(sp(8))
story.append(divider(LIGHT_PURPLE))
story.append(Paragraph(
"<i>Source: Berek & Novak's Gynecology (16th ed.) | AAGL Practice Guidelines 2025 | PubMed 2021–2026</i>",
REF))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 3 – EPIDEMIOLOGY & BURDEN
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Epidemiology & Disease Burden",
"The most common benign pelvic tumor in women of reproductive age", "03"))
story.append(sp(10))
# Stat boxes row
stat_data = [
[StatBox("77%", "of hysterectomy specimens contain fibroids", MED_PURPLE),
StatBox("80%", "of Black women affected by age 50", ACCENT_TEAL),
StatBox("70%", "of White women affected by age 50", ACCENT_ORANGE),
StatBox("$2.1B","annual inpatient surgery cost (USA)", ACCENT_RED)],
]
stat_table = Table(stat_data, colWidths=[120, 120, 120, 120])
stat_table.setStyle(TableStyle([("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4)]))
story.append(stat_table)
story.append(sp(10))
story.append(divider(LIGHT_PURPLE))
story.append(Paragraph("<b>Key Epidemiological Facts</b>", SECTION_LABEL))
story.append(sp(4))
story.append(bullet("Fibroids are <b>benign monoclonal tumors</b> of uterine smooth muscle (leiomyomas); "
"most common pelvic tumor in women"))
story.append(bullet("African American women: incidence <b>60% by age 35</b>, >80% by age 50 – "
"higher severity and earlier onset than White women"))
story.append(bullet("Nearly <b>240,000 hysterectomies</b> performed annually in the US for fibroids vs ~30,000 myomectomies"))
story.append(bullet("Outpatient care, lost productivity, and indirect costs add significantly beyond the $2.1B inpatient burden"))
story.append(bullet("<b>Racial disparities</b> persist in access to uterus-preserving treatments and time to diagnosis"))
story.append(sp(4))
story.append(Paragraph(
"<i>Berek & Novak's Gynecology, p. 497; HSTAT NIS data</i>", REF))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 4 – PATHOPHYSIOLOGY & CLASSIFICATION
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Pathophysiology & Classification",
"Origins, molecular biology, and FIGO/PALM-COEIN system", "04"))
story.append(sp(10))
# Two-column layout
left = [
Paragraph("<b>Pathogenesis</b>", SECTION_LABEL),
sp(4),
bullet("Monoclonal proliferation of uterine smooth muscle cells"),
bullet("Rich in <b>extracellular matrix</b>: collagen, elastin, fibronectin, proteoglycans"),
bullet("Driven by <b>estrogen & progesterone</b>; EGF, IGF-I, and TGF-beta act as growth factors"),
bullet("Genetic mutations: <b>MED12</b> (most common ~70%), HMGA2, FH"),
bullet("Tissue injury hypothesis: repetitive endometrial injury + stromal repair releases growth factors"),
sp(6),
Paragraph("<b>Risk Factors</b>", SECTION_LABEL),
sp(3),
bullet("African American race (3–4x higher risk)"),
bullet("Nulliparity, early menarche (<10 y)"),
bullet("Obesity (+21% risk per 10 kg body weight)"),
bullet("Red meat/low vegetable diet"),
bullet("Protective: parity, smoking (reduced estrogen), exercise (>7 h/week)"),
]
right = [
Paragraph("<b>FIGO Classification (2011)</b>", SECTION_LABEL),
sp(4),
]
figo_data = [
[Paragraph("<b>Type</b>", TABLE_HDR), Paragraph("<b>Location</b>", TABLE_HDR)],
[Paragraph("0", TABLE_CELL), Paragraph("Pedunculated intracavitary (submucosal)", TABLE_CELL)],
[Paragraph("1", TABLE_CELL), Paragraph("<50% intramural (submucosal)", TABLE_CELL)],
[Paragraph("2", TABLE_CELL), Paragraph("≥50% intramural (submucosal)", TABLE_CELL)],
[Paragraph("3", TABLE_CELL), Paragraph("Entirely intramural, contacts endometrium", TABLE_CELL)],
[Paragraph("4", TABLE_CELL), Paragraph("Entirely intramural", TABLE_CELL)],
[Paragraph("5", TABLE_CELL), Paragraph("Subserosal ≥50% intramural", TABLE_CELL)],
[Paragraph("6", TABLE_CELL), Paragraph("Subserosal <50% intramural", TABLE_CELL)],
[Paragraph("7", TABLE_CELL), Paragraph("Pedunculated subserosal", TABLE_CELL)],
[Paragraph("8", TABLE_CELL), Paragraph("Other (cervical, parasitic)", TABLE_CELL)],
]
figo_tbl = Table(figo_data, colWidths=[45, 145])
figo_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP_PURPLE),
("BACKGROUND", (0,1), (-1,1), BLUSH),
("BACKGROUND", (0,2), (-1,2), WHITE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BLUSH, WHITE]),
("GRID", (0,0), (-1,-1), 0.5, LIGHT_PURPLE),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
right.append(figo_tbl)
right.append(sp(5))
right.append(Paragraph(
"<i>Types 0–2: submucosal (most symptomatic) | 3–5: intramural | 6–8: subserosal</i>", REF))
right.append(sp(5))
right.append(Paragraph("<b>PALM-COEIN Classification (FIGO AUB)</b>", SECTION_LABEL))
right.append(sp(3))
right.append(bullet("<b>AUB-LSM</b>: submucosal leiomyoma"))
right.append(bullet("<b>AUB-LO</b>: other leiomyoma"))
from reportlab.platypus import BalancedColumns
two_col = Table([[left, right]], colWidths=[245, 245])
two_col.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
story.append(two_col)
story.append(sp(4))
story.append(Paragraph("<i>Berek & Novak's Gynecology, pp. 498–508</i>", REF))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 5 – SYMPTOMS & QoL IMPACT
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Symptoms & Impact on Quality of Life",
"Fibroids rarely cause mortality but significantly impair QoL", "05"))
story.append(sp(8))
story.append(AccentBox(
"Women with fibroids score WORSE on SF-36 QoL than patients with hypertension, "
"heart disease, chronic lung disease, or arthritis",
BLUSH, ACCENT_RED, height=38))
story.append(sp(10))
sym_data = [
[Paragraph("<b>Symptom Domain</b>", TABLE_HDR),
Paragraph("<b>Details</b>", TABLE_HDR),
Paragraph("<b>QoL Impact</b>", TABLE_HDR)],
[Paragraph("Heavy Menstrual Bleeding", TABLE_CELL),
Paragraph("Types 0–1 most associated with anemia; 7.5 pads/day vs 6.1 without fibroids; "
"Hb <12 strongly correlated with Type 0", TABLE_CELL),
Paragraph("Fatigue, anemia, activity limitation", TABLE_CELL)],
[Paragraph("Pelvic Pain/Pressure", TABLE_CELL),
Paragraph("Degeneration (red, hyaline, cystic); torsion of pedunculated fibroids; "
"dysmenorrhea slightly elevated vs controls", TABLE_CELL),
Paragraph("Work absence, sexual dysfunction", TABLE_CELL)],
[Paragraph("Bulk Symptoms", TABLE_CELL),
Paragraph("Urinary frequency/urgency (anterior fibroids); constipation/tenesmus "
"(posterior fibroids); abdominal distension", TABLE_CELL),
Paragraph("Social embarrassment, sleep disruption", TABLE_CELL)],
[Paragraph("Reproductive Impact", TABLE_CELL),
Paragraph("Submucosal fibroids impair IVF outcomes; myomectomy before IVF "
"improves implantation; risk of miscarriage increased", TABLE_CELL),
Paragraph("Infertility distress, pregnancy anxiety", TABLE_CELL)],
[Paragraph("Psychosocial", TABLE_CELL),
Paragraph("48% of 116 women with large fibroids chose treatment within 1 year due to "
"high symptom distress scores", TABLE_CELL),
Paragraph("Anxiety, body image concerns, depression", TABLE_CELL)],
]
sym_tbl = Table(sym_data, colWidths=[115, 225, 150])
sym_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP_PURPLE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BLUSH, WHITE]),
("GRID", (0,0), (-1,-1), 0.5, LIGHT_PURPLE),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
]))
story.append(sym_tbl)
story.append(sp(6))
story.append(Paragraph(
"<i>Berek & Novak's Gynecology, pp. 503–506 | SF-36 data from Roth et al.</i>", REF))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 6 – DIAGNOSIS
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Diagnosis & Imaging",
"Accurate assessment guides treatment selection", "06"))
story.append(sp(10))
diag_data = [
[Paragraph("<b>Modality</b>", TABLE_HDR),
Paragraph("<b>Sensitivity (Submucosal)</b>", TABLE_HDR),
Paragraph("<b>Specificity</b>", TABLE_HDR),
Paragraph("<b>Key Advantage</b>", TABLE_HDR)],
[Paragraph("Transvaginal US (TVS)", TABLE_CELL),
Paragraph("83%", TABLE_CELL),
Paragraph("90%", TABLE_CELL),
Paragraph("First-line; widely available; cost-effective", TABLE_CELL)],
[Paragraph("Saline Infusion Sonography (SIS)", TABLE_CELL),
Paragraph("90%", TABLE_CELL),
Paragraph("89%", TABLE_CELL),
Paragraph("Best for intracavitary distinction; pre-hysteroscopy", TABLE_CELL)],
[Paragraph("Hysteroscopy", TABLE_CELL),
Paragraph("82%", TABLE_CELL),
Paragraph("87%", TABLE_CELL),
Paragraph("Direct visualization; therapeutic simultaneously", TABLE_CELL)],
[Paragraph("MRI", TABLE_CELL),
Paragraph("<b>100%</b>", TABLE_CELL),
Paragraph("91%", TABLE_CELL),
Paragraph("Gold standard; maps all fibroids; pre-UAE/HIFU", TABLE_CELL)],
]
diag_tbl = Table(diag_data, colWidths=[120, 100, 80, 190])
diag_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP_PURPLE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BLUSH, WHITE]),
("GRID", (0,0), (-1,-1), 0.5, LIGHT_PURPLE),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("FONTNAME", (0,1), (1,-1), "Helvetica"),
]))
story.append(diag_tbl)
story.append(sp(10))
story.append(Paragraph("<b>Clinical Pearls</b>", SECTION_LABEL))
story.append(sp(4))
story.append(bullet("MRI has <b>low interobserver variability</b> and best differentiates fibroids from adenomyosis "
"(junctional zone >15 mm = adenomyosis)"))
story.append(bullet("Adenomyosis co-exists in up to 30% of women with fibroids and independently worsens dysmenorrhea"))
story.append(bullet("<b>Inability to evaluate ovaries on exam is NOT an indication for surgery</b> — "
"use sonography if needed"))
story.append(bullet("Rapid growth does NOT reliably predict leiomyosarcoma; prevalence of LMS is 1 in 1,960 "
"in surgical specimens"))
story.append(sp(4))
story.append(Paragraph("<i>Berek & Novak's Gynecology, pp. 507–509</i>", REF))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 7 – MEDICAL MANAGEMENT
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Medical Management",
"Evidence-based pharmacological options", "07"))
story.append(sp(8))
med_rows = [
[Paragraph("<b>Agent</b>", TABLE_HDR),
Paragraph("<b>Mechanism</b>", TABLE_HDR),
Paragraph("<b>Evidence / Effect</b>", TABLE_HDR),
Paragraph("<b>Limitations</b>", TABLE_HDR)],
[Paragraph("Tranexamic Acid\n1.3g TID x3–5d", TABLE_CELL),
Paragraph("Antifibrinolytic", TABLE_CELL),
Paragraph("Significant reduction in MBL vs placebo (RCT x2); non-hormonal", TABLE_CELL),
Paragraph("Headache 55%, nausea 15%; not for markedly enlarged fibroids", TABLE_CELL)],
[Paragraph("Combined OCP", TABLE_CELL),
Paragraph("Estrogen-progestin", TABLE_CELL),
Paragraph("Manages bleeding; does not stimulate new fibroid growth", TABLE_CELL),
Paragraph("Does not reduce fibroid volume", TABLE_CELL)],
[Paragraph("Levonorgestrel IUS", TABLE_CELL),
Paragraph("Local progestin", TABLE_CELL),
Paragraph("Reduces HMB; QoL improvement", TABLE_CELL),
Paragraph("May be expelled if cavity distorted", TABLE_CELL)],
[Paragraph("GnRH Agonists\n(leuprolide)", TABLE_CELL),
Paragraph("Hypoestrogen state", TABLE_CELL),
Paragraph("↓ uterine vol 35%, fibroid vol 30% in 6 months; resolves HMB in 97%", TABLE_CELL),
Paragraph("Side effects in 95%; hot flushes 78%; bone loss after 6 mo; rebound", TABLE_CELL)],
[Paragraph("GnRH Antagonists\n(elagolix, relugolix)", TABLE_CELL),
Paragraph("Competitive GnRH receptor blockade", TABLE_CELL),
Paragraph("Rapid onset; relugolix combo (2026 SR/MA) reduces HMB and improves QoL", TABLE_CELL),
Paragraph("Cost; add-back therapy needed for long-term use", TABLE_CELL)],
[Paragraph("SPRMs\n(ulipristal acetate)", TABLE_CELL),
Paragraph("Progesterone receptor modulator", TABLE_CELL),
Paragraph("Reduces HMB and fibroid size; EU approved (hepatotoxicity concern)", TABLE_CELL),
Paragraph("Hepatotoxicity – restricted use; not available in all countries", TABLE_CELL)],
]
med_tbl = Table(med_rows, colWidths=[90, 80, 165, 145])
med_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP_PURPLE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BLUSH, WHITE]),
("GRID", (0,0), (-1,-1), 0.5, LIGHT_PURPLE),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("FONTSIZE", (0,0), (-1,-1), 8.5),
]))
story.append(med_tbl)
story.append(sp(6))
story.append(Paragraph(
"<i>Berek & Novak's Gynecology, pp. 514–520 | Kalpina et al. Eur J Obstet 2026 (PMID 41389730) | "
"Puscasiu et al. Cochrane 2025 (PMID 40183418)</i>", REF))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 8 – SURGICAL MANAGEMENT
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Surgical Management",
"Tailored to symptoms, size, location, and reproductive goals", "08"))
story.append(sp(8))
surg_data = [
[Paragraph("<b>Procedure</b>", TABLE_HDR),
Paragraph("<b>Indication</b>", TABLE_HDR),
Paragraph("<b>Key Outcomes</b>", TABLE_HDR),
Paragraph("<b>Fertility Preserved?</b>", TABLE_HDR)],
[Paragraph("Hysteroscopic Myomectomy", TABLE_CELL),
Paragraph("Types 0–2 submucosal; HMB; infertility", TABLE_CELL),
Paragraph("Best for cavity fibroids; day-case; symptom relief >90%", TABLE_CELL),
Paragraph("Yes ✓", TABLE_CELL)],
[Paragraph("Laparoscopic Myomectomy", TABLE_CELL),
Paragraph("Subserosal/intramural ≤3 fibroids; preserve uterus", TABLE_CELL),
Paragraph("75% significant symptom reduction at 6 months; equivalent to open", TABLE_CELL),
Paragraph("Yes ✓", TABLE_CELL)],
[Paragraph("Abdominal Myomectomy", TABLE_CELL),
Paragraph("Large/multiple fibroids; failed laparoscopic", TABLE_CELL),
Paragraph("80% symptom relief; safe even for large fibroids; gold standard pre-myomectomy", TABLE_CELL),
Paragraph("Yes ✓", TABLE_CELL)],
[Paragraph("Laparoscopic RFA\n(Acessa/Sonata)", TABLE_CELL),
Paragraph("Intramural/subserosal; no desire for pregnancy", TABLE_CELL),
Paragraph("AAGL 2025 SR/MA: sustained QoL improvement; low complication rate", TABLE_CELL),
Paragraph("Uncertain", TABLE_CELL)],
[Paragraph("UAE", TABLE_CELL),
Paragraph("Symptomatic; uterus preservation; no surgery", TABLE_CELL),
Paragraph("2024 meta-analysis: non-inferior to myomectomy for QoL; higher reintervention", TABLE_CELL),
Paragraph("Caution - UAE", TABLE_CELL)],
[Paragraph("Hysterectomy", TABLE_CELL),
Paragraph("Definitive; completed family; failed other treatment", TABLE_CELL),
Paragraph("Cure; significant QoL improvement; most common indication for hysterectomy", TABLE_CELL),
Paragraph("No ✗", TABLE_CELL)],
]
surg_tbl = Table(surg_data, colWidths=[105, 120, 190, 75])
surg_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP_PURPLE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BLUSH, WHITE]),
("GRID", (0,0), (-1,-1), 0.5, LIGHT_PURPLE),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("TEXTCOLOR", (3,1), (3,-1), ACCENT_TEAL),
("FONTNAME", (3,1), (3,-1), "Helvetica-Bold"),
]))
story.append(surg_tbl)
story.append(sp(6))
story.append(Paragraph(
"<i>Berek & Novak's Gynecology, pp. 517–525 | Tzanis et al. AJOG 2024 (PMID 38280434) | "
"Peng et al. Sci Rep 2024 (PMID 39164326) | Chen et al. JMIG 2025 (PMID 39277104)</i>", REF))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 9 – FERTILITY & PREGNANCY
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Fibroids, Fertility & Pregnancy",
"A nuanced relationship requiring individualized counselling", "09"))
story.append(sp(10))
story.append(Paragraph("<b>Impact on Fertility</b>", SECTION_LABEL))
story.append(sp(4))
story.append(bullet("Submucosal fibroids (Types 0–2) <b>significantly reduce IVF implantation rates</b> "
"and increase miscarriage risk"))
story.append(bullet("Intramural fibroids with no cavity distortion: modest effect on fertility; "
"myomectomy benefit less clear"))
story.append(bullet("Subserosal fibroids generally do <b>not impair fertility</b>"))
story.append(bullet("<b>Hysteroscopic myomectomy</b> before IVF is recommended for Types 0–2 to improve outcomes"))
story.append(sp(8))
story.append(Paragraph("<b>Pregnancy Complications</b>", SECTION_LABEL))
story.append(sp(4))
comp_data = [
[Paragraph("<b>Complication</b>", TABLE_HDR), Paragraph("<b>Comment</b>", TABLE_HDR)],
[Paragraph("Preterm labor", TABLE_CELL), Paragraph("Particularly with multiple or large intramural fibroids", TABLE_CELL)],
[Paragraph("Malpresentation", TABLE_CELL), Paragraph("Distorted uterine cavity; increased cesarean rate", TABLE_CELL)],
[Paragraph("Placental abruption", TABLE_CELL), Paragraph("Retroplacental fibroid location increases risk", TABLE_CELL)],
[Paragraph("Fibroid degeneration (red degeneration)", TABLE_CELL), Paragraph("Painful crisis in 2nd trimester; manage conservatively with analgesia", TABLE_CELL)],
[Paragraph("Postpartum hemorrhage", TABLE_CELL), Paragraph("Uterine atony in fibromatous uteri", TABLE_CELL)],
]
comp_tbl = Table(comp_data, colWidths=[185, 305])
comp_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP_PURPLE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BLUSH, WHITE]),
("GRID", (0,0), (-1,-1), 0.5, LIGHT_PURPLE),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
]))
story.append(comp_tbl)
story.append(sp(6))
story.append(bullet("Parity is <b>protective</b>: increasing parity decreases incidence and number of fibroids "
"(postpartum involution/apoptosis)"))
story.append(sp(4))
story.append(Paragraph("<i>Berek & Novak's Gynecology, pp. 505–506, 517</i>", REF))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 10 – TREATMENT ALGORITHM
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Clinical Decision Framework",
"Patient-centered approach to management", "10"))
story.append(sp(8))
class AlgorithmFlowable(Flowable):
def wrap(self, availW, availH):
self.width = availW
return availW, 420
def draw(self):
c_obj = self.canv
w = self.width
def box(x, y, bw, bh, text, bg, text_color=colors.white, font_size=9):
c_obj.setFillColor(bg)
c_obj.roundRect(x, y, bw, bh, 6, fill=1, stroke=0)
c_obj.setFont("Helvetica-Bold", font_size)
c_obj.setFillColor(text_color)
lines = text.split("\n")
lh = font_size + 2
total_h = len(lines)*lh
start_y = y + bh/2 + total_h/2 - lh
for i, l in enumerate(lines):
c_obj.drawCentredString(x + bw/2, start_y - i*lh, l)
def arrow(x1, y1, x2, y2):
c_obj.setStrokeColor(MID_GRAY)
c_obj.setLineWidth(1.2)
c_obj.line(x1, y1, x2, y2)
# arrowhead
dx, dy = x2-x1, y2-y1
length = (dx**2 + dy**2)**0.5
if length == 0: return
ux, uy = dx/length, dy/length
ax, ay = x2-8*ux+4*uy, y2-8*uy+4*ux
bx, by = x2-8*ux-4*uy, y2-8*uy-4*ux
c_obj.setFillColor(MID_GRAY)
p = c_obj.beginPath()
p.moveTo(x2, y2); p.lineTo(ax, ay); p.lineTo(bx, by); p.close()
c_obj.drawPath(p, fill=1, stroke=0)
# Start box
box(w/2-100, 390, 200, 28, "Woman with Uterine Fibroids", DEEP_PURPLE, font_size=10)
arrow(w/2, 390, w/2, 368)
# Symptomatic?
box(w/2-75, 340, 150, 26, "Symptomatic?", MED_PURPLE, font_size=9)
# No branch
c_obj.setStrokeColor(MID_GRAY); c_obj.setLineWidth(1.2)
c_obj.line(w/2-75, 353, w/2-175, 353)
c_obj.line(w/2-175, 353, w/2-175, 308)
box(w/2-230, 288, 110, 26, "Watchful Waiting\n(esp. perimenopause)", ACCENT_TEAL, font_size=7.5)
c_obj.setFont("Helvetica-Oblique", 8); c_obj.setFillColor(ACCENT_TEAL)
c_obj.drawString(w/2-175, 358, "No")
# Yes arrow
arrow(w/2, 340, w/2, 318)
c_obj.setFont("Helvetica-Oblique", 8); c_obj.setFillColor(MED_PURPLE)
c_obj.drawString(w/2+4, 328, "Yes")
# Fertility desired?
box(w/2-85, 290, 170, 26, "Fertility Desired?", MED_PURPLE, font_size=9)
# Yes branch (left)
c_obj.setStrokeColor(MID_GRAY); c_obj.setLineWidth(1.2)
c_obj.line(w/2-85, 303, w/2-160, 303)
c_obj.line(w/2-160, 303, w/2-160, 262)
arrow(w/2-160, 262, w/2-160, 250)
box(w/2-230, 222, 140, 26, "Medical Rx 1st\n(Tranexamic/GnRHa)", ACCENT_ORANGE, font_size=7.5)
arrow(w/2-160, 222, w/2-160, 198)
box(w/2-230, 168, 140, 26, "Myomectomy\n(hystero/laparoscopic)", ACCENT_TEAL, font_size=7.5)
c_obj.setFont("Helvetica-Oblique", 8); c_obj.setFillColor(ACCENT_ORANGE)
c_obj.drawString(w/2-155, 307, "Yes")
# No branch (right)
c_obj.setStrokeColor(MID_GRAY); c_obj.setLineWidth(1.2)
c_obj.line(w/2+85, 303, w/2+160, 303)
c_obj.line(w/2+160, 303, w/2+160, 262)
arrow(w/2+160, 262, w/2+160, 250)
box(w/2+90, 222, 140, 26, "Medical Rx\n(GnRHa / GnRH Ant)", ACCENT_ORANGE, font_size=7.5)
arrow(w/2+160, 222, w/2+160, 198)
box(w/2+90, 168, 140, 26, "Surgical / Interventional\n(UAE/RFA/Hysterectomy)", ACCENT_RED, font_size=7.5)
c_obj.setFont("Helvetica-Oblique", 8); c_obj.setFillColor(ACCENT_RED)
c_obj.drawString(w/2+165, 307, "No")
# Bottom: consider QoL
box(w/2-120, 100, 240, 36,
"Reassess QoL at 3–6 months\nModify plan if inadequate symptom control",
DEEP_PURPLE, font_size=8.5)
arrow(w/2-160, 168, w/2-60, 136)
arrow(w/2+160, 168, w/2+60, 136)
# Labels
c_obj.setFont("Helvetica-Oblique", 7.5)
c_obj.setFillColor(MID_GRAY)
c_obj.drawString(20, 80, "Peri/postmenopausal women: watchful waiting often sufficient; fibroids regress after menopause")
c_obj.drawString(20, 68, "Shared decision-making: patient preferences, access, and surgeon expertise guide choice")
story.append(AlgorithmFlowable())
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 11 – RACIAL DISPARITIES & SPECIAL POPULATIONS
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Racial Disparities & Special Populations",
"Addressing inequity in fibroid care", "11"))
story.append(sp(10))
left2 = [
Paragraph("<b>African American Women</b>", SECTION_LABEL),
sp(4),
bullet("3–4x higher prevalence; earlier onset; larger and more fibroids"),
bullet("Greater fibroid-related disability and more severe anemia"),
bullet("Significantly higher hysterectomy rates relative to myomectomy"),
bullet("Less likely to receive minimally invasive or uterus-preserving options"),
bullet("Barriers: systemic access issues, physician bias, insurance gaps"),
sp(6),
Paragraph("<b>Perimenopausal Women</b>", SECTION_LABEL),
sp(4),
bullet("After menopause: bleeding stops and fibroid volume decreases"),
bullet("Short-term GnRH agonist can bridge to natural menopause"),
bullet("31/34 women avoided surgery; 15 reached natural menopause"),
bullet("Add-back therapy considered to mitigate bone loss"),
]
right2 = [
Paragraph("<b>Fibroids & Mental Health</b>", SECTION_LABEL),
sp(4),
bullet("Chronic pain and heavy bleeding linked to <b>anxiety and depression</b>"),
bullet("Body image concerns; negative impact on sexual relationships"),
bullet("Women who delay treatment often have highest psychosocial burden"),
sp(6),
Paragraph("<b>Key Recommendations for Equitable Care</b>", SECTION_LABEL),
sp(4),
AccentBox("Offer minimally invasive options equitably across all ethnic groups", BLUSH, ACCENT_TEAL, 34),
sp(4),
AccentBox("Screen for anxiety/depression in women with chronic fibroid symptoms", BLUSH, MED_PURPLE, 34),
sp(4),
AccentBox("Educate patients about full range of treatment options at first visit", BLUSH, ACCENT_ORANGE, 34),
sp(4),
AccentBox("Use validated QoL tools (SF-36, UFS-QOL) at baseline and follow-up", BLUSH, DEEP_PURPLE, 34),
]
two_col2 = Table([[left2, right2]], colWidths=[245, 245])
two_col2.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
story.append(two_col2)
story.append(sp(8))
story.append(divider())
story.append(Paragraph(
"<i>Berek & Novak's Gynecology, pp. 498–503 | ACOG Practice Bulletin 2021</i>", REF))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 12 – RECENT EVIDENCE
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Recent Evidence (2021–2026)",
"What the latest literature adds to clinical practice", "12"))
story.append(sp(8))
evidence = [
("PMID 41389730", "Relugolix combination therapy (2026, Cochrane-level SR/MA)",
"Kalpina et al. Eur J Obstet Gynecol Reprod Biol 2026",
"Relugolix 40mg + estradiol + norethindrone significantly reduces HMB and improves QoL; "
"rapid onset vs leuprolide; bone density preserved with add-back"),
("PMID 40183418", "Preoperative medical therapy before fibroid surgery (2025, Cochrane SR)",
"Puscasiu et al. Cochrane Database Syst Rev 2025",
"GnRH analogues preoperatively reduce uterine volume, correct anemia, and facilitate "
"minimally invasive surgery; ulipristal also effective"),
("PMID 39277104", "Radiofrequency ablation for uterine fibroids (2025, AAGL SR/MA)",
"Chen et al. J Minim Invasive Gynecol 2025",
"RFA (Acessa, Sonata) demonstrates sustained symptom relief and QoL improvement; "
"low complication rates; approved uterus-preserving option"),
("PMID 38280434", "UAE vs Myomectomy (2024, SR/MA)",
"Tzanis et al. Am J Obstet Gynecol 2024",
"Both modalities non-inferior for QoL improvement; UAE has higher reintervention "
"rates; myomectomy preferred for fertility preservation"),
("PMID 39164326", "UAE vs Myomectomy updated evidence (2024, SR/MA)",
"Peng et al. Sci Rep 2024",
"Confirms QoL equivalence; UAE associated with less blood loss intraoperatively "
"but higher long-term treatment failure"),
]
ev_data = [[Paragraph("<b>PMID</b>", TABLE_HDR),
Paragraph("<b>Study / Citation</b>", TABLE_HDR),
Paragraph("<b>Key Finding</b>", TABLE_HDR)]]
for pmid, title, citation, finding in evidence:
ev_data.append([
Paragraph(f"<font color='#7B3F8C'>{pmid}</font>", TABLE_CELL),
Paragraph(f"<b>{title}</b><br/><i>{citation}</i>", TABLE_CELL),
Paragraph(finding, TABLE_CELL),
])
ev_tbl = Table(ev_data, colWidths=[75, 185, 230])
ev_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DEEP_PURPLE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BLUSH, WHITE]),
("GRID", (0,0), (-1,-1), 0.5, LIGHT_PURPLE),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("FONTSIZE", (0,0), (-1,-1), 8.5),
]))
story.append(ev_tbl)
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 13 – KEY TAKE-HOMES & REFERENCES
# ──────────────────────────────────────────────────────────
story.append(ColorBanner("Key Take-Home Messages",
"Clinical summary for practice", "13"))
story.append(sp(8))
takeaways = [
("1", "Fibroids are ubiquitous", "affecting up to 80% of women by age 50, with Black women disproportionately burdened"),
("2", "QoL impact is profound", "exceeding that of hypertension and heart disease on SF-36 scores; never dismiss symptoms"),
("3", "Accurate classification matters", "FIGO Types 0–2 submucosal fibroids are most symptomatic and most amenable to hysteroscopic treatment"),
("4", "MRI is the gold standard", "for pre-procedural mapping (sensitivity 100%); use before UAE, RFA, or complex myomectomy"),
("5", "Medical therapy first", "for symptom control – tranexamic acid, GnRH analogues, and now oral GnRH antagonists offer non-surgical options"),
("6", "Fertility preservation", "is possible with myomectomy (all routes); share all options and involve patient in decision-making"),
("7", "Watchful waiting", "is safe and appropriate for asymptomatic or perimenopausal women – fibroids regress after menopause"),
("8", "Address disparities", "proactively offer MIS and uterus-preserving options to all women regardless of race or socioeconomic status"),
]
for num, bold, rest in takeaways:
story.append(Paragraph(f"<font color='#7B3F8C'><b>{num}.</b></font> <b>{bold}</b> – {rest}", BULLET))
story.append(sp(3))
story.append(sp(8))
story.append(divider(DEEP_PURPLE, 1.5))
story.append(sp(5))
story.append(Paragraph("<b>References</b>", SECTION_LABEL))
refs = [
"Berek JS, Novak E. Berek & Novak's Gynecology, 16th ed. Wolters Kluwer, 2020. Chapter 11.",
"Kalpina F et al. Efficacy and safety of relugolix for symptomatic uterine fibroids: SR/MA. Eur J Obstet Gynecol Reprod Biol. 2026. PMID: 41389730",
"Puscasiu L et al. Preoperative medical therapy before surgery for uterine fibroids. Cochrane Database Syst Rev. 2025. PMID: 40183418",
"Chen I et al. Radiofrequency Ablation for Uterine Fibroids: SR/MA by AAGL. J Minim Invasive Gynecol. 2025. PMID: 39277104",
"Tzanis AA et al. UAE vs myomectomy for uterine leiomyomas: SR/MA. Am J Obstet Gynecol. 2024. PMID: 38280434",
"Peng J et al. UAE vs myomectomy for symptomatic uterine fibroids: SR/MA. Sci Rep. 2024. PMID: 39164326",
"FIGO leiomyoma classification (Munro et al., 2011). Int J Gynecol Obstet.",
]
for r in refs:
story.append(Paragraph(f"• {r}", REF))
story.append(sp(1))
story.append(PageBreak())
# ──────────────────────────────────────────────────────────
# SLIDE 14 – CLOSING / QUESTIONS
# ──────────────────────────────────────────────────────────
class ClosingSlide(Flowable):
def wrap(self, availW, availH):
self.width = availW
return availW, 500
def draw(self):
c_obj = self.canv
w = self.width
c_obj.setFillColor(DEEP_PURPLE)
c_obj.roundRect(0, 0, w, 500, 10, fill=1, stroke=0)
c_obj.setFillColor(MED_PURPLE)
c_obj.roundRect(0, 0, 8, 500, 5, fill=1, stroke=0)
# decorative
c_obj.setFillColor(colors.HexColor("#8E44AD"))
c_obj.circle(w*0.85, 440, 70, fill=1, stroke=0)
c_obj.setFillColor(colors.HexColor("#5B2C6F"))
c_obj.circle(w*0.9, 80, 50, fill=1, stroke=0)
c_obj.setFont("Helvetica-Bold", 30)
c_obj.setFillColor(WHITE)
c_obj.drawCentredString(w/2, 400, "Questions & Discussion")
c_obj.setStrokeColor(LIGHT_PURPLE); c_obj.setLineWidth(1.5)
c_obj.line(w*0.2, 384, w*0.8, 384)
c_obj.setFont("Helvetica", 13)
c_obj.setFillColor(BLUSH)
c_obj.drawCentredString(w/2, 362, "Uterine Fibroids: Impact on Women's Health & QoL")
c_obj.setFont("Helvetica-Oblique", 10)
c_obj.drawCentredString(w/2, 344, "Grand Rounds | Department of Obstetrics & Gynecology")
c_obj.setFont("Helvetica-Bold", 11)
c_obj.setFillColor(LIGHT_PURPLE)
c_obj.drawCentredString(w/2, 300, "Discussion Points")
c_obj.setFont("Helvetica", 10)
c_obj.setFillColor(BLUSH)
points = [
"1. How do you currently counsel patients about UAE vs myomectomy?",
"2. What barriers exist to offering MIS to all patients in your institution?",
"3. When do you consider GnRH antagonists vs agonists in your practice?",
"4. How do you screen for and address the psychosocial burden of fibroids?",
]
y = 276
for p in points:
c_obj.drawCentredString(w/2, y, p)
y -= 22
c_obj.setFont("Helvetica", 8.5)
c_obj.setFillColor(LIGHT_PURPLE)
c_obj.drawCentredString(w/2, 60,
"Sources: Berek & Novak's Gynecology 16e | PubMed Literature 2021-2026 | AAGL Guidelines 2025")
story.append(ClosingSlide())
# ══════════════════════════════════════════════════════════
# PAGE NUMBER CALLBACK
# ══════════════════════════════════════════════════════════
def add_page_number(canvas, doc):
canvas.saveState()
canvas.setFont("Helvetica", 7.5)
canvas.setFillColor(MID_GRAY)
page = canvas.getPageNumber()
canvas.drawRightString(W - 2*cm, 1.2*cm, f"Uterine Fibroids & QoL | Page {page}")
canvas.restoreState()
doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print(f"PDF created: {OUTPUT}")
cd /home/daytona/workspace/fibroid-presentation && python build_pdf.py 2>&1