Physiology exam oreinted notes
mkdir -p /home/daytona/workspace/physiology-notes && ls /home/daytona/workspace/…
Are you creating a file
~/physiology-notes/cvs_physiology_notes.py
#!/usr/bin/env python3
"""Generate Cardiovascular Physiology Exam Notes PDF using ReportLab."""
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
import os
OUTPUT = "/home/daytona/workspace/physiology-notes/CVS_Physiology_ExamNotes.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE = colors.HexColor("#1A3A5C")
MID_BLUE = colors.HexColor("#2E6DA4")
LIGHT_BLUE = colors.HexColor("#D6E8F7")
TEAL = colors.HexColor("#0E7C7B")
AMBER = colors.HexColor("#F5A623")
AMBER_LIGHT = colors.HexColor("#FFF3CD")
RED_LIGHT = colors.HexColor("#FDECEA")
RED_DARK = colors.HexColor("#C0392B")
GREEN_LIGHT = colors.HexColor("#EAF7EA")
GREEN_DARK = colors.HexColor("#1E8449")
GREY_LIGHT = colors.HexColor("#F4F6F8")
GREY_MED = colors.HexColor("#BDC3C7")
WHITE = colors.white
BLACK = colors.black
# ── Styles ──────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
COVER_TITLE = S("CoverTitle", fontSize=34, textColor=WHITE, alignment=TA_CENTER,
fontName="Helvetica-Bold", leading=42, spaceAfter=8)
COVER_SUB = S("CoverSub", fontSize=18, textColor=colors.HexColor("#A8D4F5"),
alignment=TA_CENTER, fontName="Helvetica", leading=26, spaceAfter=4)
COVER_INFO = S("CoverInfo", fontSize=11, textColor=colors.HexColor("#D0E8F7"),
alignment=TA_CENTER, fontName="Helvetica", leading=16)
H1 = S("H1", fontSize=18, textColor=WHITE, fontName="Helvetica-Bold",
leading=24, spaceAfter=2, spaceBefore=6)
H2 = S("H2", fontSize=13, textColor=DARK_BLUE, fontName="Helvetica-Bold",
leading=18, spaceBefore=10, spaceAfter=4,
borderPad=4)
H3 = S("H3", fontSize=11, textColor=TEAL, fontName="Helvetica-Bold",
leading=15, spaceBefore=6, spaceAfter=3)
BODY = S("Body", fontSize=9.5, textColor=colors.HexColor("#2C3E50"),
fontName="Helvetica", leading=14, spaceAfter=3, alignment=TA_JUSTIFY)
BULLET = S("Bullet", fontSize=9.5, textColor=colors.HexColor("#2C3E50"),
fontName="Helvetica", leading=14, leftIndent=14, spaceAfter=2,
bulletIndent=4)
BULLET2 = S("Bullet2", fontSize=9, textColor=colors.HexColor("#34495E"),
fontName="Helvetica", leading=13, leftIndent=26, spaceAfter=1,
bulletIndent=16)
KEY = S("Key", fontSize=9.5, textColor=colors.HexColor("#1A3A5C"),
fontName="Helvetica-Bold", leading=14, spaceAfter=2)
FORMULA = S("Formula", fontSize=10, textColor=DARK_BLUE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=14, spaceBefore=4, spaceAfter=4,
backColor=LIGHT_BLUE, borderPad=6)
MNEMONIC = S("Mnemonic", fontSize=9.5, textColor=GREEN_DARK,
fontName="Helvetica-BoldOblique", leading=14, spaceAfter=2,
backColor=GREEN_LIGHT, leftIndent=8, borderPad=4)
CLINICAL = S("Clinical", fontSize=9, textColor=RED_DARK,
fontName="Helvetica", leading=13, spaceAfter=2,
backColor=RED_LIGHT, leftIndent=8, borderPad=4)
NOTE = S("Note", fontSize=9, textColor=colors.HexColor("#7F6000"),
fontName="Helvetica-Oblique", leading=13, spaceAfter=2,
backColor=AMBER_LIGHT, leftIndent=8, borderPad=4)
TABLE_HDR = S("TH", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=12)
TABLE_CELL = S("TC", fontSize=8.5, textColor=BLACK, fontName="Helvetica",
alignment=TA_LEFT, leading=12)
TABLE_CELL_C = S("TCC", fontSize=8.5, textColor=BLACK, fontName="Helvetica",
alignment=TA_CENTER, leading=12)
FOOTER_S = S("Footer", fontSize=8, textColor=GREY_MED, alignment=TA_CENTER,
fontName="Helvetica")
# ── Helpers ─────────────────────────────────────────────────────────────────
def section_header(title, color=DARK_BLUE):
"""Full-width blue bar for section heading."""
return Table(
[[Paragraph(title, H1)]],
colWidths=[17*cm],
style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("ROUNDEDCORNERS", [4]),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 12),
])
)
def info_box(paragraphs, bg=AMBER_LIGHT, border=AMBER):
rows = [[p] for p in paragraphs]
t = Table(rows, colWidths=[16.6*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING",(0,0), (-1,-1), 10),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LINEAFTER", (0,0), (0,-1), 2, border),
]))
return t
def two_col(left_items, right_items, widths=(8.3*cm, 8.3*cm)):
rows = []
maxr = max(len(left_items), len(right_items))
for i in range(maxr):
l = left_items[i] if i < len(left_items) else Paragraph("", BODY)
r = right_items[i] if i < len(right_items) else Paragraph("", BODY)
rows.append([l, r])
t = Table(rows, colWidths=list(widths))
t.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING",(0,0),(-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 4),
]))
return t
def styled_table(headers, rows, col_widths):
data = [[Paragraph(h, TABLE_HDR) for h in headers]]
for r in rows:
data.append([Paragraph(str(c), TABLE_CELL) for c in r])
t = Table(data, colWidths=col_widths)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), MID_BLUE),
("BACKGROUND", (0,1), (-1,-1), GREY_LIGHT),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GREY_LIGHT]),
("GRID", (0,0), (-1,-1), 0.4, GREY_MED),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
return t
def hr(): return HRFlowable(width="100%", thickness=0.5, color=GREY_MED, spaceAfter=4, spaceBefore=4)
def sp(h=6): return Spacer(1, h)
def b(text): return Paragraph(f"• {text}", BULLET)
def b2(text): return Paragraph(f"◦ {text}", BULLET2)
def p(text): return Paragraph(text, BODY)
def h2(text): return Paragraph(text, H2)
def h3(text): return Paragraph(text, H3)
def key(text): return Paragraph(text, KEY)
def formula(text): return Paragraph(text, FORMULA)
def mnemonic(text): return Paragraph(f"🧠 {text}", MNEMONIC)
def clinical(text): return Paragraph(f"🩺 {text}", CLINICAL)
def note(text): return Paragraph(f"📌 {text}", NOTE)
# ── Page template with header/footer ────────────────────────────────────────
def on_page(canvas, doc):
canvas.saveState()
w, h = A4
# Top bar
canvas.setFillColor(DARK_BLUE)
canvas.rect(0, h-28, w, 28, fill=1, stroke=0)
canvas.setFont("Helvetica-Bold", 9)
canvas.setFillColor(WHITE)
canvas.drawString(1.5*cm, h-18, "CARDIOVASCULAR PHYSIOLOGY — EXAM NOTES")
canvas.drawRightString(w-1.5*cm, h-18, "Orris Medical")
# Bottom
canvas.setFillColor(GREY_MED)
canvas.setFont("Helvetica", 8)
canvas.drawCentredString(w/2, 0.6*cm, f"Page {doc.page}")
canvas.restoreState()
# ── Build content ────────────────────────────────────────────────────────────
story = []
# ════════════════════════════════════════════════════════════════════
# COVER PAGE
# ════════════════════════════════════════════════════════════════════
cover_bg = Table(
[[
Paragraph("❤", ParagraphStyle("icon", fontSize=60, textColor=colors.HexColor("#A8D4F5"),
alignment=TA_CENTER, leading=70)),
Spacer(1,8),
Paragraph("CARDIOVASCULAR<br/>PHYSIOLOGY", COVER_TITLE),
Paragraph("Exam-Oriented Study Notes", COVER_SUB),
Spacer(1,16),
Paragraph("MBBS / USMLE Step 1 Level", COVER_INFO),
Paragraph("Based on: Guyton & Hall · Costanzo · Ganong's · Goldman-Cecil", COVER_INFO),
Spacer(1,8),
Paragraph("Orris Medical — May 2026", COVER_INFO),
]],
colWidths=[17*cm],
rowHeights=[None],
style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 70),
("BOTTOMPADDING", (0,0), (-1,-1), 70),
("LEFTPADDING", (0,0), (-1,-1), 30),
("RIGHTPADDING", (0,0), (-1,-1), 30),
])
)
story.append(cover_bg)
story.append(PageBreak())
# ════════════════════════════════════════════════════════════════════
# SECTION 1 — CARDIAC ELECTROPHYSIOLOGY
# ════════════════════════════════════════════════════════════════════
story += [
section_header("1. CARDIAC ELECTROPHYSIOLOGY"),
sp(10),
h2("1.1 Resting Membrane Potential"),
p("Cardiac cells maintain a resting membrane potential (RMP) of approximately <b>−85 to −90 mV</b> (ventricular muscle) due to the high permeability of K⁺ through leak channels. The Na⁺/K⁺-ATPase pump (3 Na⁺ out : 2 K⁺ in) maintains concentration gradients."),
sp(4),
styled_table(
["Cell Type", "RMP (mV)", "Key Ion(s)"],
[
["Ventricular muscle", "−85 to −90", "K⁺ leak channels dominant"],
["SA node (pacemaker)", "−55 to −60", "Funny current (If) — Na⁺/K⁺"],
["AV node", "−60 to −65", "Slow Ca²⁺ channels"],
["Atrial muscle", "−80 to −85", "K⁺ leak channels"],
["Purkinje fibres", "−90 to −95", "Most negative — fast conduction"],
],
[4.5*cm, 3.5*cm, 9*cm]
),
sp(8),
h2("1.2 Cardiac Action Potential — Ventricular Muscle"),
p("The ventricular action potential has 5 phases and lasts ~250–300 ms (much longer than nerve AP ~1 ms), which prevents tetanic contraction."),
sp(4),
styled_table(
["Phase", "Name", "Ion Movement", "Channel"],
[
["0", "Rapid Depolarisation", "Na⁺ rapidly into cell → RMP rises to ~+20 mV", "Fast Na⁺ channels open (voltage-gated)"],
["1", "Initial Repolarisation", "Na⁺ channels close; K⁺ exits briefly", "Transient outward K⁺ channel (Ito)"],
["2", "Plateau", "Ca²⁺ enters; K⁺ efflux slows — maintains +ve potential", "L-type Ca²⁺ channels open; K⁺ channels close"],
["3", "Rapid Repolarisation", "Ca²⁺ channels close; K⁺ rapidly exits", "Delayed rectifier K⁺ channels (IKr, IKs)"],
["4", "Resting Potential", "Na⁺/K⁺ pump restores gradients; K⁺ leak active", "K⁺ leak channels (IK1); Na⁺/K⁺ ATPase"],
],
[1.5*cm, 3.5*cm, 6*cm, 6*cm]
),
sp(4),
note("Phase 2 plateau is unique to cardiac muscle. Ca²⁺ influx triggers Ca²⁺-induced Ca²⁺ release (CICR) from sarcoplasmic reticulum — the basis of excitation-contraction coupling."),
sp(6),
h2("1.3 Pacemaker Action Potential (SA Node)"),
p("SA nodal cells lack a stable phase 4 — they exhibit <b>spontaneous diastolic depolarisation</b> (pacemaker potential) owing to the <b>funny current (If)</b> — a mixed Na⁺/K⁺ inward current activated on hyperpolarisation."),
sp(4),
styled_table(
["Phase", "Event", "Channels Involved"],
[
["Phase 4", "Slow spontaneous depolarisation (pacemaker potential)", "If (HCN channels) open; IK declines; T-type Ca²⁺"],
["Phase 0", "Upstroke via L-type Ca²⁺ channels (slow, not fast Na⁺)", "L-type Ca²⁺ channels"],
["Phase 3", "Repolarisation via K⁺ efflux", "IK (delayed rectifier)"],
],
[2*cm, 8*cm, 7*cm]
),
sp(4),
mnemonic("SA node has NO Phase 1 or Phase 2. Upstroke = Ca²⁺ (not Na⁺). Remember: SA = Slow Action potential."),
sp(4),
clinical("Ivabradine blocks If (HCN channels) → slows heart rate without affecting contractility. Used in stable angina and heart failure (NYHA II–III, EF <35%)."),
sp(8),
h2("1.4 Refractory Periods"),
two_col(
[
key("Absolute Refractory Period (ARP)"),
p("No stimulus, however strong, can re-excite the cell. Corresponds to phases 0, 1, 2, and early phase 3. In ventricles: ~200–250 ms."),
sp(4),
key("Effective Refractory Period (ERP)"),
p("The period during which no propagated action potential can be elicited. Slightly longer than ARP in practice."),
],
[
key("Relative Refractory Period (RRP)"),
p("A stronger-than-normal stimulus CAN re-excite. Corresponds to late phase 3. Dangerous zone — vulnerable to arrhythmias (R-on-T phenomenon)."),
sp(4),
note("The long refractory period in cardiac muscle prevents summation (tetanus) — essential for the heart's pumping function."),
]
),
sp(8),
h2("1.5 Conduction System of the Heart"),
p("The cardiac impulse follows a precise pathway ensuring sequential atrial then ventricular contraction with appropriate timing."),
sp(4),
styled_table(
["Structure", "Intrinsic Rate", "Conduction Velocity", "Key Feature"],
[
["SA Node (Pacemaker)", "60–100 bpm", "0.05 m/s", "Primary pacemaker; located at SVC-RA junction"],
["Internodal Tracts", "—", "1.0 m/s", "Conduct from SA→AV node; includes Bachmann's bundle (to LA)"],
["AV Node", "40–60 bpm", "0.05 m/s", "Deliberate DELAY (~0.1 s) — allows ventricular filling"],
["Bundle of His", "40–60 bpm", "1.5 m/s", "Only electrical connection between atria & ventricles"],
["Bundle Branches (L & R)", "—", "2–4 m/s", "Divide into left anterior + posterior fascicles"],
["Purkinje Fibres", "20–40 bpm", "4 m/s (fastest)", "Rapid endocardial distribution; subendocardium → epicardium"],
["Ventricular Myocardium", "20–40 bpm", "0.3–0.5 m/s", "Cell-to-cell via gap junctions"],
],
[4*cm, 2.5*cm, 3*cm, 7.5*cm]
),
sp(4),
mnemonic("SA → Atria → AV delay → His → Bundle Branches → Purkinje → Ventricles. 'Some Anatomists Have Big Parts Per Ventricular.'"),
sp(4),
clinical("AV node receives both sympathetic (↑ conduction via β1) and parasympathetic (↓ conduction via M2 / vagus) innervation. Atropine blocks vagal tone → ↑ HR. High vagal tone = first-degree AV block in athletes."),
sp(6),
note("Criteria for Normal Sinus Rhythm: (1) origin in SA node, (2) regular rate 60–100 bpm, (3) correct activation sequence with appropriate PR interval (0.12–0.20 s)."),
sp(10),
PageBreak(),
]
# ════════════════════════════════════════════════════════════════════
# SECTION 2 — CARDIAC CYCLE
# ════════════════════════════════════════════════════════════════════
story += [
section_header("2. THE CARDIAC CYCLE"),
sp(10),
h2("2.1 Phases of the Cardiac Cycle (Left Ventricle)"),
p("At a normal heart rate of 75 bpm, one cardiac cycle lasts ~0.8 s (0.3 s systole, 0.5 s diastole)."),
sp(6),
styled_table(
["Phase", "Duration", "Valves", "Pressures / Volume", "Key Events"],
[
["Late Diastole (Filling)", "~0.5 s total diastole", "MV open, AoV closed", "LV pressure low (~5–10 mmHg); LV volume ↑ to EDV (~130 mL); ~70% passive filling",
"Passive ventricular filling; E-wave (rapid fill), then slow fill, then atrial kick (A-wave = 30%)"],
["Atrial Systole", "~0.1 s", "MV open, AoV closed", "Atrial contraction adds ~30 mL; final EDV ~130 mL",
"P wave on ECG; produces 4th heart sound (S4) if pathological; lost in AF"],
["Isovolumetric Contraction (IVC)", "~0.05 s", "MV closed, AoV closed", "LV pressure rises rapidly; LV volume constant (ESV=EDV)",
"QRS complex; both valves closed; ventricular pressure builds. Mitral valve closes → S1"],
["Rapid Ejection", "~0.12 s", "MV closed, AoV open", "Aortic valve opens when LV P > aortic P (~80 mmHg); LV volume ↓ rapidly",
"Rapid ejection: ~70% of SV ejected; LV peak pressure ~120 mmHg"],
["Reduced Ejection", "~0.13 s", "MV closed, AoV open", "LV pressure begins to fall but exceeds aortic P; volume ↓ to ESV (~60 mL)",
"T wave on ECG; momentum maintains forward flow despite ↓ LV pressure"],
["Isovolumetric Relaxation (IVR)", "~0.08 s", "MV closed, AoV closed", "LV pressure falls rapidly; LV volume constant",
"Aortic valve closes → S2 (dicrotic notch on aortic waveform); LV pressure < aortic P"],
["Rapid Filling", "~0.1 s", "MV open, AoV closed", "MV opens when LV P < LA P (~5 mmHg); rapid ↑ in LV volume",
"E-wave on mitral doppler; S3 (3rd heart sound) if pathological (e.g. dilated ventricle)"],
],
[3*cm, 2*cm, 2.5*cm, 5*cm, 4.5*cm]
),
sp(6),
mnemonic("Valve closing sounds: MV closes (S1) at start of IVC; AoV closes (S2) at start of IVR. 'Mitral 1st, Aortic 2nd.'"),
sp(4),
clinical("S3 gallop (3rd sound) = rapid ventricular filling in a dilated, non-compliant ventricle → heart failure. S4 gallop = atrial kick into a stiff ventricle → LVH, hypertension, HOCM."),
sp(8),
h2("2.2 Pressure-Volume Loop (Left Ventricle)"),
p("The LV pressure-volume loop graphically represents one complete cardiac cycle and is essential for understanding changes in preload, afterload, and contractility."),
sp(4),
info_box([
Paragraph("<b>Reading the P-V Loop (counter-clockwise):</b>", KEY),
Paragraph("• <b>Point A → B (bottom right to top right)</b>: Isovolumetric Contraction — pressure ↑, volume constant", BULLET),
Paragraph("• <b>Point B → C (top right to top left)</b>: Ejection — pressure high, volume ↓ by SV", BULLET),
Paragraph("• <b>Point C → D (top left to bottom left)</b>: Isovolumetric Relaxation — pressure ↓, volume constant", BULLET),
Paragraph("• <b>Point D → A (bottom left to bottom right)</b>: Filling — pressure low, volume ↑ to EDV", BULLET),
Paragraph("• <b>Area of loop</b> = Stroke Work performed by LV", BULLET),
], bg=LIGHT_BLUE, border=MID_BLUE),
sp(4),
styled_table(
["Change", "Effect on P-V Loop", "Clinical Example"],
[
["↑ Preload (↑ EDV)", "Loop shifts RIGHT; ↑ SV (Frank-Starling); same contractility slope", "IV fluids, exercise, pregnancy"],
["↑ Afterload (↑ aortic P)", "Loop shifts UP; ↓ SV; ↑ ESV; ↑ wall stress", "Hypertension, aortic stenosis"],
["↑ Contractility (inotropy+)", "Loop shifts UP & LEFT; ↑ SV; same EDV; ↑ EF", "Catecholamines, digoxin, dobutamine"],
["↓ Contractility (heart failure)", "Loop shifts DOWN & RIGHT; ↓ SV; ↑ EDV & ESV; ↓ EF", "Cardiomyopathy, MI, beta-blockers"],
],
[4*cm, 6.5*cm, 6.5*cm]
),
sp(8),
h2("2.3 Cardiac Output, Stroke Volume & Ejection Fraction"),
formula("Cardiac Output (CO) = Stroke Volume (SV) × Heart Rate (HR)"),
formula("Stroke Volume (SV) = End-Diastolic Volume (EDV) − End-Systolic Volume (ESV)"),
formula("Ejection Fraction (EF) = SV / EDV × 100%"),
sp(4),
styled_table(
["Parameter", "Normal Value", "Clinical Significance"],
[
["Cardiac Output", "~5 L/min (4–8 L/min)", "↑ in exercise, sepsis, pregnancy; ↓ in shock, HF"],
["Stroke Volume", "~70 mL (60–100 mL)", "EDV ~130 mL; ESV ~60 mL at rest"],
["Ejection Fraction", "≥55–65%", "EF <40% = HFrEF; 40–50% = HFmrEF; ≥50% = HFpEF"],
["Cardiac Index", "2.5–4 L/min/m²", "Normalised for BSA; <2.2 = cardiogenic shock"],
["Mean Arterial Pressure", "~93 mmHg", "MAP = DBP + 1/3 Pulse Pressure"],
],
[4.5*cm, 4*cm, 8.5*cm]
),
sp(4),
note("Fick Principle: CO = O₂ consumption / (Arterial O₂ content − Venous O₂ content). Used to measure CO invasively (right heart catheterisation)."),
sp(8),
h2("2.4 Frank-Starling Law of the Heart"),
p("The Frank-Starling law states that <b>stroke volume is directly proportional to end-diastolic volume</b> (within physiological limits). The underlying mechanism is the <b>length-tension relationship</b> in cardiac sarcomeres: greater stretch → more optimal actin-myosin overlap → greater force of contraction."),
sp(4),
info_box([
Paragraph("<b>Key Concepts:</b>", KEY),
Paragraph("• <b>Preload</b> = ventricular wall tension at end-diastole ≈ LVEDP or LVEDV (clinically: PCWP)", BULLET),
Paragraph("• ↑ Venous return → ↑ EDV → ↑ SV → ↑ CO (up-slope of Starling curve)", BULLET),
Paragraph("• In physiological range, curve is nearly <b>linear</b>; at very high EDV it flattens (heart cannot keep up)", BULLET),
Paragraph("• <b>Positive inotropes</b> (digoxin, catecholamines) shift curve UP-LEFT → ↑ SV at same EDV", BULLET),
Paragraph("• <b>Negative inotropes</b> (β-blockers, heart failure) shift curve DOWN-RIGHT → ↓ SV at same EDV", BULLET),
], bg=GREEN_LIGHT, border=GREEN_DARK),
sp(4),
clinical("In heart failure, the Starling curve is shifted downward and flattened — the ventricle compensates by ↑ EDV (dilation) but generates less SV. Inotropes restore the curve upward."),
sp(10),
PageBreak(),
]
# ════════════════════════════════════════════════════════════════════
# SECTION 3 — VASCULAR PHYSIOLOGY
# ════════════════════════════════════════════════════════════════════
story += [
section_header("3. VASCULAR PHYSIOLOGY & BLOOD PRESSURE"),
sp(10),
h2("3.1 Determinants of Blood Pressure"),
formula("Mean Arterial Pressure (MAP) = Cardiac Output (CO) × Total Peripheral Resistance (TPR)"),
formula("MAP ≈ DBP + ⅓ × Pulse Pressure [Pulse Pressure = SBP − DBP]"),
sp(4),
p("MAP is determined primarily by CO and TPR. Changes in either will alter MAP unless compensated by the other."),
sp(4),
styled_table(
["Factor", "Effect on MAP", "Mechanism"],
[
["↑ HR", "↑ MAP", "↑ CO → ↑ MAP (if SV maintained)"],
["↑ SV (preload)", "↑ MAP", "↑ CO via Frank-Starling"],
["↑ Contractility", "↑ MAP", "↑ SV, ↑ CO"],
["↑ TPR (vasoconstriction)", "↑ MAP", "↑ Afterload; ↓ capillary flow"],
["↑ Blood viscosity", "↑ MAP", "↑ Resistance to flow (Poiseuille)"],
["↑ Vessel radius (vasodilation)", "↓ MAP", "↓ TPR dramatically (∝ r⁴ per Poiseuille's law)"],
["↑ Blood volume", "↑ MAP", "↑ Venous return → ↑ EDV → ↑ CO"],
],
[5*cm, 2.5*cm, 9.5*cm]
),
sp(4),
formula("Poiseuille's Law: Q = (πr⁴ × ΔP) / (8ηL) — Flow ∝ r⁴ (radius most powerful determinant)"),
sp(4),
note("Arterioles are the principal site of resistance regulation (smallest radius, greatest control). A small change in arteriolar radius causes a large change in resistance and blood flow."),
sp(8),
h2("3.2 Pressure Profile Through the Circulation"),
styled_table(
["Vessel", "Approx. Pressure", "Key Feature"],
[
["Aorta", "120/80 mmHg; MAP ~93 mmHg", "Highest pressure; elastic walls store systolic energy (Windkessel effect)"],
["Large arteries", "~90–100 mmHg MAP", "Minimal resistance; distribute blood"],
["Arterioles", "~60–80 mmHg → ~35 mmHg", "Resistance vessels; largest pressure drop; controlled by sympathetics"],
["Capillaries", "~35 → ~15 mmHg", "Exchange vessels; Starling forces govern fluid movement"],
["Venules & veins", "~15 → ~5 mmHg", "Capacitance vessels; contain ~65% of blood volume"],
["Right atrium", "0–2 mmHg", "Lowest pressure; drives venous return"],
],
[3.5*cm, 4.5*cm, 9*cm]
),
sp(4),
mnemonic("Arteries carry blood Away; veins carry blood back. Arterioles = resistance vessels; Veins = capacitance (volume) vessels."),
sp(8),
h2("3.3 Capillary Exchange — Starling Forces"),
p("Fluid movement across capillary walls is governed by four <b>Starling forces</b>. Net filtration pressure (NFP) determines whether fluid moves out (filtration) or in (reabsorption)."),
sp(4),
formula("NFP = (Pc + πi) − (Pi + πc)"),
sp(2),
styled_table(
["Force", "Symbol", "Normal Value", "Effect on Fluid"],
[
["Capillary hydrostatic pressure", "Pc", "Arterial end: ~35; Venous end: ~15 mmHg", "Pushes fluid OUT (filtration)"],
["Interstitial hydrostatic pressure", "Pi", "~−3 mmHg (slightly subatmospheric)", "Pulls fluid OUT (usually assists filtration)"],
["Plasma oncotic (colloid osmotic) P", "πc", "~25–28 mmHg (mainly albumin)", "Pulls fluid IN (reabsorption)"],
["Interstitial oncotic pressure", "πi", "~8 mmHg", "Pushes fluid OUT"],
],
[5.5*cm, 1.5*cm, 5.5*cm, 4.5*cm]
),
sp(4),
info_box([
Paragraph("<b>Net filtration at arterial end:</b> (35 + 8) − (−3 + 25) = 43 − 22 = +21 → <b>filtration</b>", BODY),
Paragraph("<b>Net filtration at venous end:</b> (15 + 8) − (−3 + 25) = 23 − 22 = +1 → slight filtration", BODY),
Paragraph("→ Overall: small net filtration; excess fluid returned via <b>lymphatics</b>.", BODY),
], bg=LIGHT_BLUE, border=MID_BLUE),
sp(4),
clinical("Oedema mechanisms: (1) ↑ Pc (venous obstruction, heart failure), (2) ↓ πc (hypoalbuminaemia — nephrotic syndrome, liver failure), (3) ↑ capillary permeability (inflammation, anaphylaxis), (4) lymphatic obstruction (filariasis, post-mastectomy)."),
sp(8),
h2("3.4 Autonomic Control of the Vasculature"),
styled_table(
["Receptor", "Location", "Stimulant", "Vascular Effect"],
[
["α1-adrenoceptor", "Arterioles (skin, splanchnic, renal)", "Norepinephrine (NE) > Epinephrine (Epi)", "Vasoconstriction → ↑ TPR"],
["α2-adrenoceptor", "Presynaptic terminals; some vasculature", "NE", "↓ NE release (autoreceptor); mild vasoconstriction"],
["β1-adrenoceptor", "SA node, AV node, ventricular myocardium", "NE = Epi", "↑ HR (chronotropy), ↑ contractility (inotropy), ↑ dromotropy"],
["β2-adrenoceptor", "Arterioles (skeletal muscle, bronchi)", "Epi >> NE", "Vasodilation (↓ TPR in exercising muscle); bronchodilation"],
["M2-muscarinic", "SA node, AV node, atria (vagus nerve)", "Acetylcholine", "↓ HR, ↓ AV conduction; no direct vascular effect normally"],
],
[3.5*cm, 4.5*cm, 3.5*cm, 5.5*cm]
),
sp(4),
mnemonic("'α1 = A for Arterioles = Arteriole constriction.' 'β1 = 1 heart (chronotropy + inotropy).' 'β2 = 2 lungs (broncho) + 2 legs (vasodilate muscle).'"),
sp(4),
note("Epinephrine effect: At LOW doses → β2 effect dominates → ↓ TPR, ↓ DBP. At HIGH doses → α1 dominates → ↑ TPR, ↑ DBP. Net effect on MAP depends on dose."),
sp(10),
PageBreak(),
]
# ════════════════════════════════════════════════════════════════════
# SECTION 4 — BLOOD PRESSURE REGULATION
# ════════════════════════════════════════════════════════════════════
story += [
section_header("4. REGULATION OF BLOOD PRESSURE"),
sp(10),
h2("4.1 Short-Term Regulation — Baroreceptor Reflex"),
p("The baroreceptor (carotid sinus + aortic arch) reflex provides rapid (seconds) beat-to-beat control of blood pressure. It reduces minute-to-minute variation in arterial pressure by ~⅓ compared to denervated controls."),
sp(4),
info_box([
Paragraph("<b>Baroreceptor Reflex Arc:</b>", KEY),
Paragraph("1. Baroreceptors in carotid sinus (CN IX / Hering's nerve) & aortic arch (CN X / vagus) sense stretch (= ↑ BP)", BULLET),
Paragraph("2. Afferent signals → Nucleus Tractus Solitarius (NTS) in medulla oblongata", BULLET),
Paragraph("3. NTS → inhibits vasomotor centre (↓ sympathetic output) AND activates nucleus ambiguus (↑ vagal output)", BULLET),
Paragraph("4. ↓ Heart rate, ↓ contractility, ↓ TPR → ↓ MAP back toward normal", BULLET),
Paragraph("Reverse (↓ BP): ↑ sympathetic output → ↑ HR, ↑ inotropy, ↑ TPR (vasoconstriction) → ↑ MAP", BULLET),
], bg=LIGHT_BLUE, border=MID_BLUE),
sp(4),
styled_table(
["Feature", "Detail"],
[
["Location of receptors", "Carotid sinus (bifurcation of common carotid) + Aortic arch"],
["Stimulus", "Mechanical stretch (transmural pressure); fire at ≥60 mmHg, maximal at ~180 mmHg"],
["Afferent nerve", "Carotid sinus: CN IX; Aortic arch: CN X (vagus)"],
["Integration centre", "Nucleus Tractus Solitarius → Rostral VLM (sympathoexcitatory) + Caudal VLM"],
["Resetting", "Adapts (resets) over 1–2 days to sustained hypertension → less effective long-term"],
["Clinical note", "Carotid sinus massage → ↑ vagal tone → ↓ HR; used to terminate SVT"],
],
[5*cm, 12*cm]
),
sp(6),
h2("4.2 Other Short-Term Mechanisms"),
two_col(
[
h3("Chemoreceptor Reflex"),
b("Peripheral: carotid + aortic bodies"),
b2("Stimulated by: ↓ PO₂, ↑ PCO₂, ↑ H⁺"),
b2("Response: ↑ ventilation + ↑ vasomotor tone → ↑ BP"),
b("Central: medullary chemoreceptors"),
b2("Sensitive to CSF PCO₂/H⁺"),
b2("Primary drive for respiration, also modulate BP"),
sp(4),
h3("CNS Ischaemic Response"),
b("Cushing reflex: ↑ ICP → brain ischaemia → massive sympathetic discharge"),
b("Results in: ↑↑ BP (compensatory), bradycardia (baroreceptor response), irregular breathing"),
b2("Clinical: raised ICP; Cushing's triad = ↑ BP + bradycardia + irregular respiration"),
],
[
h3("Atrial Natriuretic Peptide (ANP)"),
b("Released by atrial myocytes when atrial wall is stretched (↑ blood volume)"),
b("Effects: ↑ GFR, ↑ Na⁺ & water excretion, ↓ aldosterone, ↓ renin, vasodilation"),
b2("Net: ↓ blood volume → ↓ MAP"),
sp(4),
h3("Veno-Arterial Reflex & Local Autoregulation"),
b("Myogenic response: ↑ transmural pressure → vasoconstriction (smooth muscle stretch)"),
b("Metabolic autoregulation: tissue ↑ CO₂/adenosine/H⁺/K⁺/↓ O₂ → local vasodilation"),
b2("Important in brain, kidney, heart (least in skin, gut)"),
]
),
sp(8),
h2("4.3 Long-Term Regulation — Renin-Angiotensin-Aldosterone System (RAAS)"),
p("The RAAS is the primary long-term regulator of blood pressure and sodium balance, acting over hours to days via changes in blood volume."),
sp(4),
info_box([
Paragraph("<b>RAAS Cascade:</b>", KEY),
Paragraph("1. <b>Renin</b> released from JGA of kidney in response to: ↓ renal perfusion pressure, ↓ Na⁺ at macula densa, ↑ sympathetic β1 activity", BULLET),
Paragraph("2. Renin cleaves Angiotensinogen (liver) → <b>Angiotensin I</b> (inactive)", BULLET),
Paragraph("3. ACE (lung endothelium) converts Ang I → <b>Angiotensin II</b> (active); ACE also degrades Bradykinin", BULLET),
Paragraph("4. <b>Angiotensin II</b> actions:", BULLET),
Paragraph(" • Vasoconstriction (AT1 receptor) → ↑ TPR → ↑ MAP", BULLET2),
Paragraph(" • ↑ Aldosterone secretion (adrenal cortex, zona glomerulosa) → Na⁺ & H₂O retention → ↑ volume", BULLET2),
Paragraph(" • ↑ ADH (vasopressin) secretion → ↑ H₂O reabsorption in collecting duct", BULLET2),
Paragraph(" • ↑ Thirst via hypothalamus", BULLET2),
Paragraph(" • ↑ Norepinephrine release from sympathetic nerve terminals", BULLET2),
Paragraph("5. <b>Aldosterone</b> acts on principal cells of distal tubule/collecting duct: ↑ ENaC & Na⁺/K⁺-ATPase → Na⁺ in, K⁺ & H⁺ out", BULLET),
], bg=AMBER_LIGHT, border=AMBER),
sp(4),
clinical("ACE Inhibitors (e.g. ramipril) block Ang II production → ↓ vasoconstriction, ↓ aldosterone → ↓ BP, ↓ proteinuria. Side effect: dry cough (↑ bradykinin). ARBs (losartan) block AT1 receptor — no cough. Both reduce mortality in HFrEF."),
sp(4),
mnemonic("RAAS Triggers: '3 Ds' — Decreased BP, Decreased Na⁺ delivery, β1 aDrenergic stimulation → Renin release."),
sp(8),
h2("4.4 ADH (Vasopressin) in Blood Pressure Regulation"),
styled_table(
["Stimulus for Release", "Action", "Receptor", "Clinical Relevance"],
[
["↑ Plasma osmolality (main stimulus)", "↑ Water reabsorption in collecting duct (aquaporin-2)", "V2 (kidney)", "SIADH: ↑↑ ADH → dilutional hyponatraemia"],
["↓ Blood volume/BP (≥10% loss)", "Vasoconstriction", "V1 (vascular SM)", "Hypovolaemic shock: ADH surge → preserves BP"],
["Nausea, pain, drugs, hypoglycaemia", "↑ Thirst, ↑ water intake", "CNS", "Diabetes insipidus: ADH deficiency → massive dilute urine"],
],
[4.5*cm, 5.5*cm, 3*cm, 4*cm]
),
sp(10),
PageBreak(),
]
# ════════════════════════════════════════════════════════════════════
# SECTION 5 — CARDIAC PHARMACOLOGY (Physiology basis)
# ════════════════════════════════════════════════════════════════════
story += [
section_header("5. PHYSIOLOGY OF CARDIAC PHARMACOLOGY"),
sp(10),
h2("5.1 Inotropes & Their Mechanisms"),
styled_table(
["Drug / Agent", "Mechanism", "HR", "Contractility", "TPR", "Use"],
[
["Digoxin", "Inhibits Na⁺/K⁺-ATPase → ↑ intracellular Na⁺ → ↑ Ca²⁺ via NCX", "↓ (vagal)", "↑↑", "—", "HFrEF, AF rate control"],
["Dobutamine", "β1 agonist (main) + mild β2", "↑", "↑↑", "↓ slightly", "Acute HF, cardiogenic shock"],
["Dopamine (high dose)", "α1 agonist", "↑", "↑", "↑↑", "Septic/cardiogenic shock"],
["Norepinephrine", "α1 >> β1", "↓ reflex", "↑", "↑↑↑", "Septic shock (vasopressor)"],
["Adrenaline (Epi)", "α1 + β1 + β2", "↑↑", "↑↑", "↑ (high dose)", "Cardiac arrest, anaphylaxis"],
["Milrinone", "PDE-3 inhibitor → ↑ cAMP → ↑ Ca²⁺", "↑ slightly", "↑↑", "↓ (vasodilator)", "Acute HF, post-cardiac surgery"],
],
[3*cm, 5*cm, 1.5*cm, 2.5*cm, 1.5*cm, 4.5*cm]
),
sp(8),
h2("5.2 Antiarrhythmics — Vaughan Williams Classification"),
styled_table(
["Class", "Mechanism", "Effect on AP", "Example Drugs", "Key Indication"],
[
["Ia", "Na⁺ channel block (intermediate kinetics) + K⁺ block", "↑ AP duration; ↓ phase 0 slope", "Quinidine, Procainamide, Disopyramide", "AF, VT; ↑ QRS & QT"],
["Ib", "Na⁺ channel block (fast off; binds inactivated channels)", "↓ AP duration (ischaemic tissue)", "Lignocaine (Lidocaine), Mexiletine", "Ventricular arrhythmias, post-MI VT"],
["Ic", "Na⁺ channel block (slow off; most potent Na⁺ block)", "↑↑ QRS, no change QT", "Flecainide, Propafenone", "AF (structurally normal heart only)"],
["II", "β-blocker (↓ cAMP, ↓ If, ↓ Ca²⁺ current)", "↓ Phase 4 slope → ↓ HR; ↑ PR interval", "Metoprolol, Atenolol, Propranolol", "AF rate control, SVT, post-MI"],
["III", "K⁺ channel block → ↑ AP duration, ↑ ERP", "↑↑ QT interval", "Amiodarone, Sotalol, Dofetilide", "AF cardioversion; VT/VF"],
["IV", "Ca²⁺ channel block (L-type)", "↓ Phase 0 (SA/AV); ↑ PR; ↓ HR", "Verapamil, Diltiazem", "SVT, AF rate control"],
["Other", "Adenosine: activates IKAdo → ↓ AV conduction (transient)", "Short ↑ PR; terminates SVT", "Adenosine (6mg IV rapid)", "Acute SVT (drug of choice); also diagnostic"],
],
[1.2*cm, 4.5*cm, 3.5*cm, 4.5*cm, 3.3*cm]
),
sp(4),
clinical("Amiodarone (Class III) also has Class I, II, IV properties — 'dirty drug.' Side effects: pulmonary fibrosis, thyroid dysfunction (hypo or hyper), corneal microdeposits, photosensitivity, hepatotoxicity."),
sp(4),
mnemonic("Class III increases QT because K⁺ channels are blocked — repolarisation delayed. Risk of Torsades de Pointes (TdP). AVOID in long QT syndrome."),
sp(8),
h2("5.3 Heart Failure Pharmacology — Physiological Basis"),
styled_table(
["Drug Class", "Example", "Mechanism / Physiology", "Benefit in HF"],
[
["ACE Inhibitor", "Ramipril, Enalapril", "↓ Ang II → ↓ TPR (afterload), ↓ aldosterone (preload)", "↓ Mortality HFrEF; ↓ remodelling"],
["ARB", "Losartan, Candesartan", "Block AT1 receptor; same haemodynamic effect as ACEi", "Alternative to ACEi (cough-free)"],
["Beta-blocker", "Carvedilol, Bisoprolol, Metoprolol", "Block β1 → ↓ HR, ↓ renin, reverse remodelling", "↓ Mortality HFrEF (counterintuitive — not used in acute HF)"],
["MRA (spironolactone)", "Spironolactone, Eplerenone", "Block aldosterone receptor → ↓ Na⁺ retention, ↓ fibrosis", "↓ Mortality on top of ACEi"],
["ARNI", "Sacubitril/Valsartan", "ARB + neprilysin inhibitor → ↑ ANP/BNP (vasodilation, natriuresis)", "↓ Mortality > ACEi (PARADIGM-HF)"],
["SGLT2i", "Dapagliflozin, Empagliflozin", "↓ glucose reabsorption → osmotic diuresis, ↓ preload & afterload, direct cardioprotection", "↓ HF hospitalisations; ↓ mortality (even HFpEF)"],
["Loop diuretic", "Furosemide", "Block NKCC2 → ↓ Na⁺/H₂O retention → ↓ preload", "Symptomatic relief; not shown to ↓ mortality"],
["Ivabradine", "Ivabradine", "Block If (HCN) → ↓ HR without affecting contractility", "↓ HF hospitalisation in EF <35%, HR ≥70, SR"],
],
[3.5*cm, 3.5*cm, 5.5*cm, 4.5*cm]
),
sp(10),
PageBreak(),
]
# ════════════════════════════════════════════════════════════════════
# SECTION 6 — INTEGRATED CARDIOVASCULAR RESPONSES
# ════════════════════════════════════════════════════════════════════
story += [
section_header("6. INTEGRATED CARDIOVASCULAR RESPONSES"),
sp(10),
h2("6.1 Response to Exercise"),
two_col(
[
h3("Immediate (Neural — within seconds)"),
b("Central command: motor cortex → ↑ sympathetic outflow → ↑ HR, ↑ contractility"),
b("Muscle metaboreceptors: accumulating CO₂, H⁺, lactate → further ↑ sympathetic tone"),
b("↑ Venous return (muscle pump, respiratory pump) → ↑ EDV → ↑ SV (Starling)"),
b("Net: ↑ HR + ↑ SV → CO rises from ~5 to ~25 L/min (elite athletes ~40 L/min)"),
sp(4),
h3("Local (Metabolic — milliseconds)"),
b("↑ CO₂, ↑ H⁺, ↑ K⁺, ↑ adenosine, ↑ temperature → active muscle vasodilation"),
b("↓ TPR in working muscles"),
],
[
h3("Net Haemodynamic Changes During Exercise"),
styled_table(
["Parameter", "Change"],
[
["Heart Rate", "↑↑ (main CO driver)"],
["Stroke Volume", "↑ (early; plateaus)"],
["Cardiac Output", "↑↑↑ (up to 5×)"],
["SBP", "↑ (CO effect)"],
["DBP", "Slight ↓ or unchanged"],
["Pulse Pressure", "↑↑"],
["TPR", "↓ (muscle vasodilation)"],
["Muscle blood flow", "↑↑↑ (up to 15× via β2 + metabolic dilation)"],
["Skin blood flow", "↑ (thermoregulation)"],
["Splanchnic/renal", "↓ (α1 vasoconstriction)"],
],
[4.5*cm, 4.5*cm]
),
]
),
sp(8),
h2("6.2 Cardiovascular Response to Haemorrhage (Hypovolaemic Shock)"),
p("Blood loss triggers a cascade of compensatory responses to maintain vital organ perfusion."),
sp(4),
styled_table(
["% Blood Volume Lost", "Class", "Clinical Features", "Compensatory Response"],
[
["Up to 15% (<750 mL)", "Class I", "Normal vital signs; mild anxiety", "Baroreceptor ↑ HR, mild venoconstriction"],
["15–30% (750–1500 mL)", "Class II", "↑ HR (100–120), ↑ RR, ↓ pulse pressure, anxious", "↑ Sympathetic: ↑ HR, ↑ TPR, ↑ ADH, ↑ RAAS"],
["30–40% (1500–2000 mL)", "Class III", "↑↑ HR (>120), ↓ BP, ↓ urine output, confused", "Maximal sympathetic; ↑ ADH, ↑ Ang II, ↑ epi"],
["≥40% (>2000 mL)", "Class IV", "↑↑↑ HR, BP undetectable, anuric, unconscious", "Decompensated shock; Cushing reflex if cerebral ischaemia"],
],
[4*cm, 2*cm, 5.5*cm, 5.5*cm]
),
sp(4),
info_box([
Paragraph("<b>Compensatory Mechanisms (priority order):</b>", KEY),
Paragraph("1. Baroreceptor reflex: ↓ BP → ↓ baroreceptor firing → ↑ sympathetic outflow (immediate, seconds)", BULLET),
Paragraph("2. Venoconstriction: mobilises venous reservoir (~65% blood volume in veins) → ↑ venous return", BULLET),
Paragraph("3. Arteriolar vasoconstriction (α1): ↑ TPR → maintains MAP; redistributes flow to brain & heart", BULLET),
Paragraph("4. Capillary fluid shift: ↓ Pc → reabsorption of interstitial fluid (autotransfusion, up to 1L over hours)", BULLET),
Paragraph("5. ADH release: ↑ water reabsorption (V2) + ↑ vasoconstriction (V1) — within minutes", BULLET),
Paragraph("6. RAAS activation: ↑ Ang II (vasoconstriction) + ↑ Aldosterone (Na⁺/H₂O retention) — hours to days", BULLET),
Paragraph("7. Erythropoietin (EPO): ↑ RBC production — days to weeks", BULLET),
], bg=RED_LIGHT, border=RED_DARK),
sp(8),
h2("6.3 High-Yield Cardiovascular Comparisons"),
styled_table(
["Scenario", "CO", "TPR", "MAP", "HR", "SV"],
[
["Exercise (aerobic)", "↑↑↑", "↓", "↑", "↑↑", "↑"],
["Hypovolaemic shock", "↓", "↑↑", "↓", "↑↑", "↓↓"],
["Cardiogenic shock", "↓↓", "↑↑", "↓↓", "↑", "↓↓"],
["Distributive (septic) shock", "↑", "↓↓", "↓", "↑↑", "↑/N"],
["Hypertension (chronic)", "N", "↑↑", "↑", "N", "N"],
["Aortic regurgitation", "↑", "↓", "↑ PP","↑", "↑"],
["Cardiac tamponade", "↓↓", "↑↑", "↓", "↑", "↓↓"],
["Pregnancy (2nd trimester)", "↑↑", "↓", "↓", "↑", "↑"],
],
[5*cm, 2*cm, 2*cm, 2*cm, 2*cm, 2*cm]
),
sp(10),
PageBreak(),
]
# ════════════════════════════════════════════════════════════════════
# SECTION 7 — HIGH-YIELD FORMULAS & QUICK REFERENCE
# ════════════════════════════════════════════════════════════════════
story += [
section_header("7. HIGH-YIELD FORMULAS & QUICK REFERENCE"),
sp(10),
h2("7.1 Key Formulas"),
styled_table(
["Formula", "Variables", "Normal Value"],
[
["CO = SV × HR", "CO: cardiac output; SV: stroke volume; HR: heart rate", "~5 L/min"],
["SV = EDV − ESV", "EDV: end-diastolic vol; ESV: end-systolic vol", "~70 mL"],
["EF = SV/EDV × 100", "Ejection fraction", "≥55%"],
["MAP = CO × TPR", "MAP: mean arterial pressure; TPR: total peripheral resistance", "~93 mmHg"],
["MAP = DBP + ⅓PP", "PP = SBP − DBP (pulse pressure)", "SBP 120, DBP 80, PP 40 mmHg"],
["PP = SBP − DBP", "Pulse Pressure — reflects SV and aortic compliance", "~40 mmHg"],
["Q = ΔP/R (Ohm's law)", "Q: flow; ΔP: pressure difference; R: resistance", "Basis of CO = MAP/TPR"],
["R = 8ηL/πr⁴ (Poiseuille)", "η: viscosity; L: length; r: radius — R ∝ 1/r⁴", "Arterioles regulate R via radius"],
["Fick: CO = VO₂/(CaO₂−CvO₂)", "VO₂: O₂ consumption; CaO₂: arterial O₂; CvO₂: venous O₂", "CO measurement in catheter lab"],
["RPP = SBP × HR", "Rate-pressure product = index of myocardial O₂ demand", "~10,000 at rest"],
],
[5*cm, 7.5*cm, 4.5*cm]
),
sp(8),
h2("7.2 Heart Sounds — Quick Reference"),
styled_table(
["Sound", "Timing", "Mechanism", "Pathological Cause"],
[
["S1 (Lub)", "Start of systole", "Mitral + tricuspid valve closure", "Loud S1: MS (mitral stenosis), ↑ CO; Soft S1: MR, long PR"],
["S2 (Dub)", "End of systole", "Aortic + pulmonary valve closure", "Wide fixed split: ASD; Paradoxical split: LBBB, AS, HCM"],
["S3 (Gallop)", "Early diastole", "Rapid ventricular filling in dilated ventricle", "Pathological in adults: dilated CMP, HF; Normal in kids/athletes"],
["S4 (Gallop)", "Late diastole (atrial kick)", "Atrial contraction into stiff ventricle", "LVH, HTN, HOCM, AS, post-MI"],
["Opening snap", "Early diastole", "Sudden tensing of stenosed mitral valve leaflets", "Mitral stenosis (shorter OS to S2 gap = more severe)"],
["Pericardial knock", "Early diastole", "Sudden halt of ventricular filling", "Constrictive pericarditis"],
],
[3*cm, 3*cm, 5*cm, 6*cm]
),
sp(8),
h2("7.3 Murmurs — Systematic Approach"),
styled_table(
["Murmur Timing", "Lesion", "Quality / Location / Radiation", "Grading"],
[
["Systolic ejection (harsh, crescendo-decrescendo)", "Aortic Stenosis (AS)", "RUSB; radiates to carotids; best with patient sitting forward", "Grade I–VI (thrill = III+)"],
["Systolic ejection", "Pulmonary Stenosis", "LUSB; no radiation; ↑ with inspiration (Carvallo's sign)", ""],
["Pansystolic (holosystolic, plateau)", "Mitral Regurgitation (MR)", "Apex → axilla; blowing; ↓ squatting, ↑ valsalva", ""],
["Pansystolic", "Tricuspid Regurgitation", "LLSB; ↑ with inspiration", ""],
["Pansystolic", "VSD", "LLSB; harsh; right → left shunt if Eisenmenger", ""],
["Early diastolic (decrescendo, blowing)", "Aortic Regurgitation (AR)", "RUSB or LLSB; leaning forward, held expiration", ""],
["Mid-diastolic (rumbling)", "Mitral Stenosis (MS)", "Apex; opening snap precedes; left lateral decubitus", ""],
["Continuous (machinery)", "PDA", "Left infraclavicular area; ↑ in diastole", ""],
],
[4.5*cm, 3.5*cm, 6*cm, 3*cm]
),
sp(10),
PageBreak(),
]
# ════════════════════════════════════════════════════════════════════
# SECTION 8 — EXAM-STYLE Q&A
# ════════════════════════════════════════════════════════════════════
story += [
section_header("8. EXAM-STYLE Q & A"),
sp(10),
h2("High-Yield Questions with Explanations"),
sp(4),
]
qa_pairs = [
("Q1. A 30-year-old athlete has EDV = 160 mL, ESV = 50 mL, HR = 55 bpm. Calculate CO and EF.",
"SV = 160 − 50 = 110 mL. CO = 110 × 55 = 6050 mL/min ≈ 6 L/min. EF = 110/160 = 69%. Trained athletes have ↑ SV (eccentric hypertrophy → ↑ EDV) and slower HR but maintain normal CO."),
("Q2. Which phase of the cardiac cycle has the highest myocardial O₂ demand?",
"Isovolumetric contraction (IVC) — highest wall tension (Laplace: T = P × r / 2h) with no external work. Rate-pressure product (SBP × HR) is a clinical surrogate for myocardial O₂ demand."),
("Q3. Why does the dicrotic notch appear on the aortic pressure tracing?",
"At the end of systole, momentum carries blood forward briefly even as LV pressure falls. When forward flow stops, blood transiently flows backward toward the aortic valve, briefly ↓ aortic pressure. The aortic valve snaps shut, causing a brief pressure wave = dicrotic notch. This closure produces S2."),
("Q4. A patient is given a drug that blocks L-type Ca²⁺ channels. What happens to cardiac contractility and rate?",
"↓ Contractility (less Ca²⁺ for E-C coupling in myocardium) and ↓ SA node firing rate (L-type Ca²⁺ is the upstroke of SA action potential). This is a non-dihydropyridine Ca²⁺ channel blocker (e.g. verapamil/diltiazem). Avoid in HF (negative inotrope)."),
("Q5. Explain why squatting increases murmur intensity in aortic stenosis but decreases it in HOCM.",
"Squatting ↑ venous return (compression of leg veins) → ↑ EDV (preload) → ↑ LV filling. In AS: ↑ flow across fixed obstruction → ↑ murmur. In HOCM: ↑ EDV widens the dynamic outflow tract (more blood cushions the septal hypertrophy) → ↓ gradient → ↓ murmur. Valsalva and standing have opposite effects."),
("Q6. A patient in the ICU has CVP = 18 mmHg, BP = 80/60 mmHg, CO = 1.8 L/min. What type of shock?",
"↑ CVP (↑ preload/filling), ↓ BP, ↓ CO = cardiogenic shock (pump failure — heart cannot eject against adequate pressure despite sufficient filling). Treat with inotropes (dobutamine), consider balloon pump (IABP), diuretics cautiously if overloaded. Distinct from distributive shock (↑ CO, ↓ TPR)."),
("Q7. What is the Windkessel effect and its clinical significance?",
"Large elastic arteries (aorta) expand during systole, storing kinetic energy, then recoil during diastole, maintaining forward flow and diastolic BP. This smooths out pulsatile flow into near-continuous capillary flow. In atherosclerosis/ageing, aortic stiffness ↑ → ↑ SBP (more of the SV goes to ↑ pressure not stretch), ↓ DBP → widened pulse pressure → isolated systolic hypertension in the elderly."),
("Q8. Rank the following in order of increasing resistance (lowest to highest): capillaries, aorta, arterioles, veins.",
"Aorta (lowest R, highest Q) < Veins < Capillaries < Arterioles (highest R — smallest radius, greatest resistance per unit). Arterioles account for ~50% of total peripheral resistance."),
]
for q, a in qa_pairs:
story.append(KeepTogether([
info_box([Paragraph(q, KEY)], bg=LIGHT_BLUE, border=MID_BLUE),
sp(2),
info_box([Paragraph(a, BODY)], bg=GREEN_LIGHT, border=GREEN_DARK),
sp(8),
]))
# ════════════════════════════════════════════════════════════════════
# BACK COVER
# ════════════════════════════════════════════════════════════════════
story += [
PageBreak(),
Table(
[[
Paragraph("CARDIOVASCULAR PHYSIOLOGY", ParagraphStyle("bc1", fontSize=22, textColor=WHITE,
alignment=TA_CENTER, fontName="Helvetica-Bold", leading=30)),
Paragraph("Exam Notes — Quick Reference Summary", ParagraphStyle("bc2", fontSize=13,
textColor=colors.HexColor("#A8D4F5"), alignment=TA_CENTER, fontName="Helvetica", leading=20)),
Spacer(1, 20),
Paragraph("Key Topics Covered:", ParagraphStyle("bc3", fontSize=11, textColor=AMBER,
alignment=TA_CENTER, fontName="Helvetica-Bold", leading=18)),
Paragraph(
"1. Cardiac Electrophysiology (AP, Conduction, Refractory Periods)<br/>"
"2. Cardiac Cycle (Phases, P-V Loop, Heart Sounds)<br/>"
"3. Cardiac Output, SV, EF, Frank-Starling Law<br/>"
"4. Vascular Physiology, Pressure Profile, Starling Forces<br/>"
"5. BP Regulation (Baroreceptors, RAAS, ADH)<br/>"
"6. Autonomic Control (Sympathetic, Parasympathetic)<br/>"
"7. Pharmacology (Inotropes, Antiarrhythmics, HF drugs)<br/>"
"8. Integrated Responses (Exercise, Haemorrhage, Shock)<br/>"
"9. High-Yield Formulas, Heart Sounds, Murmurs<br/>"
"10. Exam Q&A",
ParagraphStyle("bc4", fontSize=10, textColor=WHITE, alignment=TA_CENTER,
fontName="Helvetica", leading=18)
),
Spacer(1, 30),
Paragraph("Based on: Guyton & Hall · Costanzo Physiology 7e · Ganong's Review · Goldman-Cecil Medicine",
ParagraphStyle("bc5", fontSize=9, textColor=colors.HexColor("#A8D4F5"),
alignment=TA_CENTER, fontName="Helvetica-Oblique", leading=14)),
Paragraph("Orris Medical — May 2026",
ParagraphStyle("bc6", fontSize=9, textColor=GREY_MED, alignment=TA_CENTER,
fontName="Helvetica", leading=14)),
]],
colWidths=[17*cm],
style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 60),
("BOTTOMPADDING", (0,0), (-1,-1), 60),
("LEFTPADDING", (0,0), (-1,-1), 30),
("RIGHTPADDING", (0,0), (-1,-1), 30),
])
),
]
# ── Build PDF ────────────────────────────────────────────────────────────────
os.makedirs(os.path.dirname(OUTPUT), exist_ok=True)
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
topMargin=1.8*cm,
bottomMargin=1.5*cm,
leftMargin=2*cm,
rightMargin=2*cm,
title="Cardiovascular Physiology Exam Notes",
author="Orris Medical",
)
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"PDF generated: {OUTPUT}")