Post op hypotension and treatment guidelines
"postoperative hypotension" AND treatment
PMID: 37778937
PMID: 38839472
PMID: 40886448
postoperative hypotension management guidelines 2024 vasopressor treatment thresholds
| Outcome | Odds Ratio (95% CI) |
|---|---|
| Mortality | OR 2.51 (1.86-3.38) |
| Myocardial injury | OR 2.52 (1.71-3.69) |
| Acute kidney injury | OR 1.72 (1.25-2.36) |
| Stroke | OR 1.82 (1.09-3.05) |
| Agent | Mechanism | Indication |
|---|---|---|
| Norepinephrine | α1 + β1 | First-line vasodilatory shock; most common vasopressor used post-op |
| Phenylephrine | α1 only | Pure vasodilation; spinal hypotension; preserves CO in certain patients |
| Ephedrine | α + β (indirect) | Spinal/epidural hypotension; bradycardia component |
| Vasopressin | V1 receptor | Refractory vasodilatory shock; add-on to norepinephrine |
| Epinephrine | α + β | Anaphylaxis; cardiogenic shock with vasodilation |
Create notes on how to treat post op hypertension in step wise approach with Pharmacology explained
"postoperative hypertension" AND management
postoperative hypertension stepwise treatment guidelines antihypertensive drugs 2024
"Mild hypertension generally does not require treatment, but a reversible cause should be sought." - Morgan & Mikhail's Clinical Anesthesiology, 7th ed.
| Category | Specific Cause |
|---|---|
| Pain | Incisional pain, endotracheal tube irritation |
| Physiological | Hypoxaemia, hypercapnia, metabolic acidosis |
| Bladder | Bladder distension (very common - check first) |
| Neurological | Emergence agitation/excitement, raised ICP |
| Drug rebound | Beta-blocker withdrawal, clonidine withdrawal |
| Volume | Fluid overload / hypervolaemia |
| Endocrine | Neuroendocrine stress response (catecholamine surge) |
| Surgical-specific | Carotid endarterectomy (baroreceptor denervation), intracranial procedures |
| Occult | Phaeochromocytoma (unresected residual tumour) |
If BP normalises after addressing the above, no antihypertensive drug is needed.
| Situation | First Choice | Second Choice | Avoid |
|---|---|---|---|
| Coronary artery surgery | Nitroglycerin, nicardipine, clevidipine | Esmolol, labetalol, SNP | - |
| Heart failure / pulmonary oedema | Clevidipine, nitroglycerin, fenoldopam | SNP + loop diuretic | Hydralazine, diazoxide, beta-blockers |
| Aortic dissection | Labetalol OR esmolol + SNP/fenoldopam | - | Vasodilator monotherapy (reflex tachycardia) |
| Carotid endarterectomy | Short-acting IV agents (labetalol, nicardipine) | - | Delay - most resolve in 12-24h |
| Neurological surgery (raised ICP) | Esmolol, labetalol | Nicardipine | SNP (increases ICP via cerebral vasodilation) |
| Catecholamine excess (phaeochromocytoma) | Phentolamine (α-blocker) | Labetalol | Beta-blocker alone (precipitates hypertensive crisis) |
| Renal failure | Clevidipine, nicardipine, labetalol | Fenoldopam (increases renal blood flow) | SNP (thiocyanate accumulation) |
| Post-eclampsia | Hydralazine, labetalol, nicardipine | - | ACE inhibitors, ARBs (teratogenic) |
| Drug | Reason to Avoid |
|---|---|
| Sublingual nifedipine | Uncontrolled BP drop, reflex tachycardia → myocardial ischaemia/infarction |
| IV hydralazine | Unpredictable response, reflex tachycardia, prolonged duration, difficult to titrate |
| Diazoxide | Excessive and prolonged hypotension |
| Beta-blocker monotherapy in phaeochromocytoma | Unopposed alpha stimulation → hypertensive crisis |
| SNP in raised ICP | Cerebral vasodilation worsens ICP |
| ACE inhibitors in bilateral renal artery stenosis | Acute renal failure |
| Drug | Class | Mechanism | Onset | Duration | Key Use | Key Avoid |
|---|---|---|---|---|---|---|
| Labetalol | α1+β blocker | ↓ SVR + ↓ HR/CO | 5-10 min | 3-6 h | Most post-op HTN | HF, asthma, bradycardia |
| Nicardipine | Dihydropyridine CCB | ↓ Ca²+ in vascular SM → ↓ SVR | 5-15 min | 4-6 h | Cardiac/vascular surgery | - |
| Clevidipine | Dihydropyridine CCB (ultra-short) | ↓ Ca²+ arterial SM → plasma esterase hydrolysis | 2-4 min | 5-15 min | Critical care hypertension, organ failure | Soy/egg allergy |
| Esmolol | β1 blocker | ↓ HR + contractility via β1 blockade | 1-2 min | 10-30 min | Rate-driven HTN, aortic dissection | HF, asthma, bradycardia |
| SNP | Nitrovasodilator | NO release → ↑cGMP → arterial + venous vasodilation | Seconds | 1-2 min | Hypertensive crisis | Renal failure, raised ICP |
| Nitroglycerin | Organic nitrate | NO → venodilation > arterial dilation | 1-2 min | 3-5 min | CAB surgery, ischaemia | Tolerance after 24h |
| Enalaprilat | ACE inhibitor (IV) | ↓ Ang II → ↓ SVR + preload | 15-30 min | 6-12 h | Renin-mediated HTN | Renal artery stenosis, AKI |
| Fenoldopam | Dopamine D1 agonist | D1 receptor → arterial vasodilation + natriuresis | 5-10 min | 30-60 min | Renal failure patients | Reflex tachycardia at high dose |
| Phentolamine | α-blocker | Blocks α1+α2 → ↓ SVR | 1-2 min | 10-30 min | Phaeochromocytoma, catecholamine surge | Tachycardia |
| Urapidil | α1-blocker + 5-HT1A agonist | ↓ SVR + central sympatholysis | 3-5 min | 4-6 h | Perioperative HTN | - |
Generate a clinical decision tree PDF for POH drug selection by presentation
mkdir -p /home/daytona/workspace/poh-decision-tree && ls /home/daytona/workspace…
~/poh-decision-tree/generate_pdf.py
"""
Post-Operative Hypertension (POH) Clinical Decision Tree PDF
Uses ReportLab to draw a detailed flowchart on A3 landscape pages.
"""
from reportlab.lib.pagesizes import A3, landscape
from reportlab.lib.units import mm
from reportlab.lib import colors
from reportlab.pdfgen import canvas
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import Paragraph
from reportlab.lib.enums import TA_CENTER, TA_LEFT
import os
OUTPUT_PATH = "/home/daytona/workspace/poh-decision-tree/POH_Drug_Selection_Decision_Tree.pdf"
# ── Colour palette ─────────────────────────────────────────────────────────────
C_NAVY = colors.HexColor("#1B2A4A")
C_TEAL = colors.HexColor("#1F7A8C")
C_ORANGE = colors.HexColor("#E87040")
C_RED = colors.HexColor("#C0392B")
C_GREEN = colors.HexColor("#27AE60")
C_YELLOW = colors.HexColor("#F39C12")
C_PURPLE = colors.HexColor("#7D3C98")
C_BLUE_LT = colors.HexColor("#D6EAF8")
C_TEAL_LT = colors.HexColor("#D1F2EB")
C_ORANGE_LT = colors.HexColor("#FAE5D3")
C_RED_LT = colors.HexColor("#FADBD8")
C_GREEN_LT = colors.HexColor("#D5F5E3")
C_YELLOW_LT = colors.HexColor("#FEF9E7")
C_PURPLE_LT = colors.HexColor("#E8DAEF")
C_GREY_LT = colors.HexColor("#F2F3F4")
C_WHITE = colors.white
C_BLACK = colors.HexColor("#1A1A1A")
C_BORDER = colors.HexColor("#BFC9CA")
PAGE_W, PAGE_H = landscape(A3) # 420 × 297 mm
# ── Helper: wrapped text in a box ─────────────────────────────────────────────
def draw_box(c, x, y, w, h,
lines, # list of (text, fontname, fontsize, color)
bg=C_WHITE, border=C_BORDER,
radius=4, border_width=1.2,
shadow=False):
"""Draw a rounded rectangle with multiple text lines centred inside."""
if shadow:
c.setFillColor(colors.HexColor("#CCCCCC"))
c.roundRect(x+2, y-2, w, h, radius, fill=1, stroke=0)
c.setFillColor(bg)
c.setStrokeColor(border)
c.setLineWidth(border_width)
c.roundRect(x, y, w, h, radius, fill=1, stroke=1)
total_text_h = sum(fs + 2 for _, _, fs, _ in lines)
gap = (h - total_text_h) / 2
cur_y = y + h - gap
for text, font, fs, col in lines:
cur_y -= fs
c.setFillColor(col)
c.setFont(font, fs)
c.drawCentredString(x + w / 2, cur_y, text)
cur_y -= 2
def draw_diamond(c, cx, cy, hw, hh,
lines, bg=C_YELLOW_LT, border=C_YELLOW,
border_width=1.5):
"""Draw a diamond decision shape."""
path = c.beginPath()
path.moveTo(cx, cy + hh)
path.lineTo(cx + hw, cy)
path.lineTo(cx, cy - hh)
path.lineTo(cx - hw, cy)
path.close()
c.setFillColor(bg)
c.setStrokeColor(border)
c.setLineWidth(border_width)
c.drawPath(path, fill=1, stroke=1)
total_text_h = sum(fs + 2 for _, _, fs, _ in lines)
cur_y = cy + total_text_h / 2
for text, font, fs, col in lines:
c.setFillColor(col)
c.setFont(font, fs)
c.drawCentredString(cx, cur_y, text)
cur_y -= (fs + 3)
def arrow(c, x1, y1, x2, y2, label="", col=C_NAVY, lw=1.2):
"""Draw an arrow with an optional label."""
c.setStrokeColor(col)
c.setLineWidth(lw)
c.line(x1, y1, x2, y2)
# Arrowhead
import math
angle = math.atan2(y2 - y1, x2 - x1)
ah = 6
for da in (0.4, -0.4):
ex = x2 - ah * math.cos(angle - da)
ey = y2 - ah * math.sin(angle - da)
c.line(x2, y2, ex, ey)
if label:
mx, my = (x1 + x2) / 2, (y1 + y2) / 2
c.setFont("Helvetica-Bold", 7)
c.setFillColor(col)
c.drawCentredString(mx, my + 3, label)
def h_arrow(c, x1, y, x2, label="", col=C_NAVY):
arrow(c, x1, y, x2, y, label, col)
def v_arrow(c, x, y1, y2, label="", col=C_NAVY):
arrow(c, x, y1, x, y2, label, col)
# ══════════════════════════════════════════════════════════════════════════════
# PAGE 1 – MASTER DECISION TREE
# ══════════════════════════════════════════════════════════════════════════════
def page1(c):
W, H = PAGE_W, PAGE_H
c.setPageSize(landscape(A3))
# ── Background ────────────────────────────────────────────────────────────
c.setFillColor(colors.HexColor("#F7F9FC"))
c.rect(0, 0, W, H, fill=1, stroke=0)
# ── Header bar ────────────────────────────────────────────────────────────
c.setFillColor(C_NAVY)
c.rect(0, H - 22*mm, W, 22*mm, fill=1, stroke=0)
c.setFillColor(C_WHITE)
c.setFont("Helvetica-Bold", 16)
c.drawCentredString(W/2, H - 13*mm, "POST-OPERATIVE HYPERTENSION (POH-T) — CLINICAL DRUG SELECTION DECISION TREE")
c.setFont("Helvetica", 9)
c.drawCentredString(W/2, H - 19*mm,
"Sources: Morgan & Mikhail 7e • Miller's Anesthesia 10e • Comprehensive Clinical Nephrology 7e • AHA/ACC 2024 Perioperative Guidelines")
# ── Footer ────────────────────────────────────────────────────────────────
c.setFillColor(C_NAVY)
c.rect(0, 0, W, 8*mm, fill=1, stroke=0)
c.setFillColor(C_WHITE)
c.setFont("Helvetica-Oblique", 7)
c.drawCentredString(W/2, 2.5*mm,
"For clinical use only. Individualise all decisions to the patient. MAP target ≥60 mmHg (POQI 2024). Page 1 of 2")
# ── Column guide lines (subtle) ───────────────────────────────────────────
# Nothing — keep clean
# ═══ TIER 0 : START ═══
bw, bh = 90*mm, 16*mm
bx = W/2 - bw/2
by = H - 22*mm - 5*mm - bh
draw_box(c, bx, by, bw, bh,
[("PATIENT DEVELOPS POST-OP HYPERTENSION", "Helvetica-Bold", 10, C_WHITE),
("SBP >20–30% above patient's own baseline OR SBP ≥180 mmHg", "Helvetica", 7.5, C_WHITE)],
bg=C_NAVY, border=C_NAVY, radius=5, shadow=True)
top_cx = W/2
top_cy = by # bottom of start box
# ═══ TIER 1 : Diamond — Reversible Cause? ═══
d1_cx = W/2
d1_cy = by - 22*mm
d1_hw, d1_hh = 72*mm, 11*mm
draw_diamond(c, d1_cx, d1_cy, d1_hw, d1_hh,
[("STEP 1: Identify & Treat Reversible Causes First", "Helvetica-Bold", 8.5, C_BLACK),
("Pain? Bladder distension? Hypoxaemia? Hypercapnia? Agitation? Fluid overload?", "Helvetica", 7, C_BLACK)],
bg=C_YELLOW_LT, border=C_YELLOW)
v_arrow(c, top_cx, top_cy, d1_cx, d1_cy + d1_hh + 0.5*mm)
# YES branch — BP resolved
yes_bx = W/2 + d1_hw + 6*mm
yes_by = d1_cy - 7*mm
yes_bw, yes_bh = 55*mm, 14*mm
draw_box(c, yes_bx, yes_by, yes_bw, yes_bh,
[("BP RESOLVES", "Helvetica-Bold", 9, C_GREEN),
("No drug needed", "Helvetica", 7.5, C_BLACK),
("Continue monitoring", "Helvetica", 7.5, C_BLACK)],
bg=C_GREEN_LT, border=C_GREEN, radius=5)
h_arrow(c, d1_cx + d1_hw, d1_cy, yes_bx, label="YES", col=C_GREEN)
# NO branch — continues down
v_arrow(c, d1_cx, d1_cy - d1_hh - 0.5*mm, d1_cx, d1_cy - d1_hh - 12*mm, label="NO", col=C_RED)
# ═══ TIER 2 : Severity Diamond ═══
d2_cy = d1_cy - d1_hh - 18*mm
d2_hw, d2_hh = 60*mm, 11*mm
draw_diamond(c, d1_cx, d2_cy, d2_hw, d2_hh,
[("STEP 2: Assess Severity & End-Organ Signs", "Helvetica-Bold", 8.5, C_BLACK),
("Ischaemia? Heart failure? Bleeding? Neuro signs? ICU?", "Helvetica", 7, C_BLACK)],
bg=C_YELLOW_LT, border=C_ORANGE)
# ── MILD-MODERATE branch (LEFT) ───────────────────────────────────────────
mild_cx = W/2 - 110*mm
mild_cy = d2_cy - 0*mm
# Arrow from diamond left
arrow(c, d1_cx - d2_hw, d2_cy, mild_cx + 55*mm, d2_cy,
label="MILD–MODERATE", col=C_TEAL)
# MILD BOX
draw_box(c, mild_cx - 27*mm, d2_cy - 8*mm, 54*mm, 14*mm,
[("MILD–MODERATE HTN", "Helvetica-Bold", 9, C_WHITE),
("20–30% above baseline", "Helvetica", 7.5, C_WHITE),
("No end-organ signs", "Helvetica", 7.5, C_WHITE)],
bg=C_TEAL, border=C_TEAL, radius=5, shadow=True)
# STEP 3 drugs — mild
mild_drugs_y = d2_cy - 24*mm
drug_w, drug_h = 54*mm, 42*mm
draw_box(c, mild_cx - 27*mm, mild_drugs_y - drug_h, drug_w, drug_h,
[("STEP 3A — FIRST-LINE IV DRUGS", "Helvetica-Bold", 8, C_WHITE),
("", "Helvetica", 2, C_WHITE),
("① LABETALOL (α₁+β blocker)", "Helvetica-Bold", 8, C_YELLOW_LT),
("0.3–1 mg/kg IV bolus (max 80 mg)", "Helvetica", 7, C_WHITE),
("Onset 5–10 min | Duration 3–6 h", "Helvetica", 7, C_WHITE),
("Avoid: HF, asthma, bradycardia", "Helvetica-Oblique", 6.5, colors.HexColor("#FADADD")),
("", "Helvetica", 2, C_WHITE),
("② NICARDIPINE (DHP-CCB)", "Helvetica-Bold", 8, C_YELLOW_LT),
("5 mg/h IV → titrate to 15 mg/h", "Helvetica", 7, C_WHITE),
("Onset 5–15 min | Duration 4–6 h", "Helvetica", 7, C_WHITE),
("Preferred post cardiac/vascular surgery", "Helvetica-Oblique", 6.5, colors.HexColor("#D5F5E3")),
("", "Helvetica", 2, C_WHITE),
("③ ENALAPRILAT (IV ACE-i)", "Helvetica-Bold", 8, C_YELLOW_LT),
("0.625–1.25 mg IV q6h", "Helvetica", 7, C_WHITE),
("Onset 15–30 min | Duration 6–12 h", "Helvetica", 7, C_WHITE),
("Avoid: RAS inhibitors post-bypass, AKI", "Helvetica-Oblique", 6.5, colors.HexColor("#FADADD"))],
bg=C_TEAL, border=C_TEAL, radius=5, shadow=True)
# ── SEVERE branch (RIGHT) ─────────────────────────────────────────────────
sev_cx = W/2 + 110*mm
arrow(c, d1_cx + d2_hw, d2_cy, sev_cx - 27*mm, d2_cy,
label="SEVERE / END-ORGAN SIGNS", col=C_RED)
draw_box(c, sev_cx - 27*mm, d2_cy - 8*mm, 54*mm, 14*mm,
[("SEVERE HTN / END-ORGAN SIGNS", "Helvetica-Bold", 9, C_WHITE),
("Ischaemia, HF, ICH, bleeding", "Helvetica", 7.5, C_WHITE),
("→ Arterial line mandatory", "Helvetica-Bold", 7.5, colors.HexColor("#FFD700"))],
bg=C_RED, border=C_RED, radius=5, shadow=True)
sev_drugs_y = d2_cy - 24*mm
draw_box(c, sev_cx - 27*mm, sev_drugs_y - drug_h, drug_w, drug_h,
[("STEP 3B — IV INFUSION AGENTS", "Helvetica-Bold", 8, C_WHITE),
("", "Helvetica", 2, C_WHITE),
("① CLEVIDIPINE (ultra-short DHP-CCB)", "Helvetica-Bold", 8, C_YELLOW_LT),
("Start 1–2 mg/h → double q90 sec", "Helvetica", 7, C_WHITE),
("Onset 2–4 min | Duration 5–15 min", "Helvetica", 7, C_WHITE),
("Plasma esterase metabolism — organ-safe", "Helvetica-Oblique", 6.5, colors.HexColor("#D5F5E3")),
("", "Helvetica", 2, C_WHITE),
("② SODIUM NITROPRUSSIDE (SNP)", "Helvetica-Bold", 8, C_YELLOW_LT),
("0.3–10 mcg/kg/min IV (titrate)", "Helvetica", 7, C_WHITE),
("Onset seconds | Duration 1–2 min", "Helvetica", 7, C_WHITE),
("⚠ Cyanide toxicity if >2 mcg/kg/min >48h", "Helvetica-Oblique", 6.5, colors.HexColor("#FADADD")),
("", "Helvetica", 2, C_WHITE),
("③ ESMOLOL (β₁-blocker, ultra-short)", "Helvetica-Bold", 8, C_YELLOW_LT),
("500 mcg/kg bolus → 50–300 mcg/kg/min", "Helvetica", 7, C_WHITE),
("Onset 1–2 min | Duration 10–30 min", "Helvetica", 7, C_WHITE),
("Rate-related HTN, aortic dissection", "Helvetica-Oblique", 6.5, colors.HexColor("#D5F5E3"))],
bg=C_RED, border=C_RED, radius=5, shadow=True)
# ── CENTRE: STEP 4 — Situation-specific ──────────────────────────────────
spec_y = d2_cy - 24*mm - drug_h - 10*mm
spec_w = 120*mm
spec_x = W/2 - spec_w/2
spec_h = 28*mm
# Connector from both branches
v_arrow(c, mild_cx, d2_cy - 24*mm - drug_h,
W/2, spec_y + spec_h, col=C_NAVY)
v_arrow(c, sev_cx, d2_cy - 24*mm - drug_h,
W/2, spec_y + spec_h, col=C_NAVY)
draw_box(c, spec_x, spec_y, spec_w, spec_h,
[("STEP 4 — SITUATION-SPECIFIC DRUG SELECTION", "Helvetica-Bold", 9, C_WHITE),
("(See Page 2 for full situation-by-situation chart)", "Helvetica", 7.5, colors.HexColor("#D6EAF8")),
("Coronary surgery → NTG / Nicardipine", "Helvetica", 7.5, C_WHITE),
("Aortic dissection → Labetalol + SNP (↓dP/dt)", "Helvetica", 7.5, C_WHITE),
("Raised ICP → Esmolol / Labetalol (AVOID SNP)", "Helvetica", 7.5, C_WHITE),
("Phaeochromocytoma → Phentolamine (AVOID β-blocker alone)", "Helvetica", 7.5, C_WHITE)],
bg=C_NAVY, border=C_TEAL, radius=6, shadow=True)
# ── STEP 5 ────────────────────────────────────────────────────────────────
step5_y = spec_y - 14*mm
step5_w = 110*mm
step5_x = W/2 - step5_w/2
v_arrow(c, W/2, spec_y, W/2, step5_y + 12*mm, col=C_NAVY)
draw_box(c, step5_x, step5_y, step5_w, 12*mm,
[("STEP 5 — RESUME ORAL ANTIHYPERTENSIVES when tolerating orally", "Helvetica-Bold", 8, C_NAVY),
("Restart β-blockers & clonidine FIRST to prevent rebound | Delay ACE-i/ARB until volume adequate", "Helvetica", 7, C_BLACK)],
bg=C_BLUE_LT, border=C_NAVY, radius=4)
# ── Legend boxes ─────────────────────────────────────────────────────────
leg_x = 8*mm
leg_y = 12*mm
lw, lh = 30*mm, 7*mm
items = [
(C_TEAL_LT, C_TEAL, "Mild–Moderate"),
(C_RED_LT, C_RED, "Severe / End-Organ"),
(C_GREEN_LT,C_GREEN,"Resolved / No Rx"),
(C_YELLOW_LT,C_YELLOW,"Decision Point"),
(C_NAVY, C_NAVY, "Navigation"),
]
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(C_NAVY)
c.drawString(leg_x, leg_y + len(items)*lh + 2*mm, "LEGEND")
for i, (bg, bdr, txt) in enumerate(items):
bx2 = leg_x
by2 = leg_y + i * (lh + 1.5*mm)
c.setFillColor(bg)
c.setStrokeColor(bdr)
c.setLineWidth(1)
c.roundRect(bx2, by2, lw, lh, 2, fill=1, stroke=1)
c.setFillColor(C_BLACK if bg != C_NAVY else C_WHITE)
c.setFont("Helvetica", 7)
c.drawCentredString(bx2 + lw/2, by2 + 2*mm, txt)
# ── Arrows: mild & severe down to situation-specific ─────────────────────
# Already drawn above as connector lines
# ══════════════════════════════════════════════════════════════════════════════
# PAGE 2 – SITUATION-SPECIFIC CHART + PHARMACOLOGY REFERENCE
# ══════════════════════════════════════════════════════════════════════════════
def page2(c):
W, H = PAGE_W, PAGE_H
c.setPageSize(landscape(A3))
# Background
c.setFillColor(colors.HexColor("#F7F9FC"))
c.rect(0, 0, W, H, fill=1, stroke=0)
# Header
c.setFillColor(C_NAVY)
c.rect(0, H - 22*mm, W, 22*mm, fill=1, stroke=0)
c.setFillColor(C_WHITE)
c.setFont("Helvetica-Bold", 15)
c.drawCentredString(W/2, H - 13*mm,
"POH-T — SITUATION-SPECIFIC DRUG SELECTION & PHARMACOLOGY REFERENCE")
c.setFont("Helvetica", 8.5)
c.drawCentredString(W/2, H - 19*mm,
"Sources: Comprehensive Clinical Nephrology 7e (Table 36.2, 38.1) • Miller's Anesthesia 10e • Morgan & Mikhail 7e")
# Footer
c.setFillColor(C_NAVY)
c.rect(0, 0, W, 8*mm, fill=1, stroke=0)
c.setFillColor(C_WHITE)
c.setFont("Helvetica-Oblique", 7)
c.drawCentredString(W/2, 2.5*mm,
"Individualise all treatment decisions. MAP target ≥60 mmHg (POQI 2024 Consensus, Br J Anaesth). Page 2 of 2")
# ─── SECTION A: Situation-Specific Table ────────────────────────────────
tbl_y = H - 22*mm - 5*mm
tbl_x = 8*mm
tbl_w = W - 16*mm
col_widths = [52*mm, 60*mm, 55*mm, 45*mm, 50*mm] # 5 cols
row_h = 10*mm
headers = ["CLINICAL SITUATION", "FIRST-CHOICE DRUG(S)", "SECOND CHOICE / ADD-ON", "DRUGS TO AVOID", "BP REDUCTION AIM"]
rows = [
["Coronary artery / CABG surgery",
"Nitroglycerin (GTN)\nNicardipine\nClevidipine",
"Labetalol\nEsmolol (if no HF)\nSNP",
"Diazoxide\nHydralazine",
"Improve coronary perfusion\nAvoid ischaemia"],
["Heart failure /\nPulmonary oedema",
"Clevidipine\nNitroglycerin\nFenoldopam",
"SNP + loop diuretic\nEnalaprilat",
"Diazoxide\nHydralazine\nβ-blockers",
"↓ Afterload\nReduce pulmonary oedema"],
["Aortic dissection",
"Labetalol\n— OR —\nEsmolol + SNP/Fenoldopam",
"Nicardipine\nClevidipine",
"Vasodilator monotherapy\n(reflex tachycardia ↑ dP/dt)",
"HR <60 bpm\nSBP 100–120 mmHg\nMinimise dP/dt"],
["Raised ICP /\nNeurosurgery",
"Esmolol\nLabetalol",
"Nicardipine",
"SNP\n(cerebral vasodilation → ↑ICP)",
"Lower MAP gradually\nPreserve CPP"],
["Post-carotid endarterectomy",
"Short-acting IV agents:\nLabetalol, Nicardipine",
"Esmolol",
"—",
"Near pre-op values\nMost resolve in 12–24 h"],
["Phaeochromocytoma\n(catecholamine excess)",
"Phentolamine\n(α-blocker)\nNicardipine",
"Labetalol (combined α+β)",
"β-blocker ALONE\n(→ hypertensive crisis)",
"Control catecholamine surge\nAvoid reflex tachycardia"],
["Renal failure",
"Clevidipine\nNicardipine\nLabetalol",
"Fenoldopam\n(↑ renal blood flow + natriuresis)",
"SNP\n(thiocyanate accumulates)",
"Preserve renal perfusion"],
["Post-eclampsia /\nObstetric",
"Hydralazine (IV)\nLabetalol\nNicardipine",
"Magnesium sulfate\n(seizure prophylaxis)",
"ACE inhibitors\nARBs (teratogenic)",
"SBP <160 / DBP <110 mmHg"],
]
# Draw header row
cur_x = tbl_x
c.setFillColor(C_NAVY)
for i, h_txt in enumerate(headers):
c.rect(cur_x, tbl_y - row_h, col_widths[i], row_h, fill=1, stroke=0)
c.setFillColor(C_WHITE)
c.setFont("Helvetica-Bold", 7.5)
c.drawCentredString(cur_x + col_widths[i]/2, tbl_y - row_h + 3.5*mm, h_txt)
c.setFillColor(C_NAVY)
cur_x += col_widths[i]
# Table rows
row_colors = [C_BLUE_LT, C_WHITE]
situation_colors = [C_TEAL, C_RED, C_PURPLE, C_ORANGE,
C_TEAL, C_RED, C_GREEN, C_NAVY]
situation_lt = [C_TEAL_LT, C_RED_LT, C_PURPLE_LT, C_ORANGE_LT,
C_TEAL_LT, C_RED_LT, C_GREEN_LT, C_BLUE_LT]
cur_row_y = tbl_y - row_h
for ri, row in enumerate(rows):
rh = row_h * 2 if '\n' in row[0] else row_h * 1.7
cur_row_y -= rh
cur_x = tbl_x
for ci, cell in enumerate(row):
bg = situation_lt[ri] if ci == 0 else row_colors[ri % 2]
c.setFillColor(bg)
c.setStrokeColor(C_BORDER)
c.setLineWidth(0.5)
c.rect(cur_x, cur_row_y, col_widths[ci], rh, fill=1, stroke=1)
# Text
lines = cell.split('\n')
font = "Helvetica-Bold" if ci == 0 else "Helvetica"
fs = 7.5 if ci == 0 else 7
total_h = len(lines) * (fs + 2.5)
ty = cur_row_y + rh/2 + total_h/2 - fs
for line in lines:
c.setFillColor(situation_colors[ri] if ci == 0 else C_BLACK)
c.setFont(font, fs)
c.drawCentredString(cur_x + col_widths[ci]/2, ty, line)
ty -= (fs + 2.5)
cur_x += col_widths[ci]
# ─── SECTION B: Pharmacology Quick Reference Boxes ──────────────────────
pharm_y = cur_row_y - 8*mm
c.setFont("Helvetica-Bold", 10)
c.setFillColor(C_NAVY)
c.drawString(tbl_x, pharm_y, "PHARMACOLOGY QUICK REFERENCE")
c.setLineWidth(1.5)
c.setStrokeColor(C_TEAL)
c.line(tbl_x, pharm_y - 1.5*mm, tbl_x + 100*mm, pharm_y - 1.5*mm)
drugs_data = [
{
"name": "LABETALOL", "class": "α₁ + β blocker",
"mech": "Blocks α₁ (↓SVR) and β₁ (↓HR, ↓CO). α:β ratio 1:7 IV.",
"dose": "0.3–1 mg/kg IV bolus q10 min\nor 0.4–1 mg/kg/h infusion",
"onset": "5–10 min", "dur": "3–6 h",
"avoid": "HF, asthma, bradycardia, AV block",
"bg": C_TEAL_LT, "bdr": C_TEAL
},
{
"name": "NICARDIPINE", "class": "DHP Calcium Channel Blocker",
"mech": "Blocks L-type Ca²⁺ in vascular SM → arterial vasodilation. Minimal cardiac effect.",
"dose": "5 mg/h IV → titrate 2.5 mg/h\nevery 5–15 min; max 15 mg/h",
"onset": "5–15 min", "dur": "4–6 h",
"avoid": "Severe LV dysfunction (relative)",
"bg": C_BLUE_LT, "bdr": C_TEAL
},
{
"name": "CLEVIDIPINE", "class": "Ultra-short DHP-CCB (3rd gen)",
"mech": "Highly selective arterial L-type Ca²⁺ blocker. Hydrolysed by plasma esterases → organ-independent metabolism.",
"dose": "1–2 mg/h IV; double q90 sec\nUsual 4–6 mg/h; max 32 mg/h",
"onset": "2–4 min", "dur": "5–15 min",
"avoid": "Soy/egg allergy (lipid vehicle), severe AS",
"bg": C_BLUE_LT, "bdr": C_NAVY
},
{
"name": "ESMOLOL", "class": "Ultra-short β₁ blocker",
"mech": "β₁-adrenoceptor antagonism → ↓ HR and contractility. t½ ~9 min (RBC esterases).",
"dose": "500 mcg/kg bolus over 1 min\nthen 50–300 mcg/kg/min infusion",
"onset": "1–2 min", "dur": "10–30 min",
"avoid": "HF, asthma, COPD, AV block, bradycardia",
"bg": C_ORANGE_LT, "bdr": C_ORANGE
},
{
"name": "SODIUM NITROPRUSSIDE", "class": "Nitrovasodilator",
"mech": "Releases NO → ↑ cGMP → arterial + venous vasodilation. Most titratable agent available.",
"dose": "0.3 mcg/kg/min → titrate\nto max 10 mcg/kg/min. Cover from light.",
"onset": "Seconds", "dur": "1–2 min",
"avoid": "Renal failure (thiocyanate), raised ICP\n⚠ Cyanide toxicity >2 mcg/kg/min >48h",
"bg": C_RED_LT, "bdr": C_RED
},
{
"name": "NITROGLYCERIN", "class": "Organic nitrate",
"mech": "mtALDH2 converts to NO → venodilation >> arterial dilation. Reduces preload & wall tension. Coronary vasodilator.",
"dose": "5–10 mcg/min IV; titrate\nto 200 mcg/min",
"onset": "1–2 min", "dur": "3–5 min",
"avoid": "PDE-5 inhibitors; tolerance within 24h",
"bg": C_RED_LT, "bdr": C_ORANGE
},
{
"name": "FENOLDOPAM", "class": "Dopamine D₁ agonist",
"mech": "D₁ receptor stimulation → arterial vasodilation + ↑ renal blood flow (natriuresis, diuresis). No adrenergic activity.",
"dose": "0.1–1.6 mcg/kg/min IV infusion\n(start low, titrate)",
"onset": "5–10 min", "dur": "30–60 min",
"avoid": "High doses → reflex tachycardia\nGlaucoma (↑ IOP)",
"bg": C_GREEN_LT, "bdr": C_GREEN
},
{
"name": "PHENTOLAMINE", "class": "Non-selective α blocker",
"mech": "Competitive α₁ + α₂ blockade → ↓ SVR. α₂ blockade → reflex noradrenaline release → tachycardia.",
"dose": "5–15 mg IV bolus\nRepeat q10 min as needed",
"onset": "1–2 min", "dur": "10–30 min",
"avoid": "Use without β-blocker (if rate control needed,\nadd β-blocker AFTER α-blockade established)",
"bg": C_PURPLE_LT, "bdr": C_PURPLE
},
]
# Draw drug boxes in 2 rows of 4
box_w = (tbl_w - 7*mm) / 4
box_h = 32*mm
box_gap = 2.5*mm
pharm_box_y = pharm_y - 4*mm - box_h
for idx, d in enumerate(drugs_data):
col = idx % 4
row = idx // 4
bx = tbl_x + col * (box_w + box_gap)
by = pharm_box_y - row * (box_h + box_gap)
# Box background
c.setFillColor(d["bg"])
c.setStrokeColor(d["bdr"])
c.setLineWidth(1.5)
c.roundRect(bx, by, box_w, box_h, 4, fill=1, stroke=1)
# Header strip
c.setFillColor(d["bdr"])
c.roundRect(bx, by + box_h - 8*mm, box_w, 8*mm, 4, fill=1, stroke=0)
# Cover bottom corners of header
c.rect(bx, by + box_h - 8*mm, box_w, 4*mm, fill=1, stroke=0)
c.setFillColor(C_WHITE)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(bx + box_w/2, by + box_h - 5*mm, d["name"])
c.setFont("Helvetica-Oblique", 6.5)
c.drawCentredString(bx + box_w/2, by + box_h - 8*mm + 1.5*mm, d["class"])
# Content
content_y = by + box_h - 10*mm
text_items = [
("Mechanism: " + d["mech"], "Helvetica", 6.2, C_BLACK),
("Dose: " + d["dose"], "Helvetica-Bold", 6.5, C_BLACK),
("Onset: " + d["onset"] + " Duration: " + d["dur"], "Helvetica", 6.2, C_BLACK),
("⚠ Avoid: " + d["avoid"], "Helvetica-Oblique", 6, C_RED),
]
for text, font, fs, col2 in text_items:
# Wrap manually if needed
lines = text.split('\n')
for line in lines:
content_y -= (fs + 1.5)
c.setFillColor(col2)
c.setFont(font, fs)
# Truncate if too wide
while c.stringWidth(line, font, fs) > box_w - 3*mm and len(line) > 10:
line = line[:-4] + "…"
c.drawString(bx + 2*mm, content_y, line)
# ─── DRUGS TO AVOID PANEL ─────────────────────────────────────────────────
avoid_y = pharm_box_y - 2 * (box_h + box_gap) - 3*mm
avoid_w = tbl_w
avoid_h = 12*mm
c.setFillColor(C_RED_LT)
c.setStrokeColor(C_RED)
c.setLineWidth(1.5)
c.roundRect(tbl_x, avoid_y, avoid_w, avoid_h, 4, fill=1, stroke=1)
c.setFillColor(C_RED)
c.setFont("Helvetica-Bold", 8.5)
c.drawString(tbl_x + 3*mm, avoid_y + 8*mm, "⛔ DRUGS TO AVOID IN POST-OP HYPERTENSION:")
c.setFillColor(C_BLACK)
c.setFont("Helvetica", 7.5)
avoid_text = ("Sublingual Nifedipine (uncontrolled BP drop, reflex tachycardia → MI risk) | "
"IV Hydralazine (unpredictable, prolonged, reflex tachycardia) | "
"Diazoxide (excessive / prolonged hypotension) | "
"SNP in raised ICP (cerebral vasodilation ↑ ICP) | "
"β-blocker alone in phaeochromocytoma (unopposed α → hypertensive crisis) | "
"ACE-i / ARBs in bilateral RAS or AKI")
c.drawString(tbl_x + 3*mm, avoid_y + 2.5*mm, avoid_text)
# ══════════════════════════════════════════════════════════════════════════════
# MAIN
# ══════════════════════════════════════════════════════════════════════════════
def main():
os.makedirs(os.path.dirname(OUTPUT_PATH), exist_ok=True)
c = canvas.Canvas(OUTPUT_PATH, pagesize=landscape(A3))
c.setTitle("POH-T Clinical Drug Selection Decision Tree")
c.setAuthor("Orris Clinical AI")
c.setSubject("Post-Operative Hypertension Management")
page1(c)
c.showPage()
page2(c)
c.showPage()
c.save()
print(f"PDF saved to: {OUTPUT_PATH}")
if __name__ == "__main__":
main()
cd /home/daytona/workspace/poh-decision-tree && python generate_pdf.py
~/poh-decision-tree/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/poh-decision-tree/generate_pdf.py'
cd /home/daytona/workspace/poh-decision-tree && python generate_pdf.py
~/poh-decision-tree/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/poh-decision-tree/generate_pdf.py'
cd /home/daytona/workspace/poh-decision-tree && python generate_pdf.py 2>&1
"def v_arrow" in ~/poh-decision-tree
grep -n "v_arrow" /home/daytona/workspace/poh-decision-tree/generate_pdf.py
~/poh-decision-tree/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/poh-decision-tree/generate_pdf.py'
~/poh-decision-tree/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/poh-decision-tree/generate_pdf.py'
cd /home/daytona/workspace/poh-decision-tree && python generate_pdf.py 2>&1 && l…