Why is tackycardia common in pregnacy
| Mechanism | Effect on Heart Rate |
|---|---|
| Low-resistance placenta + progesterone vasodilation | Reflex sympathetic tachycardia |
| Sympathetic nervous system activation | Direct increase via beta-1 receptors |
| 40% plasma volume expansion | Increased preload → increased CO demand |
| Higher metabolic demand (fetus + placenta) | Need for greater cardiac output |
| Progesterone on autonomic tone | Contributes to elevated baseline HR |
Create a clinical summary document on cardiovascular changes in pregnancy
mkdir -p /home/daytona/workspace/cv-pregnancy && ls /home/daytona/workspace/cv-p…
~/cv-pregnancy/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib.colors import HexColor, white, black
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.pdfgen import canvas
from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame
OUTPUT = "/home/daytona/workspace/cv-pregnancy/CV_Changes_in_Pregnancy.pdf"
# --- Colour palette ---
DEEP_BLUE = HexColor("#1B3A6B")
MID_BLUE = HexColor("#2E6DA4")
LIGHT_BLUE = HexColor("#D6E8F7")
ACCENT_TEAL = HexColor("#1A7F8E")
WARN_AMBER = HexColor("#D97706")
WARN_BG = HexColor("#FEF3C7")
TABLE_ALT = HexColor("#EAF4FB")
BORDER_GREY = HexColor("#CBD5E1")
BODY_GREY = HexColor("#374151")
LIGHT_GREY = HexColor("#F8FAFC")
W, H = A4
# ─── Page template with header / footer ─────────────────────────────────────
class HeaderFooterCanvas(canvas.Canvas):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._saved_page_states = []
def showPage(self):
self._saved_page_states.append(dict(self.__dict__))
self._startPage()
def save(self):
num_pages = len(self._saved_page_states)
for state in self._saved_page_states:
self.__dict__.update(state)
self.draw_header_footer(num_pages)
super().showPage()
super().save()
def draw_header_footer(self, page_count):
page_num = self._saved_page_states.index(dict(self.__dict__)) + 1 \
if dict(self.__dict__) in self._saved_page_states else self._pageNumber
# Header bar
self.setFillColor(DEEP_BLUE)
self.rect(0, H - 1.5*cm, W, 1.5*cm, fill=1, stroke=0)
self.setFillColor(white)
self.setFont("Helvetica-Bold", 11)
self.drawString(1.5*cm, H - 0.95*cm, "Cardiovascular Changes in Pregnancy")
self.setFont("Helvetica", 8)
self.drawRightString(W - 1.5*cm, H - 0.95*cm, "Clinical Summary for Medical Students")
# Accent line under header
self.setStrokeColor(ACCENT_TEAL)
self.setLineWidth(2)
self.line(0, H - 1.55*cm, W, H - 1.55*cm)
# Footer
self.setStrokeColor(BORDER_GREY)
self.setLineWidth(0.5)
self.line(1.2*cm, 1.3*cm, W - 1.2*cm, 1.3*cm)
self.setFillColor(BODY_GREY)
self.setFont("Helvetica", 7.5)
self.drawString(1.5*cm, 0.75*cm,
"Sources: Braunwald's Heart Disease | Fuster & Hurst's The Heart | Barash Clinical Anesthesia | Campbell Walsh Urology | Murray & Nadel's Respiratory Medicine")
self.drawRightString(W - 1.5*cm, 0.75*cm, f"Page {self._pageNumber} of {page_count}")
# ─── Build styles ─────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
title_style = ParagraphStyle(
"Title", fontName="Helvetica-Bold", fontSize=22,
textColor=white, alignment=TA_CENTER, spaceAfter=4
)
subtitle_style = ParagraphStyle(
"Subtitle", fontName="Helvetica", fontSize=11,
textColor=HexColor("#BFD9F0"), alignment=TA_CENTER, spaceAfter=0
)
h1_style = ParagraphStyle(
"H1", fontName="Helvetica-Bold", fontSize=13,
textColor=white, spaceAfter=6, spaceBefore=4,
leftIndent=0, borderPad=4
)
h2_style = ParagraphStyle(
"H2", fontName="Helvetica-Bold", fontSize=11,
textColor=DEEP_BLUE, spaceAfter=4, spaceBefore=10,
borderColor=DEEP_BLUE
)
body_style = ParagraphStyle(
"Body", fontName="Helvetica", fontSize=9.5,
textColor=BODY_GREY, leading=14, spaceAfter=5,
alignment=TA_JUSTIFY
)
bullet_style = ParagraphStyle(
"Bullet", fontName="Helvetica", fontSize=9.5,
textColor=BODY_GREY, leading=14, spaceAfter=3,
leftIndent=14, bulletIndent=4
)
small_style = ParagraphStyle(
"Small", fontName="Helvetica-Oblique", fontSize=8,
textColor=HexColor("#6B7280"), leading=11, spaceAfter=4,
alignment=TA_CENTER
)
callout_style = ParagraphStyle(
"Callout", fontName="Helvetica-Bold", fontSize=9.5,
textColor=HexColor("#92400E"), leading=13, spaceAfter=2
)
callout_body_style = ParagraphStyle(
"CalloutBody", fontName="Helvetica", fontSize=9,
textColor=HexColor("#78350F"), leading=13, spaceAfter=3,
leftIndent=8
)
warn_style = ParagraphStyle(
"Warn", fontName="Helvetica-Bold", fontSize=9.5,
textColor=HexColor("#991B1B"), leading=13, spaceAfter=2
)
# ─── Helper: section header band ──────────────────────────────────────────────
def section_header(text, color=DEEP_BLUE):
data = [[Paragraph(text, h1_style)]]
t = Table(data, colWidths=[W - 3.4*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), color),
("ROWBACKGROUNDS", (0, 0), (-1, -1), [color]),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
("LEFTPADDING", (0, 0), (-1, -1), 10),
("RIGHTPADDING", (0, 0), (-1, -1), 6),
("ROUNDEDCORNERS", [4, 4, 4, 4]),
]))
return t
def callout_box(title, items, bg=WARN_BG, border=WARN_AMBER):
content = [Paragraph(title, callout_style)]
for item in items:
content.append(Paragraph(f"• {item}", callout_body_style))
data = [[content]]
t = Table(data, colWidths=[W - 3.4*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), bg),
("BOX", (0, 0), (-1, -1), 1.5, border),
("LEFTPADDING", (0, 0), (-1, -1), 10),
("RIGHTPADDING", (0, 0), (-1, -1), 8),
("TOPPADDING", (0, 0), (-1, -1), 7),
("BOTTOMPADDING", (0, 0), (-1, -1), 7),
("ROUNDEDCORNERS", [4, 4, 4, 4]),
]))
return t
# ─── Document setup ───────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=1.7*cm, rightMargin=1.7*cm,
topMargin=2.2*cm, bottomMargin=1.8*cm,
title="Cardiovascular Changes in Pregnancy",
author="Orris Medical"
)
story = []
# ══════════════════════════════════════════════════════════════════════
# COVER / TITLE BLOCK
# ══════════════════════════════════════════════════════════════════════
cover_text = [
[Paragraph("Cardiovascular Changes in Pregnancy", title_style)],
[Paragraph("A Clinical Summary for Medical Students", subtitle_style)],
[Paragraph("July 2026 | Compiled from Braunwald's Heart Disease, Fuster & Hurst's The Heart,<br/>"
"Barash Clinical Anesthesia, Campbell Walsh Urology, Murray & Nadel's Respiratory Medicine",
small_style)]
]
cover = Table(cover_text, colWidths=[W - 3.4*cm])
cover.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, -1), DEEP_BLUE),
("TOPPADDING", (0, 0), (-1, 0), 20),
("BOTTOMPADDING", (0, 0), (-1, 0), 4),
("TOPPADDING", (0, 1), (-1, 1), 2),
("BOTTOMPADDING", (0, 1), (-1, 1), 4),
("TOPPADDING", (0, 2), (-1, 2), 6),
("BOTTOMPADDING", (0, 2), (-1, 2), 20),
("LEFTPADDING", (0, 0), (-1, -1), 16),
("RIGHTPADDING", (0, 0), (-1, -1), 16),
]))
story.append(cover)
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 1. OVERVIEW
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("1. Overview"))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"Pregnancy induces profound but reversible cardiovascular adaptations that begin as early as "
"<b>6 weeks of gestation</b> and reach their peak around <b>25-32 weeks</b>. These changes are "
"designed to meet the increased metabolic demands of the mother, fetus, and placenta. "
"In women with normal hearts they are well tolerated; however, in women with pre-existing heart "
"disease they can precipitate decompensation and cardiac complications.",
body_style
))
story.append(Spacer(1, 0.3*cm))
# ══════════════════════════════════════════════════════════════════════
# 2. KEY HAEMODYNAMIC CHANGES TABLE
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("2. Key Haemodynamic Changes at a Glance", color=MID_BLUE))
story.append(Spacer(1, 0.2*cm))
hd_headers = ["Parameter", "Change", "Magnitude / Timing", "Clinical Significance"]
hd_data = [
hd_headers,
["Heart Rate (HR)", "↑ Increase", "+10-20 bpm; peaks ~20 wks", "Physiological tachycardia; worsens mitral stenosis"],
["Stroke Volume (SV)", "↑ Increase", "+20-50%", "Main driver of CO rise in early pregnancy"],
["Cardiac Output (CO)", "↑ Increase", "+30-50%; peaks 25-32 wks", "Further ↑ 60-80% during labour"],
["Systemic Vascular\nResistance (SVR)", "↓ Decrease", "-20-50%; from 8 wks", "Driven by progesterone, prostacyclin, placenta"],
["Blood Pressure (BP)", "↓ then normal", "Falls 5-10 mmHg; returns\nto baseline in 3rd trimester", "Widened pulse pressure; postural hypotension risk"],
["Plasma Volume", "↑ Increase", "+40-50% (~2 L)", "Physiological anaemia; dilutional effect"],
["Red Cell Mass", "↑ Increase", "+20-30%", "Less than plasma rise → Hb may fall to 11 g/dL"],
["Pulmonary Vascular\nResistance (PVR)", "↓ Decrease", "Parallel to SVR", "Risk if pre-existing pulmonary hypertension"],
["CVP / PCWP", "Unchanged", "Stable throughout", "Reflects ↑ LV compliance"],
["Uterine Blood Flow", "↑ Increase", "50-100 → 700-900 mL/min\nby term", "Vital for fetal oxygenation"],
["Renal Blood Flow", "↑ Increase", "+60%; GFR +40-50%", "Adjust drug doses; ↑ creatinine clearance"],
]
col_widths = [3.5*cm, 2.3*cm, 4.7*cm, 6.2*cm]
hd_table = Table(hd_data, colWidths=col_widths, repeatRows=1)
hd_style = TableStyle([
# Header row
("BACKGROUND", (0, 0), (-1, 0), DEEP_BLUE),
("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"),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
# Alternating rows
("ROWBACKGROUNDS", (0, 1), (-1, -1), [white, TABLE_ALT]),
("FONTNAME", (0, 1), (-1, -1), "Helvetica"),
("FONTSIZE", (0, 1), (-1, -1), 8.5),
("TEXTCOLOR", (0, 1), (-1, -1), BODY_GREY),
# Highlight change column
("FONTNAME", (1, 1), (1, -1), "Helvetica-Bold"),
# Grid
("GRID", (0, 0), (-1, -1), 0.4, BORDER_GREY),
("LINEBELOW", (0, 0), (-1, 0), 1.5, white),
# Padding
("TOPPADDING", (0, 0), (-1, -1), 5),
("BOTTOMPADDING", (0, 0), (-1, -1), 5),
("LEFTPADDING", (0, 0), (-1, -1), 6),
("RIGHTPADDING", (0, 0), (-1, -1), 6),
])
hd_table.setStyle(hd_style)
story.append(hd_table)
story.append(Paragraph(
"CO = cardiac output; CVP = central venous pressure; GFR = glomerular filtration rate; "
"LV = left ventricle; PCWP = pulmonary capillary wedge pressure; SVR = systemic vascular resistance.",
small_style
))
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 3. MECHANISMS
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("3. Mechanisms Driving Cardiovascular Adaptation"))
story.append(Spacer(1, 0.2*cm))
mech_data = [
["Mechanism", "Details"],
["Low-resistance placenta",
"Placenta acts as an arteriovenous shunt, reducing SVR from early gestation before "
"uteroplacental circulation is fully established."],
["Progesterone & prostacyclin",
"Smooth muscle relaxation causes widespread peripheral vasodilation, reducing SVR "
"by 20-50%. Progesterone also drives minute ventilation (dyspnoea of pregnancy)."],
["Renin-Angiotensin-\nAldosterone System",
"Activated early in pregnancy, promoting sodium and water retention, expanding plasma "
"volume by ~2 L (40-50%)."],
["Sympathetic activation",
"Reflex response to reduced SVR. Up to a 30% increase in heart rate via beta-1 "
"adrenoceptors, peaking around 20 weeks' gestation."],
["Frank-Starling mechanism",
"Expanded blood volume stretches ventricular walls, increasing stroke volume by 20-50%. "
"Left ventricular end-diastolic volume is increased; ejection fraction is little changed."],
["Relaxin & oestrogen",
"Relaxin promotes vasodilation and increases glomerular filtration. Oestrogen, volume "
"overload, and increased cardiac demand cause reversible LV hypertrophy (~50% increase "
"in mass at term) and mild diastolic dysfunction."],
]
mech_col_widths = [4.2*cm, 12.5*cm]
mech_table = Table(mech_data, colWidths=mech_col_widths, repeatRows=1)
mech_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), ACCENT_TEAL),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 9),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [white, TABLE_ALT]),
("FONTNAME", (0, 1), (0, -1), "Helvetica-Bold"),
("FONTSIZE", (0, 1), (-1, -1), 8.5),
("TEXTCOLOR", (0, 1), (-1, -1), BODY_GREY),
("TEXTCOLOR", (0, 1), (0, -1), DEEP_BLUE),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("GRID", (0, 0), (-1, -1), 0.4, BORDER_GREY),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
("LEFTPADDING", (0, 0), (-1, -1), 7),
("RIGHTPADDING", (0, 0), (-1, -1), 7),
]))
story.append(mech_table)
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 4. TRIMESTER-BY-TRIMESTER
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("4. Trimester-by-Trimester Timeline", color=MID_BLUE))
story.append(Spacer(1, 0.2*cm))
tri_data = [
["Stage", "Key Cardiovascular Events"],
["Weeks 6-12\n(1st Trimester)",
"• Plasma volume begins to expand\n"
"• SVR starts to fall (progesterone, prostacyclin)\n"
"• Heart rate starts rising\n"
"• CO begins to increase; BP falls 5-10 mmHg\n"
"• Early LV remodelling begins"],
["Weeks 13-28\n(2nd Trimester)",
"• CO peaks progressively toward 25-32 wks (+30-50%)\n"
"• HR increase peaks ~20 wks (+10-20 bpm)\n"
"• BP nadir (lowest point)\n"
"• Plasma volume expansion maximal (~32 wks)\n"
"• Physiological anaemia most evident at 32-34 wks\n"
"• LV mass increases ~50%; mild diastolic dysfunction"],
["Weeks 29-40\n(3rd Trimester)",
"• BP gradually returns toward pre-pregnancy baseline\n"
"• SVR begins to recover slightly\n"
"• Gravid uterus compresses IVC in supine position\n"
" → Supine hypotensive syndrome (venous return ↓, CO ↓ 25%)\n"
"• Uterine blood flow reaches 700-900 mL/min at term"],
["Labour &\nDelivery",
"• CO rises a further 60-80% during active labour\n"
"• Each uterine contraction autotransfuses 300-500 mL\n"
"• Catecholamines from pain/anxiety increase HR and BP\n"
"• Immediately postpartum: IVC compression relieved → surge in venous return"],
["Postpartum\n(0-6 months)",
"• Haemodynamic changes resolve within 2 weeks\n"
"• Complete normalisation may take up to 6 months\n"
"• Risk of heart failure in first week (fluid mobilisation)\n"
"• Plasma volume falls sharply after delivery"],
]
tri_col_widths = [3.5*cm, 13.2*cm]
tri_table = Table(tri_data, colWidths=tri_col_widths, repeatRows=1)
tri_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), DEEP_BLUE),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 9),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [white, TABLE_ALT]),
("FONTNAME", (0, 1), (0, -1), "Helvetica-Bold"),
("FONTSIZE", (0, 1), (-1, -1), 8.5),
("TEXTCOLOR", (0, 1), (0, -1), ACCENT_TEAL),
("TEXTCOLOR", (1, 1), (1, -1), BODY_GREY),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("ALIGN", (0, 0), (0, -1), "CENTER"),
("GRID", (0, 0), (-1, -1), 0.4, BORDER_GREY),
("TOPPADDING", (0, 0), (-1, -1), 7),
("BOTTOMPADDING", (0, 0), (-1, -1), 7),
("LEFTPADDING", (0, 0), (-1, -1), 7),
("RIGHTPADDING", (0, 0), (-1, -1), 7),
]))
story.append(tri_table)
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 5. CARDIAC EXAMINATION IN NORMAL PREGNANCY
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("5. Cardiac Examination Findings in Normal Pregnancy"))
story.append(Spacer(1, 0.2*cm))
exam_data = [
["Finding", "Expected (Normal)", "Abnormal - Warrants Investigation"],
["Symptoms", "Fatigue, dyspnoea on exertion, palpitations,\nlight-headedness, ankle oedema (mild)",
"Angina, resting dyspnoea, PND, syncope,\nsustained palpitations"],
["Vital signs", "HR ↑ 10-20 bpm above baseline;\nBP slightly reduced; widened pulse pressure",
"HR >120 at rest; BP ≥140/90 mmHg\n(hypertensive disorder)"],
["Pulse", "Collapsing (bounding) arterial pulse", "Irregularly irregular (AF)"],
["JVP", "Prominent pulsations; pressure NOT elevated", "Elevated JVP (heart failure)"],
["Apex beat", "Laterally displaced; palpable RV or pulmonary trunk", "Heaving apex (LV hypertrophy)"],
["Murmurs", "Soft systolic ejection murmur (pulmonic area /\nleft sternal border) - flow murmur\n"
"Mammary souffle (benign, 3rd trimester)",
"Holosystolic murmur, diastolic murmur,\nexaggerated S2 (pulmonary HTN), S4"],
["Heart sounds", "S3 may be physiological", "S4 always abnormal"],
["ECG", "Sinus tachycardia; left axis deviation;\nshortened PR; Q waves in inferior leads;\nnonspecific ST-T changes; ectopics common",
"Sustained arrhythmia; bundle branch block;\nsigns of ischaemia"],
["Echocardiogram", "↑ LV dimensions; ↑ LV mass; mild\ndiastolic dysfunction; mild MR/TR normal",
"Systolic dysfunction; severe valvular disease;\ndilated RV; pericardial effusion"],
]
exam_col_widths = [3.2*cm, 7.3*cm, 6.2*cm]
exam_table = Table(exam_data, colWidths=exam_col_widths, repeatRows=1)
exam_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), ACCENT_TEAL),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 9),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [white, TABLE_ALT]),
("FONTNAME", (0, 1), (0, -1), "Helvetica-Bold"),
("FONTSIZE", (0, 1), (-1, -1), 8),
("TEXTCOLOR", (0, 1), (0, -1), DEEP_BLUE),
("TEXTCOLOR", (1, 1), (1, -1), BODY_GREY),
# Red text for abnormal column
("TEXTCOLOR", (2, 1), (2, -1), HexColor("#991B1B")),
("FONTNAME", (2, 1), (2, -1), "Helvetica-Oblique"),
("BACKGROUND", (2, 0), (2, 0), HexColor("#991B1B")),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("GRID", (0, 0), (-1, -1), 0.4, BORDER_GREY),
("TOPPADDING", (0, 0), (-1, -1), 5),
("BOTTOMPADDING", (0, 0), (-1, -1), 5),
("LEFTPADDING", (0, 0), (-1, -1), 6),
("RIGHTPADDING", (0, 0), (-1, -1), 6),
]))
story.append(exam_table)
story.append(Paragraph(
"AF = atrial fibrillation; HTN = hypertension; JVP = jugular venous pressure; LV = left ventricle; "
"MR = mitral regurgitation; PND = paroxysmal nocturnal dyspnoea; RV = right ventricle; TR = tricuspid regurgitation.",
small_style
))
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 6. SYSTEMIC CHANGES BEYOND THE HEART
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("6. Systemic Changes: Beyond the Heart", color=MID_BLUE))
story.append(Spacer(1, 0.2*cm))
sys_data = [
["System", "Change", "Key Implications"],
["Haematology",
"Plasma volume +50%; RBC mass +20-30%\nPhysiological anaemia (Hb may fall to 11 g/dL)\nCoagulation factors ↑; Protein S ↓; fibrinolysis ↓",
"Increased VTE risk\nAnaemia worsens high-output state\nFibrinogen ↑ 400-500 mg/dL (postpartum\nhaemorrhage predictor)"],
["Renal",
"Renal blood flow +60%; GFR +40-50%\nProteinuria mildly ↑; uric acid clearance ↑",
"Drug dosing adjustment needed\n↑ Proteinuria in preeclampsia\nNormal creatinine may be lower than expected"],
["Respiratory",
"Tidal volume +50% (progesterone)\nMinute ventilation ↑; FRC ↓\nMild respiratory alkalosis (PaCO2 ~30 mmHg)",
"Rapid desaturation during intubation\nDyspnoea common (normal)\nDifficult airway in late pregnancy"],
["Lipid / Metabolic",
"Triglycerides ↑; total cholesterol +50%\nInsulin resistance ↑; diabetogenic state",
"Gestational diabetes risk\nExisting dyslipidaemia → adverse outcomes"],
["Coagulation",
"Procoagulant state (↑ factors II, VII, X, XII;\n↑ fibrinogen; ↓ protein S; ↓ fibrinolysis)",
"DVT / PE risk especially with:\n- Prosthetic heart valves\n- Atrial fibrillation\n- Fontan circulation"],
]
sys_col_widths = [3.0*cm, 7.5*cm, 6.2*cm]
sys_table = Table(sys_data, colWidths=sys_col_widths, repeatRows=1)
sys_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), DEEP_BLUE),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 9),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [white, TABLE_ALT]),
("FONTNAME", (0, 1), (0, -1), "Helvetica-Bold"),
("FONTSIZE", (0, 1), (-1, -1), 8),
("TEXTCOLOR", (0, 1), (0, -1), ACCENT_TEAL),
("TEXTCOLOR", (1, 1), (-1, -1), BODY_GREY),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("GRID", (0, 0), (-1, -1), 0.4, BORDER_GREY),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
("LEFTPADDING", (0, 0), (-1, -1), 7),
("RIGHTPADDING", (0, 0), (-1, -1), 7),
]))
story.append(sys_table)
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 7. CLINICAL IMPLICATIONS / HIGH-RISK CONDITIONS
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("7. Clinical Implications - High-Risk Cardiac Conditions"))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"Pre-existing cardiac disease is the leading cause of indirect maternal death in developed countries. "
"Pregnancy amplifies haemodynamic stress, making certain conditions particularly dangerous.",
body_style
))
story.append(Spacer(1, 0.2*cm))
risk_data = [
["Condition", "Why Pregnancy is Dangerous", "Risk Category"],
["Mitral Stenosis",
"Fixed obstruction cannot accommodate ↑ CO and HR\n"
"↑ Transmitral gradient → pulmonary oedema, tachyarrhythmias",
"HIGH"],
["Pulmonary Hypertension\n(incl. Eisenmenger's)",
"Fixed PVR cannot accommodate ↑ CO\nSVR fall → ↑ R→L shunt; systemic hypoxaemia\nMortality 25-50%",
"VERY HIGH\n(Contraindicated)"],
["Peripartum\nCardiomyopathy",
"New-onset LV systolic dysfunction in last month of\npregnancy or within 5 months postpartum\nMortality 6-10%",
"HIGH"],
["Hypertrophic\nCardiomyopathy",
"Outflow obstruction worsened by SVR drop\nVentricular arrhythmia risk ↑",
"MODERATE-HIGH"],
["Aortic Stenosis\n(severe)",
"Fixed obstruction cannot accommodate ↑ SV demand\nLV failure risk; syncope; sudden death",
"HIGH"],
["Fontan Circulation",
"Single-ventricle physiology has limited haemodynamic\nreserve; ↑ thromboembolic risk; fetal loss common",
"HIGH"],
["Prosthetic Heart\nValves",
"Anticoagulation management complex during pregnancy\n↑ Valve thrombosis risk with mechanical valves",
"HIGH"],
["Hypertensive\nDisorders",
"Chronic HTN, gestational HTN, preeclampsia, eclampsia\n↑ MAP + SVR in preeclampsia (opposite of normal adaptation)",
"MODERATE-HIGH"],
]
risk_col_widths = [3.6*cm, 9.8*cm, 3.3*cm]
risk_table = Table(risk_data, colWidths=risk_col_widths, repeatRows=1)
risk_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), DEEP_BLUE),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 9),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [white, TABLE_ALT]),
("FONTNAME", (0, 1), (0, -1), "Helvetica-Bold"),
("FONTSIZE", (0, 1), (-1, -1), 8),
("TEXTCOLOR", (0, 1), (0, -1), DEEP_BLUE),
("TEXTCOLOR", (1, 1), (1, -1), BODY_GREY),
("TEXTCOLOR", (2, 1), (2, -1), HexColor("#991B1B")),
("FONTNAME", (2, 1), (2, -1), "Helvetica-Bold"),
("ALIGN", (2, 0), (2, -1), "CENTER"),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("GRID", (0, 0), (-1, -1), 0.4, BORDER_GREY),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
("LEFTPADDING", (0, 0), (-1, -1), 7),
("RIGHTPADDING", (0, 0), (-1, -1), 7),
]))
story.append(risk_table)
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 8. SUPINE HYPOTENSIVE SYNDROME
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("8. Supine Hypotensive Syndrome (Aortocaval Compression)", color=MID_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"After ~20 weeks, the gravid uterus can nearly completely compress the inferior vena cava (IVC) "
"when a woman lies supine. This reduces venous return, dropping preload and causing:",
body_style
))
supcols = ["Effect", "Consequence"]
supdata = [
supcols,
["IVC compression → ↓ venous return", "↓ Preload → ↓ Stroke Volume"],
["↓ Stroke Volume", "CO falls by up to 25-30%"],
["Baroreceptor reflex", "Compensatory tachycardia"],
["Hypotension", "Nausea, dizziness, altered mental status"],
["↓ Uterine perfusion", "Fetal distress / bradycardia"],
["Anaesthesia impairs sympathetic compensation", "Severe hypotension, cardiovascular collapse"],
]
suptable = Table(supdata, colWidths=[8.35*cm, 8.35*cm], repeatRows=1)
suptable.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), ACCENT_TEAL),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 9),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [white, TABLE_ALT]),
("FONTSIZE", (0, 1), (-1, -1), 8.5),
("FONTNAME", (0, 1), (0, -1), "Helvetica-Bold"),
("TEXTCOLOR", (0, 1), (0, -1), DEEP_BLUE),
("TEXTCOLOR", (1, 1), (-1, -1), BODY_GREY),
("GRID", (0, 0), (-1, -1), 0.4, BORDER_GREY),
("TOPPADDING", (0, 0), (-1, -1), 5),
("BOTTOMPADDING", (0, 0), (-1, -1), 5),
("LEFTPADDING", (0, 0), (-1, -1), 7),
("RIGHTPADDING", (0, 0), (-1, -1), 7),
]))
story.append(suptable)
story.append(Spacer(1, 0.15*cm))
story.append(callout_box(
"Management of Supine Hypotension",
[
"Position: Left lateral decubitus OR 15-20 degree left lateral tilt with wedge after 20 weeks",
"During surgery: aggressive IV fluid preloading; vasopressors (phenylephrine preferred) ready",
"Avoid supine and lithotomy positions where possible in late pregnancy",
"Monitor fetal heart rate intraoperatively",
],
bg=LIGHT_BLUE, border=MID_BLUE
))
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 9. RED FLAGS / WHEN TO INVESTIGATE
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("9. Red Flag Symptoms - When to Investigate"))
story.append(Spacer(1, 0.2*cm))
story.append(callout_box(
"Symptoms that are NORMAL in Pregnancy (no investigation needed if mild, <20 wks):",
[
"Dyspnoea on exertion",
"Fatigue, light-headedness",
"Palpitations (especially ectopics)",
"Mild ankle oedema",
"Soft systolic ejection murmur",
],
bg=HexColor("#F0FFF4"), border=HexColor("#16A34A")
))
story.append(Spacer(1, 0.2*cm))
story.append(callout_box(
"RED FLAG Symptoms - Prompt Cardiology Referral / Investigation:",
[
"Angina or chest pain at rest",
"Significant resting dyspnoea or paroxysmal nocturnal dyspnoea (PND)",
"Syncope or pre-syncope (especially exertional)",
"Sustained palpitations or documented arrhythmia",
"Symptoms arising after 20 weeks that are progressive or disabling",
"Any diastolic murmur or new holosystolic murmur",
"Exaggerated S2 (pulmonary hypertension)",
"Cyanosis",
],
bg=WARN_BG, border=WARN_AMBER
))
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 10. INVESTIGATION GUIDE
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("10. Investigations in Pregnancy", color=MID_BLUE))
story.append(Spacer(1, 0.2*cm))
inv_data = [
["Investigation", "Use in Pregnancy", "Notes"],
["ECG", "Safe; first-line for arrhythmia, ischaemia\nNormal changes: see Section 5", "Sinus tachycardia and ectopics common; LAD normal"],
["Echocardiogram (TTE)", "Safe; preferred imaging modality\nFor unexplained symptoms, murmurs, known CVD", "LV dilation and mild MR/TR normal findings"],
["Chest X-Ray", "Safe with abdominal shielding\nUse for pulmonary oedema, cardiomegaly", "Cardiac silhouette normally enlarged"],
["BNP / NT-proBNP", "BNP >111 pg/mL: LR+ 2.5 for heart failure\nBNP <100 pg/mL: 100% NPV for complications\n(in known heart disease group)", "Levels rise in pregnancy; interpret cautiously"],
["Holter Monitor", "Safe; for palpitations and arrhythmia documentation", "Ectopics very common; not necessarily abnormal"],
["MRI (non-contrast)", "Considered safe; no gadolinium\nUseful for aortic/complex CHD assessment", "Avoid gadolinium contrast (teratogenic concern)"],
["Cardiac CT", "High radiation dose; avoid if possible\nCan be used for coronary artery disease if critical", "Use only when other modalities inadequate"],
["Exercise Stress Test", "Safe up to moderate intensity\nUseful pre-pregnancy risk stratification", "Abnormal chronotropic response predicts complications"],
]
inv_col_widths = [3.4*cm, 8.0*cm, 5.3*cm]
inv_table = Table(inv_data, colWidths=inv_col_widths, repeatRows=1)
inv_table.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), DEEP_BLUE),
("TEXTCOLOR", (0, 0), (-1, 0), white),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 9),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [white, TABLE_ALT]),
("FONTNAME", (0, 1), (0, -1), "Helvetica-Bold"),
("FONTSIZE", (0, 1), (-1, -1), 8),
("TEXTCOLOR", (0, 1), (0, -1), DEEP_BLUE),
("TEXTCOLOR", (1, 1), (-1, -1), BODY_GREY),
("VALIGN", (0, 0), (-1, -1), "TOP"),
("GRID", (0, 0), (-1, -1), 0.4, BORDER_GREY),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
("LEFTPADDING", (0, 0), (-1, -1), 7),
("RIGHTPADDING", (0, 0), (-1, -1), 7),
]))
story.append(inv_table)
story.append(Spacer(1, 0.4*cm))
# ══════════════════════════════════════════════════════════════════════
# 11. QUICK-REFERENCE SUMMARY
# ══════════════════════════════════════════════════════════════════════
story.append(section_header("11. Quick-Reference Summary Card"))
story.append(Spacer(1, 0.2*cm))
summary_items = [
["Key Numbers to Know", [
"Cardiac output: ↑ 30-50% (peaks 25-32 wks); ↑ further 60-80% during labour",
"Heart rate: ↑ 10-20 bpm above baseline (peaks ~20 wks)",
"Stroke volume: ↑ 20-50%",
"SVR: ↓ 20-50% (key trigger for all other changes)",
"Plasma volume: ↑ 40-50% (~2 L)",
"Normal Hb in pregnancy: ≥ 11 g/dL (physiological anaemia)",
"Uterine blood flow at term: 700-900 mL/min",
"CO drop supine at term: up to 25-30%",
]],
["Cardinal Physiological Principle", [
"SVR falls first (vasodilation from progesterone/placenta) → BP drops → sympathetic activation "
"→ HR and SV rise → CO rises 30-50%. Plasma volume expands to fill the enlarged vascular bed.",
]],
["Highest Risk Conditions", [
"Eisenmenger's syndrome / pulmonary hypertension (mortality 25-50%)",
"Mitral stenosis (class III/IV)",
"Peripartum cardiomyopathy",
"Severe aortic stenosis",
"Fontan circulation",
]],
]
for item in summary_items:
title, bullets = item
story.append(callout_box(title, bullets, bg=LIGHT_BLUE, border=MID_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(Spacer(1, 0.3*cm))
story.append(HRFlowable(width="100%", thickness=1, color=BORDER_GREY))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph(
"This document is a clinical summary for educational purposes. Always refer to current national and "
"institutional guidelines for clinical decision-making. Sources: Braunwald's Heart Disease (2022), "
"Fuster & Hurst's The Heart 15th Ed, Barash Clinical Anesthesia 9th Ed, "
"Campbell Walsh Wein Urology, Murray & Nadel's Respiratory Medicine.",
small_style
))
# ─── Build ────────────────────────────────────────────────────────────────────
doc.build(story, canvasmaker=HeaderFooterCanvas)
print(f"PDF saved to: {OUTPUT}")
cd /home/daytona/workspace/cv-pregnancy && python generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/cv-pregnancy/CV_Changes_in_Pregnancy.pdf
CV Changes in Pregnancy
PDF Document · PDF
| Section | Content |
|---|---|
| 1. Overview | Introduction to when changes begin and why they matter |
| 2. Key Haemodynamic Changes | Full colour-coded table - HR, CO, SV, SVR, BP, plasma volume, renal flow, etc. with magnitudes and timings |
| 3. Mechanisms | Why each change happens - progesterone, placenta, RAAS, Frank-Starling, sympathetics, relaxin |
| 4. Trimester-by-Trimester | Timeline from 6 weeks through labour to 6 months postpartum |
| 5. Cardiac Exam Findings | Normal vs. abnormal - symptoms, pulse, murmurs, ECG, echo |
| 6. Systemic Changes | Haematology, renal, respiratory, coagulation, metabolic |
| 7. High-Risk Cardiac Conditions | Mitral stenosis, pulmonary HTN, peripartum CMP, Fontan, prosthetic valves |
| 8. Supine Hypotensive Syndrome | Aortocaval compression mechanism + management box |
| 9. Red Flag Symptoms | Colour-coded callout boxes: normal vs. refer urgently |
| 10. Investigations | ECG, echo, BNP, MRI, CT - safety and interpretation in pregnancy |
| 11. Quick-Reference Card | Key numbers, cardinal principle, highest-risk conditions |