Can you help me out because I recently joined icu to learn from the things basic how can I manage things confidently can make a good pdf with images chart for a beginner icu doctor every thing which is important emergency icu drugs pt handling ventilator support including everything which necessary which I can learn from that pdf first send chat now
ls -la /home/daytona/workspace/ && mkdir -p /home/daytona/workspace/icu-guide
~/icu-guide/generate_icu_pdf.py
#!/usr/bin/env python3
"""
ICU Beginner's Guide - Comprehensive PDF Generator
Uses ReportLab to produce a rich, visually formatted reference guide.
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus.flowables import HRFlowable
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle, Polygon
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics import renderPDF
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle
from reportlab.platypus import Image
import io
OUTPUT = "/home/daytona/workspace/icu-guide/ICU_Beginners_Guide.pdf"
# ──────────────────────────────────────────────────────────────────────────────
# COLOR PALETTE
# ──────────────────────────────────────────────────────────────────────────────
ICU_DARK_BLUE = colors.HexColor("#1A3A5C") # deep navy
ICU_MID_BLUE = colors.HexColor("#2E6DA4") # medium blue
ICU_LIGHT_BLUE = colors.HexColor("#D6E8F7") # pale blue bg
ICU_RED = colors.HexColor("#C0392B") # alert / danger
ICU_ORANGE = colors.HexColor("#E67E22") # warning
ICU_GREEN = colors.HexColor("#1E8449") # safe / normal
ICU_YELLOW = colors.HexColor("#F9E79F") # highlight
ICU_WHITE = colors.white
ICU_GREY = colors.HexColor("#F2F3F4")
ICU_DARK_GREY = colors.HexColor("#5D6D7E")
# ──────────────────────────────────────────────────────────────────────────────
# STYLES
# ──────────────────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def make_style(name, parent_name="Normal", **kwargs):
return ParagraphStyle(name, parent=styles[parent_name], **kwargs)
TITLE_STYLE = make_style("ICUTitle", fontSize=28, textColor=ICU_WHITE,
alignment=TA_CENTER, fontName="Helvetica-Bold",
spaceAfter=6, leading=34)
SUBTITLE_STYLE = make_style("ICUSubtitle", fontSize=14, textColor=ICU_LIGHT_BLUE,
alignment=TA_CENTER, fontName="Helvetica",
spaceAfter=4)
H1 = make_style("H1", fontSize=16, textColor=ICU_WHITE,
fontName="Helvetica-Bold", leading=20,
spaceAfter=4, spaceBefore=2)
H2 = make_style("H2", fontSize=13, textColor=ICU_DARK_BLUE,
fontName="Helvetica-Bold", leading=16,
spaceAfter=3, spaceBefore=8)
H3 = make_style("H3", fontSize=11, textColor=ICU_MID_BLUE,
fontName="Helvetica-Bold", leading=14,
spaceAfter=2, spaceBefore=4)
BODY = make_style("Body", fontSize=9.5, textColor=colors.black,
fontName="Helvetica", leading=13,
spaceAfter=3, alignment=TA_JUSTIFY)
BULLET = make_style("Bullet", fontSize=9.5, textColor=colors.black,
fontName="Helvetica", leading=13,
spaceAfter=2, leftIndent=12, firstLineIndent=-8)
SMALL = make_style("Small", fontSize=8, textColor=ICU_DARK_GREY,
fontName="Helvetica", leading=11, spaceAfter=2)
TABLE_HDR = make_style("TblHdr", fontSize=9, textColor=ICU_WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER)
TABLE_CELL = make_style("TblCell", fontSize=8.5, textColor=colors.black,
fontName="Helvetica", leading=11)
WARNING = make_style("Warning", fontSize=9, textColor=ICU_RED,
fontName="Helvetica-Bold", leading=12,
leftIndent=8, spaceAfter=4)
# ──────────────────────────────────────────────────────────────────────────────
# HELPERS
# ──────────────────────────────────────────────────────────────────────────────
def section_banner(title, color=ICU_DARK_BLUE):
"""Returns a colored banner with white text as a Table."""
data = [[Paragraph(title, H1)]]
t = Table(data, colWidths=[18*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [6,6,6,6]),
]))
return t
def info_box(title, items, bg=ICU_LIGHT_BLUE, title_color=ICU_DARK_BLUE):
"""Compact info box."""
rows = [[Paragraph(f"<b>{title}</b>", make_style("_ib", fontSize=10,
textColor=title_color, fontName="Helvetica-Bold"))]]
for item in items:
rows.append([Paragraph(f"• {item}", BULLET)])
t = Table(rows, colWidths=[17.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), bg),
("BACKGROUND", (0,1), (-1,-1), ICU_WHITE),
("BOX", (0,0), (-1,-1), 0.5, ICU_MID_BLUE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
return t
def data_table(headers, rows, col_widths=None, alt_rows=True):
"""Standard data table with header row."""
if col_widths is None:
col_widths = [17.5*cm / len(headers)] * len(headers)
data = [[Paragraph(h, TABLE_HDR) for h in headers]]
for i, row in enumerate(rows):
data.append([Paragraph(str(cell), TABLE_CELL) for cell in row])
t = Table(data, colWidths=col_widths)
style_cmds = [
("BACKGROUND", (0,0), (-1,0), ICU_DARK_BLUE),
("TEXTCOLOR", (0,0), (-1,0), ICU_WHITE),
("GRID", (0,0), (-1,-1), 0.4, ICU_DARK_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]
if alt_rows:
for i in range(1, len(data)):
bg = ICU_GREY if i % 2 == 0 else ICU_WHITE
style_cmds.append(("BACKGROUND", (0,i), (-1,i), bg))
t.setStyle(TableStyle(style_cmds))
return t
def alert_box(text, level="danger"):
color = ICU_RED if level == "danger" else (ICU_ORANGE if level == "warn" else ICU_GREEN)
icon = "⚠ " if level in ("danger","warn") else "✓ "
label = "CRITICAL" if level == "danger" else ("WARNING" if level == "warn" else "NOTE")
bg = colors.HexColor("#FDEDEC") if level == "danger" else (colors.HexColor("#FEF9E7") if level == "warn" else colors.HexColor("#EAFAF1"))
data = [[Paragraph(f"<b>{icon}{label}:</b> {text}",
make_style("_alert", fontSize=9, textColor=color,
fontName="Helvetica-Bold", leading=12))]]
t = Table(data, colWidths=[17.5*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("BOX", (0,0), (-1,-1), 1.0, color),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
]))
return t
# ──────────────────────────────────────────────────────────────────────────────
# CHART: RASS Score Visual
# ──────────────────────────────────────────────────────────────────────────────
def rass_chart():
d = Drawing(500, 160)
levels = [
("+4", "Combative", ICU_RED),
("+3", "Very Agitated", colors.HexColor("#E74C3C")),
("+2", "Agitated", colors.HexColor("#E67E22")),
("+1", "Restless", colors.HexColor("#F39C12")),
("0", "Alert&Calm", ICU_GREEN),
("-1", "Drowsy", colors.HexColor("#27AE60")),
("-2", "Lt Sedation", colors.HexColor("#2980B9")),
("-3", "Mod Sedation", ICU_MID_BLUE),
("-4", "Deep Sedation", ICU_DARK_BLUE),
("-5", "Unarousable", colors.HexColor("#1A252F")),
]
box_w, box_h = 44, 26
x0 = 10
for i, (score, label, clr) in enumerate(levels):
x = x0 + i * (box_w + 4)
d.add(Rect(x, 70, box_w, box_h, fillColor=clr, strokeColor=ICU_WHITE, strokeWidth=1))
d.add(String(x + box_w/2, 80, score,
fontSize=11, fillColor=ICU_WHITE,
fontName="Helvetica-Bold", textAnchor="middle"))
# label below
d.add(String(x + box_w/2, 52, label[:8],
fontSize=7, fillColor=colors.black,
fontName="Helvetica", textAnchor="middle"))
d.add(String(10, 110, "RASS (Richmond Agitation-Sedation Scale) — Target: -1 to 0 for most ICU patients",
fontSize=9, fillColor=ICU_DARK_BLUE,
fontName="Helvetica-Bold"))
d.add(String(10, 38, "← More Sedated More Agitated →",
fontSize=8, fillColor=ICU_DARK_GREY, fontName="Helvetica"))
return d
# ──────────────────────────────────────────────────────────────────────────────
# CHART: Shock classification
# ──────────────────────────────────────────────────────────────────────────────
def shock_chart():
d = Drawing(500, 130)
types = [
("Distributive\n(Septic)", "↑CO, ↓SVR", colors.HexColor("#E74C3C")),
("Cardiogenic", "↓CO, ↑SVR", colors.HexColor("#2980B9")),
("Hypovolemic", "↓CO, ↑SVR\n↓PCWP", colors.HexColor("#F39C12")),
("Obstructive\n(PE/Tamponade)", "↓CO, ↑SVR\n↑CVP", colors.HexColor("#8E44AD")),
]
bw = 100
for i, (label, hemo, clr) in enumerate(types):
x = 20 + i * (bw + 15)
d.add(Rect(x, 50, bw, 55, fillColor=clr, strokeColor=ICU_WHITE, strokeWidth=1.5))
# Split label for multiline
lines = label.split("\n")
y_start = 95
for ln in lines:
d.add(String(x + bw/2, y_start, ln, fontSize=9, fillColor=ICU_WHITE,
fontName="Helvetica-Bold", textAnchor="middle"))
y_start -= 11
# Hemodynamics below box
hlines = hemo.split("\n")
yh = 40
for hl in hlines:
d.add(String(x + bw/2, yh, hl, fontSize=8, fillColor=colors.black,
fontName="Helvetica", textAnchor="middle"))
yh -= 10
d.add(String(20, 118, "Types of Shock & Key Hemodynamics (CO=Cardiac Output, SVR=Systemic Vascular Resistance)",
fontSize=9, fillColor=ICU_DARK_BLUE, fontName="Helvetica-Bold"))
return d
# ──────────────────────────────────────────────────────────────────────────────
# CHART: Ventilator Settings Flowchart
# ──────────────────────────────────────────────────────────────────────────────
def vent_flowchart():
d = Drawing(500, 200)
steps = [
("INTUBATE\n& Connect", ICU_RED),
("Set Mode\nAC/VC", ICU_DARK_BLUE),
("TV 6-8\nmL/kg IBW", ICU_MID_BLUE),
("RR 12-16\n/min", ICU_MID_BLUE),
("FiO2 100%\n(titrate down)", colors.HexColor("#16A085")),
("PEEP 5-10\ncmH2O", colors.HexColor("#16A085")),
("Check ABG\n30 min", colors.HexColor("#7D3C98")),
]
bw, bh = 60, 50
y = 80
x = 10
gap = 10
for i, (label, clr) in enumerate(steps):
bx = x + i * (bw + gap)
d.add(Rect(bx, y, bw, bh, fillColor=clr, strokeColor=ICU_WHITE, strokeWidth=1.5))
lines = label.split("\n")
yo = y + bh - 14
for ln in lines:
d.add(String(bx + bw/2, yo, ln, fontSize=8.5, fillColor=ICU_WHITE,
fontName="Helvetica-Bold", textAnchor="middle"))
yo -= 11
# Arrow
if i < len(steps) - 1:
ax = bx + bw + 2
d.add(Line(ax, y + bh/2, ax + gap - 2, y + bh/2,
strokeColor=ICU_DARK_GREY, strokeWidth=1.5))
# arrowhead
d.add(Polygon([ax+gap-2, y+bh/2, ax+gap-6, y+bh/2+3, ax+gap-6, y+bh/2-3],
fillColor=ICU_DARK_GREY, strokeColor=ICU_DARK_GREY))
d.add(String(10, 148, "Initial Ventilator Setup Sequence",
fontSize=10, fillColor=ICU_DARK_BLUE, fontName="Helvetica-Bold"))
d.add(String(10, 52, "After ABG: Adjust FiO2 to SpO2 94-98% | Adjust RR to target PaCO2 35-45 | Plateau P < 30 cmH2O",
fontSize=8, fillColor=ICU_DARK_GREY, fontName="Helvetica"))
return d
# ──────────────────────────────────────────────────────────────────────────────
# CHART: GCS Visual
# ──────────────────────────────────────────────────────────────────────────────
def gcs_chart():
d = Drawing(500, 145)
categories = [
("EYE OPENING", ["4 - Spontaneous", "3 - To Voice", "2 - To Pain", "1 - None"],
[ICU_GREEN, colors.HexColor("#27AE60"), ICU_ORANGE, ICU_RED]),
("VERBAL", ["5 - Oriented", "4 - Confused", "3 - Words", "2 - Sounds", "1 - None"],
[ICU_GREEN, colors.HexColor("#27AE60"), colors.HexColor("#F39C12"), ICU_ORANGE, ICU_RED]),
("MOTOR", ["6 - Obeys", "5 - Localizes", "4 - Withdraws", "3 - Flexion", "2 - Extension", "1 - None"],
[ICU_GREEN, colors.HexColor("#27AE60"), colors.HexColor("#F39C12"),
ICU_ORANGE, colors.HexColor("#E74C3C"), ICU_RED]),
]
x_starts = [10, 180, 350]
col_widths = [155, 155, 145]
bh = 15
d.add(String(10, 133, "Glasgow Coma Scale (GCS) — Minimum 3, Maximum 15 | Score ≤8 = Consider Intubation",
fontSize=9, fillColor=ICU_DARK_BLUE, fontName="Helvetica-Bold"))
for ci, (cat, items, clrs) in enumerate(categories):
x = x_starts[ci]
cw = col_widths[ci]
d.add(Rect(x, 108, cw, 18, fillColor=ICU_DARK_BLUE, strokeColor=ICU_WHITE))
d.add(String(x + cw/2, 114, cat, fontSize=8.5, fillColor=ICU_WHITE,
fontName="Helvetica-Bold", textAnchor="middle"))
for ri, (item, clr) in enumerate(zip(items, clrs)):
ry = 107 - (ri+1)*(bh+1)
d.add(Rect(x, ry, cw, bh, fillColor=clr, strokeColor=ICU_WHITE, strokeWidth=0.5))
d.add(String(x+6, ry+4, item, fontSize=8, fillColor=ICU_WHITE,
fontName="Helvetica"))
return d
# ──────────────────────────────────────────────────────────────────────────────
# CHART: ABC Priorities Diagram
# ──────────────────────────────────────────────────────────────────────────────
def abc_diagram():
d = Drawing(500, 110)
items = [
("A", "AIRWAY", "Patent? Intubate\nif GCS ≤8", ICU_RED),
("B", "BREATHING", "RR, SpO2, ABG\nO2 / Ventilator", ICU_ORANGE),
("C", "CIRCULATION", "BP, HR, IV Access\nFluids / Vasopressors", ICU_MID_BLUE),
("D", "DISABILITY", "GCS, Pupils\nBSL check", ICU_GREEN),
("E", "EXPOSURE", "Full exam\nTemp, Lines", ICU_DARK_GREY),
]
bw = 87
for i, (letter, title, sub, clr) in enumerate(items):
x = 10 + i*(bw + 5)
# Big letter circle
d.add(Circle(x + bw/2, 78, 18, fillColor=clr, strokeColor=ICU_WHITE, strokeWidth=2))
d.add(String(x + bw/2, 73, letter, fontSize=18, fillColor=ICU_WHITE,
fontName="Helvetica-Bold", textAnchor="middle"))
d.add(String(x + bw/2, 52, title, fontSize=8, fillColor=clr,
fontName="Helvetica-Bold", textAnchor="middle"))
lines = sub.split("\n")
y_sub = 40
for ln in lines:
d.add(String(x + bw/2, y_sub, ln, fontSize=7, fillColor=colors.black,
fontName="Helvetica", textAnchor="middle"))
y_sub -= 9
d.add(String(10, 103, "ABCDE Primary Survey — Systematic ICU Patient Assessment",
fontSize=10, fillColor=ICU_DARK_BLUE, fontName="Helvetica-Bold"))
return d
# ──────────────────────────────────────────────────────────────────────────────
# MAIN DOCUMENT BUILD
# ──────────────────────────────────────────────────────────────────────────────
def build_pdf():
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
topMargin=1.5*cm, bottomMargin=1.5*cm,
leftMargin=1.5*cm, rightMargin=1.5*cm
)
story = []
SP = lambda n=6: Spacer(1, n)
HR = lambda: HRFlowable(width="100%", thickness=0.5, color=ICU_LIGHT_BLUE, spaceAfter=4, spaceBefore=4)
# ──────────── COVER ────────────
cover_data = [[
Paragraph("ICU SURVIVAL GUIDE", TITLE_STYLE),
Paragraph("A Beginner's Handbook for Junior ICU Doctors", SUBTITLE_STYLE),
Spacer(1, 4),
Paragraph("Emergency Drugs • Ventilator Management • Patient Monitoring", SUBTITLE_STYLE),
Paragraph("Fluid Resuscitation • Sedation • Common Emergencies • Quick Reference", SUBTITLE_STYLE),
]]
cover_t = Table(cover_data, colWidths=[18*cm])
cover_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), ICU_DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 20),
("BOTTOMPADDING", (0,0), (-1,-1), 20),
("LEFTPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [8,8,8,8]),
]))
story.append(cover_t)
story.append(SP(10))
story.append(alert_box("This guide is a quick reference for educational purposes. Always verify drug doses and follow your institution's protocols.", "warn"))
story.append(SP(6))
story.append(Paragraph("References: Washington Manual of Medical Therapeutics | Tintinalli's Emergency Medicine | Current Surgical Therapy 14e | Goldman-Cecil Medicine | Harrison's Internal Medicine 22E", SMALL))
story.append(PageBreak())
# ──────────── SECTION 1: ABCDE ────────────
story.append(section_banner("1. SYSTEMATIC ICU PATIENT ASSESSMENT — ABCDE"))
story.append(SP(8))
story.append(abc_diagram())
story.append(SP(8))
abcde_detail = [
["Component", "Assessment", "Immediate Actions"],
["A — Airway", "Is airway patent? Stridor? Secretions?",
"Head-tilt chin-lift, jaw thrust\nOropharyngeal/nasopharyngeal airway\nIntubate if GCS ≤8 or airway at risk"],
["B — Breathing", "RR, SpO2, breath sounds\nWork of breathing, symmetry",
"O2 via mask/NRB → target SpO2 ≥94%\nABG\nNIV or intubation if needed"],
["C — Circulation", "HR, BP, capillary refill, skin\nUrine output, IV access",
"2 large-bore IVs\nFluid bolus 500mL–1L crystalloid\nVasopressors if MAP <65 mmHg"],
["D — Disability", "GCS, pupils (size & reactivity)\nBlood glucose",
"Glucose if BSL <3.5 mmol/L\nCT head if focal neurology\nTreat seizures"],
["E — Exposure", "Full body exam, temperature\nLines, wounds, rashes",
"Remove clothing carefully\nLog-roll exam\nCultures before antibiotics"],
]
story.append(data_table(
abcde_detail[0], abcde_detail[1:],
col_widths=[3*cm, 6.5*cm, 8*cm]
))
story.append(SP(8))
story.append(info_box("Key Monitoring Parameters (Set Up on Arrival)", [
"Continuous ECG monitoring — detect arrhythmias",
"Pulse oximetry (SpO2) — continuous",
"Non-invasive / invasive arterial BP — q1h minimum",
"Urine output via IDC — target ≥0.5 mL/kg/hr",
"Central venous pressure (CVP) if CVC in situ",
"Temperature — q4h",
"End-tidal CO2 (ETCO2) — if intubated",
"Daily: ABG, electrolytes, FBC, CMP, lactate",
]))
story.append(PageBreak())
# ──────────── SECTION 2: VENTILATOR ────────────
story.append(section_banner("2. MECHANICAL VENTILATION BASICS", ICU_MID_BLUE))
story.append(SP(8))
story.append(vent_flowchart())
story.append(SP(8))
story.append(Paragraph("2A. Initial Ventilator Settings (AC/VC Mode)", H2))
vent_settings = [
["Parameter", "Initial Setting", "Target / Notes"],
["Mode", "AC/VC (Assist Control, Volume Control)", "Most common starting mode in ICU"],
["Tidal Volume (VT)", "6–8 mL/kg Ideal Body Weight (IBW)", "Low VT = lung protection. IBW:\nMale: 50 + 1.1×(Ht cm − 152)\nFemale: 45.5 + 1.1×(Ht cm − 152)"],
["Respiratory Rate (RR)", "12–16 breaths/min", "Adjust to maintain PaCO2 35–45 mmHg\nIncrease if acidosis"],
["FiO2", "Start 100%, wean rapidly", "Target SpO2 94–98% / PaO2 ≥60 mmHg\nAvoid prolonged hyperoxia"],
["PEEP", "5–10 cmH2O", "Higher PEEP in ARDS (8–16)\nCheck for auto-PEEP in COPD/asthma"],
["Inspiratory Flow", "60 L/min (square wave)", "↑ flow in obstructive disease"],
["I:E Ratio", "1:2 (default)", "1:3 or 1:4 in obstructive disease"],
["Plateau Pressure", "Target <30 cmH2O", "Check with end-inspiratory hold\n>30 = risk of barotrauma → ↓VT"],
]
story.append(data_table(vent_settings[0], vent_settings[1:],
col_widths=[3.5*cm, 6*cm, 8*cm]))
story.append(SP(8))
story.append(Paragraph("2B. Ventilator Modes — Quick Reference", H2))
modes = [
["Mode", "Full Name", "When to Use", "Key Feature"],
["AC/VC", "Assist-Control Volume Control", "Most ICU patients", "Fixed VT with each breath; patient can trigger"],
["SIMV", "Synchronized IMV", "Weaning", "Set rate + spontaneous breaths"],
["PS", "Pressure Support", "Weaning / spontaneous", "Patient controls RR and VT; ventilator assists"],
["CPAP", "Continuous Positive Airway Pressure", "NIV, pre-extubation", "No mandatory breaths; constant airway pressure"],
["BiPAP/NIPPV", "Bilevel Positive Airway Pressure", "COPD exacerbation, hypercapnic RF", "IPAP (inspiratory) + EPAP (expiratory)"],
["APRV", "Airway Pressure Release Ventilation", "Severe ARDS", "High P, long I-time; experts only"],
]
story.append(data_table(modes[0], modes[1:],
col_widths=[2*cm, 4.5*cm, 4.5*cm, 6.5*cm]))
story.append(SP(8))
story.append(alert_box("ARDS Ventilation: Use low VT 4–6 mL/kg IBW, PEEP 8–16 cmH2O, Plateau P <30, permissive hypercapnia (pH ≥7.20). Prone positioning for P/F <150.", "danger"))
story.append(SP(6))
story.append(alert_box("COPD/Asthma: Longer expiratory time (I:E 1:3–1:4), avoid auto-PEEP. Permissive hypercapnia acceptable.", "warn"))
story.append(Paragraph("2C. ARDS — Berlin Definition & P/F Ratio", H2))
pf_data = [
["Severity", "P/F Ratio (PaO2/FiO2)", "PEEP Required", "Mortality"],
["Mild ARDS", "200–300 mmHg", "≥5 cmH2O", "~27%"],
["Moderate ARDS","100–200 mmHg", "≥5 cmH2O", "~32%"],
["Severe ARDS", "<100 mmHg", "≥5 cmH2O", "~45%"],
]
story.append(data_table(pf_data[0], pf_data[1:],
col_widths=[4*cm, 5*cm, 4*cm, 4.5*cm]))
story.append(PageBreak())
# ──────────── SECTION 3: EMERGENCY DRUGS ────────────
story.append(section_banner("3. EMERGENCY & ICU DRUGS QUICK REFERENCE", ICU_RED))
story.append(SP(8))
story.append(Paragraph("3A. Vasopressors & Inotropes", H2))
vaso_data = [
["Drug", "Mechanism", "Dose", "Indication", "Key Points"],
["Norepinephrine\n(Noradrenaline)", "α1 > β1\n↑SVR, mild ↑HR",
"0.5–30 mcg/min IV\n(0.01–1 mcg/kg/min)",
"Septic shock (FIRST LINE)", "Preferred vasopressor in sepsis\nNeeds CVC for prolonged use"],
["Epinephrine\n(Adrenaline)", "α1 + β1 + β2\n↑HR, ↑CO, ↑SVR",
"Cardiac arrest: 1mg IV q3-5min\nInfusion: 0.01–0.5 mcg/kg/min",
"Cardiac arrest\nAnaphylaxis\nRefractory shock",
"Anaphylaxis: 0.5mg IM (thigh)\nMay ↑lactate (not true hypoperfusion)"],
["Dopamine", "D1, β1, α1\n(dose dependent)",
"Low: 2–5 mcg/kg/min\nMid: 5–10 mcg/kg/min\nHigh: >10 mcg/kg/min",
"2nd line vasopressor\nCardiogenic shock",
"Higher arrhythmia risk\nNOT recommended over NE in sepsis"],
["Vasopressin", "V1 receptor\n↑SVR (no HR change)",
"0.03–0.04 U/min\n(DO NOT titrate)",
"Adjunct to NE\nRefractory vasodilatory shock",
"Do not exceed 0.04 U/min\nReduces NE dose requirement"],
["Dobutamine", "β1 > β2\n↑HR, ↑CO, ↓SVR",
"2–20 mcg/kg/min",
"Cardiogenic shock\nLow CO states",
"May ↓BP due to vasodilation\nCombine with vasopressor if BP low"],
["Phenylephrine", "Pure α1\n↑SVR, ↓HR",
"100–300 mcg/min\nor 0.5–6 mcg/kg/min",
"SVT with hypotension\nWhen tachycardia is problem",
"Causes reflex bradycardia\nAvoid in cardiogenic shock"],
["Milrinone", "PDE inhibitor\n↑cAMP → ↑CO",
"Load: 50 mcg/kg over 10min\nMaintenance: 0.375–0.75 mcg/kg/min",
"Cardiac failure\nDobutamine intolerance",
"Reduce dose in renal failure\nMay cause hypotension"],
]
story.append(data_table(vaso_data[0], vaso_data[1:],
col_widths=[3*cm, 3*cm, 3.8*cm, 3.5*cm, 4.2*cm]))
story.append(SP(8))
story.append(Paragraph("3B. Sedation & Analgesia (PADIS Bundle)", H2))
story.append(info_box("PADIS Bundle (Pain, Agitation, Delirium, Immobility, Sleep)", [
"P — Assess pain regularly (NRS/BPS scale). Treat pain FIRST before sedation.",
"A — Light sedation target: RASS -1 to 0. Avoid deep sedation unless indicated.",
"D — Assess delirium with CAM-ICU. Minimize benzodiazepines. Early mobility.",
"I — Daily spontaneous awakening trials (SAT) + spontaneous breathing trials (SBT).",
"S — Optimize sleep hygiene; cluster nursing care; minimize noise at night.",
]))
story.append(SP(6))
story.append(rass_chart())
story.append(SP(8))
sed_data = [
["Drug", "Class", "Dose", "Duration", "Advantages", "Cautions"],
["Propofol", "GABA agonist\nSedative-hypnotic",
"5–50 mcg/kg/min\n(0.3–3 mg/kg/hr)",
"Short (t½ 30–60min)", "Fast on/off\nAnticonvulsant\nEasy titration",
"Hypotension\nPropofol infusion syndrome (PRIS) if >48hr at high dose\nHigh lipid load"],
["Midazolam", "Benzodiazepine",
"Bolus: 1–5 mg IV\nInfusion: 0.02–0.1 mg/kg/hr",
"Medium\nActive metabolite accumulates",
"Amnestic\nAnticonvulsant",
"Delirium risk\nAccumulates in renal failure\nProlong ICU stay"],
["Dexmedetomidine", "α2 agonist",
"0.2–1.5 mcg/kg/hr\n(no loading in ICU)",
"Short-medium",
"Co-operable sedation\n↓Delirium\n↓Ventilator time",
"Bradycardia, hypotension\nExpensive"],
["Ketamine", "NMDA antagonist\nDissociative",
"Bolus: 1–2 mg/kg IV\nInfusion: 0.1–0.5 mg/kg/hr",
"Short (IV bolus)\nInfusion variable",
"Bronchodilator\nAnalgesic\nHemodynamically stable",
"Increases secretions\n↑ICP (avoid in brain injury)\nEmergence reactions"],
["Morphine", "Opioid (MOR agonist)",
"2–4 mg IV bolus q2-4h\nInfusion: 1–5 mg/hr",
"Medium (active metabolite)",
"Analgesia\nSedation adjunct",
"Histamine release\nAccumulates in renal failure"],
["Fentanyl", "Opioid (MOR agonist)",
"25–100 mcg IV bolus\nInfusion: 25–200 mcg/hr",
"Short (bolus)\nLong (infusion accumulates)",
"No histamine\nHemodynamically stable",
"Chest wall rigidity (high dose)\nLipophilic — accumulates"],
["Lorazepam", "Benzodiazepine",
"0.5–2 mg IV q2-4h PRN",
"Medium-long",
"Anticonvulsant\nAnxiolytic",
"High delirium risk\nAvoid continuous infusion"],
]
story.append(data_table(sed_data[0], sed_data[1:],
col_widths=[2.8*cm, 2.5*cm, 3.2*cm, 2.5*cm, 3*cm, 3.5*cm]))
story.append(PageBreak())
story.append(section_banner("3C. CARDIAC EMERGENCY DRUGS", ICU_DARK_BLUE))
story.append(SP(8))
cardiac_data = [
["Drug", "Indication", "Dose", "Notes"],
["Amiodarone", "VT/VF (cardiac arrest)\nAF with rapid ventricular rate",
"VF/VT: 300mg IV push → 150mg\nAF: 150mg over 10min → 1mg/min x6h → 0.5mg/min",
"Multiple interactions\nThyroid/lung/liver toxicity (chronic)"],
["Adenosine", "SVT (narrow complex, regular)",
"6mg rapid IV → 12mg → 12mg\n(give into antecubital or central)",
"Very short t½ (10 sec)\nWarn patient of chest tightness\nContraindicated in asthma/AF/AFL"],
["Atropine", "Symptomatic bradycardia",
"0.5mg IV q3-5min (max 3mg)",
"Useful for vagal-mediated bradycardia\nNot for high-degree AV block (use pacing)"],
["Metoprolol", "Rate control: AF, SVT, sinus tachy",
"5mg IV over 2min, repeat q5min x3",
"Avoid in decompensated HF, COPD"],
["Labetalol", "Hypertensive urgency/emergency",
"20mg IV → 40–80mg q10min\nInfusion: 0.5–2 mg/min",
"Alpha + Beta blockade\nAvoid in acute HF, bradycardia"],
["Sodium Nitroprusside", "Hypertensive emergency\nAortic dissection",
"0.3–10 mcg/kg/min\n(light-protect infusion)",
"Risk of cyanide toxicity (>72h or high dose)\nTitratable"],
["GTN/Nitroglycerin", "ACS, hypertension, LV failure",
"Sublingual: 0.4mg q5min x3\nInfusion: 5–200 mcg/min",
"Headache, hypotension\nTolerance with prolonged use"],
["Digoxin", "Rate control: AF (not acute)",
"0.25–0.5mg IV load → 0.0625–0.25 mg/day",
"Narrow therapeutic index\nToxicity: nausea, visual changes, arrhythmias\nCheck levels + K+"],
["Calcium Gluconate", "Hyperkalemia, hypocalcemia\nCa-channel blocker OD",
"10mL of 10% over 2–5min IV",
"Stabilizes cardiac membrane\nRepeat if ECG changes persist"],
["Sodium Bicarbonate", "Severe metabolic acidosis (pH<7.1)\nHyperkalemia\nTCA OD",
"1–2 mEq/kg IV (50–100 mEq bolus)",
"Risk of hypernatremia, alkalosis\nCorrect pH cautiously"],
]
story.append(data_table(cardiac_data[0], cardiac_data[1:],
col_widths=[3.5*cm, 4.5*cm, 5*cm, 4.5*cm]))
story.append(PageBreak())
story.append(section_banner("3D. OTHER ESSENTIAL ICU DRUGS", colors.HexColor("#6C3483")))
story.append(SP(8))
story.append(Paragraph("Antibiotics — Empiric Therapy Guide", H2))
abx_data = [
["Condition", "Common Pathogens", "Empiric Regimen", "Notes"],
["Sepsis (unknown source)", "Gram neg, Gram pos, anaerobes",
"Pip-Tazo 4.5g IV q6h\n± Vancomycin if MRSA risk",
"Get cultures FIRST\nGive within 1 hour of recognition"],
["CAP (severe/ICU)", "Strep pneumo, atypicals, influenza",
"Ceftriaxone 2g IV + Azithromycin 500mg\nor Levofloxacin 750mg IV",
"Cover atypicals\nConsider antifungal if immunocompromised"],
["HAP/VAP", "Pseudomonas, MRSA, Klebsiella",
"Pip-Tazo 4.5g q6h + Vancomycin\nor Meropenem if MDR risk",
"MRSA nares swab guides vancomycin\nReview 48–72h with culture"],
["Meningitis (bacterial)", "Strep pneumo, Neisseria meningitidis",
"Ceftriaxone 2g IV q12h\n+ Dexamethasone 0.15 mg/kg q6h x4d",
"LP before antibiotics ONLY if no raised ICP\nAcyclovir 10mg/kg q8h if viral?"],
["UTI/Urosepsis", "E. coli, Klebsiella",
"Ceftriaxone 2g IV\nor Pip-Tazo if complicated",
"Source control (remove catheter)\nStep-down to oral when stable"],
["Fungemia (Candida)", "Candida spp",
"Micafungin 100–150mg IV daily\nor Fluconazole 400mg IV (if non-krusei/glabrata)",
"Ophthalmology review\nRemove CVC if possible"],
]
story.append(data_table(abx_data[0], abx_data[1:],
col_widths=[3.5*cm, 3.5*cm, 5*cm, 5.5*cm]))
story.append(SP(8))
story.append(Paragraph("Rapid Sequence Intubation (RSI) Drugs", H2))
rsi_data = [
["Drug", "Role", "Dose", "Notes"],
["Preoxygenation", "Prep",
"100% O2 for 3–5 min\nHigh-flow nasal O2 during apnea",
"Target SpO2 >95%\nApneic oxygenation reduces desaturation"],
["Ketamine", "Induction",
"1.5–2 mg/kg IV",
"Preferred in hypotensive or asthmatic patients\n↑secretions — have suction ready"],
["Propofol", "Induction",
"1.5–2.5 mg/kg IV (reduce in elderly/unstable)",
"Causes hypotension — avoid in hemodynamic instability"],
["Etomidate", "Induction",
"0.3 mg/kg IV",
"Hemodynamically neutral\nMay suppress adrenals (single dose usually OK)"],
["Succinylcholine", "Paralytic (depol.)",
"1.5 mg/kg IV",
"Fastest onset (60 sec)\nContraindicated: burn, crush, hyperkalaemia, NMD\nMalignant hyperthermia risk"],
["Rocuronium", "Paralytic (non-depol.)",
"1.2 mg/kg IV (RSI dose)",
"Onset ~60–90 sec at high dose\nReversible with Sugammadex 16 mg/kg IV"],
["Fentanyl", "Analgesia / ↓pressor response",
"1–3 mcg/kg IV 3 min before",
"Attenuates intubation response\nOmit in hypotensive patients"],
]
story.append(data_table(rsi_data[0], rsi_data[1:],
col_widths=[3*cm, 2.5*cm, 4.5*cm, 7.5*cm]))
story.append(PageBreak())
# ──────────── SECTION 4: FLUID & SHOCK ────────────
story.append(section_banner("4. FLUID RESUSCITATION & SHOCK MANAGEMENT"))
story.append(SP(8))
story.append(shock_chart())
story.append(SP(8))
story.append(Paragraph("4A. Fluid Types — Comparison", H2))
fluid_data = [
["Fluid", "Type", "Na (mEq/L)", "Use For", "Avoid In"],
["Normal Saline (0.9%)", "Isotonic crystalloid", "154",
"Volume resuscitation\nDrug dilution", "Large volumes → hyperchloraemic acidosis"],
["Lactated Ringer's (Hartmann's)", "Balanced crystalloid", "130",
"Preferred in most resuscitation\nSepsis, trauma", "Hyperkalemia (K+ 4 mEq/L)"],
["Albumin 4–5%", "Colloid", "130–160",
"Cirrhosis with ascites\nWhen crystalloids failing",
"Head injury (20% albumin OK)\nRoutinely over crystalloids"],
["Albumin 20%", "Concentrated colloid", "130",
"Refractory hyponatremia\nSBP in cirrhosis", "Cardiac overload risk"],
["Dextrose 5%", "Hypotonic", "0",
"Free water replacement\nHypernatremia maintenance",
"Resuscitation (worsens hyperglycemia)\nHyponatremia"],
["Dextrose 50%", "Hypertonic glucose", "0",
"Hypoglycemia treatment\n50mL IV for BSL <3.5 mmol/L",
"Routine maintenance"],
["HES / Starch", "Synthetic colloid", "Variable",
"Largely abandoned", "Renal failure, sepsis (↑AKI risk)"],
]
story.append(data_table(fluid_data[0], fluid_data[1:],
col_widths=[3.5*cm, 3*cm, 2.5*cm, 4*cm, 4.5*cm]))
story.append(SP(8))
story.append(Paragraph("4B. Septic Shock — Surviving Sepsis Campaign 1-Hour Bundle", H2))
story.append(info_box("Hour-1 Bundle (Do ALL within 1 hour of recognition)", [
"1. Measure lactate — if >2 mmol/L, remeasure at 2h. Lactate >4 = high mortality.",
"2. Blood cultures x2 sets (aerobic + anaerobic) BEFORE antibiotics.",
"3. Broad-spectrum antibiotics IV — give within 1 hour.",
"4. Crystalloid 30 mL/kg IV if MAP <65 or lactate ≥4. Use balanced crystalloid (Hartmann's).",
"5. Vasopressors — start NOREPINEPHRINE if MAP <65 mmHg despite fluids. Target MAP ≥65.",
], bg=colors.HexColor("#FDEDEC"), title_color=ICU_RED))
story.append(SP(6))
story.append(alert_box("Volume Responsiveness Test: Passive Leg Raise (PLR) — Lift legs 45° for 60 sec. A rise in MAP >10% or pulse pressure variation reduction = fluid responsive.", "warn"))
story.append(SP(6))
story.append(Paragraph("4C. Fluid Assessment Tools", H2))
fluid_assess = [
["Tool", "What It Measures", "Fluid Responsive if..."],
["Passive Leg Raise (PLR)", "Reversible autotransfusion\n~300mL venous return",
"MAP increases >10% or CO increases >10%"],
["Pulse Pressure Variation (PPV)", "Respiratory variation in arterial pulse",
"PPV >13% (only valid in mechanically ventilated patients in sinus rhythm)"],
["Stroke Volume Variation (SVV)", "Beat-to-beat stroke volume change",
"SVV >10% suggests fluid responsiveness"],
["CVP", "Right atrial pressure proxy",
"CVP alone is unreliable for guiding fluids\nLow CVP (<5) suggests depletion"],
["Ultrasound IVC", "IVC collapsibility index",
">50% collapse with inspiration (spontaneously breathing) = fluid responsive"],
]
story.append(data_table(fluid_assess[0], fluid_assess[1:],
col_widths=[4*cm, 5.5*cm, 8*cm]))
story.append(PageBreak())
# ──────────── SECTION 5: COMMON EMERGENCIES ────────────
story.append(section_banner("5. ICU EMERGENCY MANAGEMENT ALGORITHMS", ICU_RED))
story.append(SP(8))
story.append(Paragraph("5A. Cardiac Arrest — ALS Algorithm Overview", H2))
arrest_data = [
["Step", "Shockable (VF/Pulseless VT)", "Non-Shockable (PEA/Asystole)"],
["1", "CPR 30:2 — high quality\n100–120/min, 5–6cm depth", "CPR 30:2 immediately"],
["2", "Defibrillate ASAP:\n200J biphasic (monophasic: 360J)", "Identify reversible cause (4H4T)"],
["3", "Adrenaline 1mg IV after 3rd shock", "Adrenaline 1mg IV immediately"],
["4", "Amiodarone 300mg IV after 3rd shock", "Repeat adrenaline q3-5 min"],
["5", "Continue CPR 2-min cycles\nMinimize interruptions", "Continue CPR 2-min cycles"],
["Post-ROSC", "12-lead ECG, CT head/chest, TTM 32–36°C x24h\nPCI if STEMI, ICU care", "Same post-ROSC care"],
]
story.append(data_table(arrest_data[0], arrest_data[1:],
col_widths=[1.5*cm, 8*cm, 8*cm]))
story.append(SP(6))
story.append(info_box("4Hs and 4Ts — Reversible Causes of Cardiac Arrest", [
"4 Hs: Hypoxia | Hypovolemia | Hypo/Hyperkalemia (& metabolic) | Hypothermia",
"4 Ts: Tension Pneumothorax | Tamponade | Toxins/drugs | Thrombosis (PE / MI)",
]))
story.append(SP(8))
story.append(Paragraph("5B. Anaphylaxis — Management", H2))
anaphylaxis_data = [
["Priority", "Action", "Drug/Dose"],
["IMMEDIATE", "Remove trigger, call for help, lay flat (raise legs)", "—"],
["FIRST LINE", "Epinephrine IM (mid-outer thigh)",
"0.5mg IM (adult)\n0.3mg (10–25kg)\n0.15mg (<10kg)"],
["AIRWAY", "O2 high flow, prepare for intubation if stridor",
"100% O2 via NRB mask"],
["IV ACCESS", "Large bore IV, IV fluids",
"500mL–1L Hartmann's FAST"],
["SECOND LINE", "Antihistamine IV",
"Chlorphenamine 10mg IV\nor Diphenhydramine 25–50mg"],
["ADJUNCT", "Corticosteroid IV",
"Hydrocortisone 200mg IV"],
["BRONCHOSPASM", "Bronchodilator nebulized",
"Salbutamol 5mg neb"],
["REFRACTORY", "Repeat epi q5-15min\nor IV epinephrine infusion",
"0.1–1 mcg/kg/min IV (ICU only)"],
["MONITORING", "Observe minimum 4–6 hours after reaction",
"Monitor HR, BP, SpO2 continuously"],
]
story.append(data_table(anaphylaxis_data[0], anaphylaxis_data[1:],
col_widths=[2.5*cm, 8*cm, 7*cm]))
story.append(PageBreak())
story.append(Paragraph("5C. Hypertensive Emergency vs Urgency", H2))
htn_data = [
["", "Hypertensive Urgency", "Hypertensive Emergency"],
["BP", ">180/120 mmHg", ">180/120 mmHg (same)"],
["End-organ damage", "ABSENT", "PRESENT (brain, heart, kidney, eyes)"],
["Examples", "Severe HTN, headache only",
"Hypertensive encephalopathy, STEMI, stroke, aortic dissection, AKI, eclampsia"],
["Target BP reduction", "Oral agents, reduce over 24–48h",
"IV agents: Reduce MAP by 25% in 1st hour ONLY\nThen gradually normalize over 24h"],
["Drugs",
"Amlodipine 5–10mg PO\nLabetalol 200mg PO\nClonidine 0.1–0.2mg PO",
"Labetalol 20–80mg IV\nNicardipine 5–15mg/hr IV\nNitroprusside 0.3–10 mcg/kg/min\nNTG 5–200 mcg/min (ACS)"],
]
story.append(data_table(htn_data[0], htn_data[1:],
col_widths=[4*cm, 7*cm, 7*cm]))
story.append(SP(8))
story.append(Paragraph("5D. Status Epilepticus — Management Timeline", H2))
sei_data = [
["Time", "Drug / Action", "Dose"],
["0–5 min", "ABCs, O2, IV access, glucose\nMonitor (ECG, SpO2, BP)", "Dextrose 50% 50mL if hypoglycaemic"],
["5–20 min\n(Early SE)", "Benzodiazepine — 1st line\nLorazepam IV preferred",
"Lorazepam: 0.1 mg/kg IV (max 4mg)\nor Diazepam 0.15 mg/kg IV\nor Midazolam 10mg buccal/IM"],
["20–40 min\n(Established SE)", "AED 2nd line",
"Levetiracetam: 60 mg/kg (max 4.5g) IV over 10min\nor Phenytoin: 20 mg/kg IV at 50mg/min (ECG monitor)\nor Valproate: 40 mg/kg IV (max 3g)"],
["40–60 min\n(Refractory SE)", "Anaesthetic agent + ICU admission\n+Intubation + EEG",
"Propofol: 1–2 mg/kg bolus → 1–10 mg/kg/hr\nor Midazolam: 0.2 mg/kg → 0.1–2 mg/kg/hr\nor Thiopental: 3–5 mg/kg → 3–5 mg/kg/hr"],
[">60 min\n(Super-refractory)", "Ketamine, IVIG, steroids\nInvestigate autoimmune, metabolic, structural",
"Ketamine: 1–3 mg/kg/hr infusion"],
]
story.append(data_table(sei_data[0], sei_data[1:],
col_widths=[2.5*cm, 7*cm, 8*cm]))
story.append(PageBreak())
# ──────────── SECTION 6: MONITORING & LABS ────────────
story.append(section_banner("6. MONITORING, LABS & NORMAL VALUES", colors.HexColor("#1E8449")))
story.append(SP(8))
story.append(gcs_chart())
story.append(SP(8))
story.append(Paragraph("6A. Arterial Blood Gas (ABG) — Interpretation Steps", H2))
abg_steps = [
["Step", "Question", "Normal Range", "Abnormal Interpretation"],
["1 — pH", "Acidaemia or Alkalaemia?", "7.35–7.45",
"<7.35 = Acidaemia\n>7.45 = Alkalaemia"],
["2 — PaCO2", "Is it respiratory cause?", "35–45 mmHg (4.7–6 kPa)",
"↑CO2 + ↓pH = Respiratory Acidosis\n↓CO2 + ↑pH = Respiratory Alkalosis"],
["3 — HCO3-", "Is it metabolic cause?", "22–26 mEq/L",
"↓HCO3 + ↓pH = Metabolic Acidosis\n↑HCO3 + ↑pH = Metabolic Alkalosis"],
["4 — Compensation", "Is it appropriate?",
"Resp acidosis: HCO3 ↑1.5 per 10 CO2 rise\nMetab acidosis: CO2 = 1.5×HCO3 + 8 (±2)",
"No compensation = mixed disorder"],
["5 — PaO2 / SpO2", "Is the patient hypoxaemic?", "PaO2 80–100 mmHg\nSpO2 ≥94%",
"P/F Ratio <300 = Possible ARDS\n<200 = Moderate ARDS\n<100 = Severe ARDS"],
["6 — Lactate", "Is there tissue hypoperfusion?", "<2 mmol/L",
">2 = Increased lactate (investigate)\n>4 = Septic shock threshold, high mortality"],
["7 — Base Excess", "Overall metabolic picture", "−2 to +2",
"Negative BE (base deficit) = metabolic acidosis\nPositive BE = metabolic alkalosis"],
]
story.append(data_table(abg_steps[0], abg_steps[1:],
col_widths=[2.5*cm, 4*cm, 4.5*cm, 6.5*cm]))
story.append(SP(8))
story.append(Paragraph("6B. Anion Gap — Metabolic Acidosis MUDPILES", H2))
mudpiles = info_box("MUDPILES Mnemonic — High Anion Gap Metabolic Acidosis (AG = Na – (Cl + HCO3), Normal 8–12)", [
"M — Methanol",
"U — Uraemia (renal failure)",
"D — Diabetic Ketoacidosis (DKA)",
"P — Propylene glycol / Paraldehyde",
"I — Isoniazid / Iron poisoning",
"L — Lactic acidosis (sepsis, ischaemia)",
"E — Ethylene glycol",
"S — Salicylates",
])
story.append(mudpiles)
story.append(SP(8))
story.append(Paragraph("6C. Electrolyte Emergencies", H2))
electrolyte_data = [
["Electrolyte", "Critical Value", "Clinical Features", "Emergency Treatment"],
["Hyperkalaemia", "K+ >6.5 mEq/L\n(or ECG changes)",
"Peaked T waves → wide QRS → sine wave → VF",
"1. Calcium gluconate 10mL 10% IV (membrane stabilize)\n2. Insulin 10U + 50mL 50% dextrose IV\n3. Salbutamol 10–20mg neb\n4. Sodium bicarbonate if acidotic\n5. Kayexalate / Patiromer\n6. Dialysis if refractory"],
["Hypokalaemia", "K+ <2.5 mEq/L\n(or symptomatic)",
"Weakness, cramps\nU-waves on ECG\nVentricular arrhythmias",
"K+ replacement: 10–20mEq/hr IV (max 40mEq/hr via CVC)\nOral preferred if tolerated\nCorrect Mg2+ simultaneously"],
["Hyponatraemia", "Na+ <120 mEq/L acute\nor symptomatic",
"Confusion, seizures, herniation",
"Symptomatic/acute: 3% NaCl 1–2 mL/kg over 20–30 min\nTarget: ↑Na by 1–2 mEq/L/hr until symptoms resolve\nDO NOT correct >8–12 mEq/L in 24h (ODS risk)"],
["Hypernatraemia", "Na+ >155 mEq/L",
"Altered consciousness, seizures\nUusally from free water deficit",
"Replace free water: D5W or 0.45% saline\nCorrect SLOWLY: max 10 mEq/L per 24h\nMaintenance fluids adjusted"],
["Hypocalcaemia", "Ca2+ <1.9 mmol/L\nor symptomatic",
"Tetany, Chvostek's/Trousseau's\nQT prolongation, seizures",
"Calcium gluconate 10mL 10% IV over 10min\nContinuous infusion for refractory"],
["Hypomagnesaemia", "Mg2+ <0.5 mmol/L",
"Muscle weakness, arrhythmias\nRefractory hypokalaemia",
"MgSO4 4–8g IV over 15–60 min\nContinuous infusion: 2g/hr"],
]
story.append(data_table(electrolyte_data[0], electrolyte_data[1:],
col_widths=[2.5*cm, 3*cm, 4*cm, 8*cm]))
story.append(PageBreak())
# ──────────── SECTION 7: PROCEDURES ────────────
story.append(section_banner("7. COMMON ICU PROCEDURES — QUICK GUIDE", ICU_DARK_BLUE))
story.append(SP(8))
story.append(Paragraph("7A. Endotracheal Intubation — Preparation Checklist", H2))
intubation_check = [
"SOAP-ME: Suction | O2 supply | Airway equipment | Pharmacy (drugs) | Monitors & ECG",
"ETT sizes: Female 7.0–7.5 mm, Male 7.5–8.0 mm (have size above and below ready)",
"Confirm ETT position: End-tidal CO2 waveform (gold standard) + CXR (tip at carina – 2 cm)",
"Cuff pressure: Inflate to 20–30 cmH2O (use cuff manometer)",
"Secure tube: Mark cm at lips, tape/holder, document position",
"Immediate post-intubation: Chest auscultation bilaterally + CXR",
]
story.append(info_box("Pre-Intubation Checklist", intubation_check))
story.append(SP(6))
story.append(Paragraph("7B. Central Venous Catheter (CVC) — Key Points", H2))
cvc_data = [
["Site", "Advantages", "Disadvantages / Risks"],
["Internal Jugular (Right)", "Easy US guidance\nLower pneumothorax risk", "Patient discomfort\nCarotid puncture risk"],
["Subclavian", "Patient comfort (ambulatory)\nLower infection risk", "Highest pneumothorax risk\nHard to compress if bleeding"],
["Femoral", "No pneumothorax\nEasiest in emergency", "Highest infection risk\nLimit activity\nHigher DVT risk"],
["PICC (Peripherally Inserted)", "Long-term access\nLow infection", "Smaller lumen\nThrombosis risk\nNot for emergency"],
]
story.append(data_table(cvc_data[0], cvc_data[1:],
col_widths=[4*cm, 6*cm, 7.5*cm]))
story.append(SP(6))
story.append(info_box("CVC Insertion — Aseptic Technique (CLABSI Bundle)", [
"Hand hygiene + full barrier precautions (gown, gloves, mask, drape)",
"Chlorhexidine skin prep (allow to dry 30 sec)",
"Real-time ultrasound guidance (mandatory at most centres)",
"Confirm placement with CXR before use",
"Daily assessment — remove as soon as no longer indicated",
]))
story.append(SP(8))
story.append(Paragraph("7C. Arterial Line — Radial Artery Cannulation", H2))
story.append(info_box("Indications & Technique", [
"Indications: Continuous BP monitoring, frequent ABGs, vasoactive drug infusions",
"Allen's test: Compress radial + ulnar arteries 5 sec, release ulnar — hand should flush within 5 sec (confirms collateral)",
"Technique: 20G catheter, 30–45° angle, advance over wire (Seldinger) or direct cannulation",
"Confirm: Transduced waveform + arterial trace (pulsatile, dicrotic notch)",
"Complications: Thrombosis, infection, haematoma, distal ischaemia (rare)",
]))
story.append(PageBreak())
# ──────────── SECTION 8: QUICK REFERENCE CARDS ────────────
story.append(section_banner("8. ICU QUICK REFERENCE CARDS", colors.HexColor("#2E86C1")))
story.append(SP(8))
story.append(Paragraph("8A. Normal Physiological Values — ICU Reference", H2))
normal_vals = [
["Parameter", "Normal Range", "Critical Low", "Critical High"],
["Heart Rate", "60–100 bpm", "<40 bpm", ">150 bpm"],
["Systolic BP", "100–140 mmHg", "<80 mmHg", ">180 mmHg"],
["Mean Arterial Pressure", "70–100 mmHg", "<65 mmHg", ">110 mmHg"],
["SpO2", "94–100%", "<90%", "—"],
["PaO2", "80–100 mmHg", "<60 mmHg", ">300 mmHg (toxicity)"],
["PaCO2", "35–45 mmHg", "<25 mmHg", ">60 mmHg"],
["pH", "7.35–7.45", "<7.20", ">7.55"],
["HCO3-", "22–26 mEq/L", "<15 mEq/L", ">35 mEq/L"],
["Lactate", "<2 mmol/L", "—", ">4 mmol/L (critical)"],
["Temperature", "36.0–37.5°C", "<35°C (hypothermia)", ">38.5°C (fever)"],
["Urine Output", "≥0.5 mL/kg/hr", "<0.5 mL/kg/hr", ">3 mL/kg/hr (DI?)"],
["CVP", "5–12 mmHg", "<3 mmHg", ">15 mmHg"],
["Glucose (BSL)", "4–10 mmol/L (ICU)", "<4 mmol/L", ">12 mmol/L"],
["Sodium", "135–145 mEq/L", "<125 mEq/L", ">155 mEq/L"],
["Potassium", "3.5–5.0 mEq/L", "<2.5 mEq/L", ">6.0 mEq/L"],
["Haemoglobin", "Male: 130–170 g/L\nFemale: 120–160 g/L", "<70 g/L (transfuse)", "<180 g/L"],
["Platelets", "150–400 ×10⁹/L", "<50 ×10⁹/L (active bleeding)", ">1000 ×10⁹/L"],
["INR", "<1.3", "—", ">3.0 (bleeding risk)"],
["Creatinine", "Male: 60–110 μmol/L\nFemale: 50–90 μmol/L", "—", ">300 μmol/L"],
]
story.append(data_table(normal_vals[0], normal_vals[1:],
col_widths=[4.5*cm, 4*cm, 4.5*cm, 4.5*cm]))
story.append(SP(8))
story.append(Paragraph("8B. Common Infusion Drip Rates — Reference Guide", H2))
drip_data = [
["Drug", "Standard Concentration", "Dose Range", "Rate Calculation Example"],
["Norepinephrine", "4mg in 50mL NS (80 mcg/mL)",
"0.01–1 mcg/kg/min",
"For 70kg at 0.1 mcg/kg/min:\n0.1 × 70 / 80 × 60 = 5.25 mL/hr"],
["Epinephrine", "1mg in 50mL NS (20 mcg/mL)",
"0.01–0.5 mcg/kg/min",
"For 70kg at 0.05 mcg/kg/min:\n0.05 × 70 / 20 × 60 = 10.5 mL/hr"],
["Dopamine", "200mg in 50mL NS (4000 mcg/mL)",
"2–20 mcg/kg/min",
"For 70kg at 5 mcg/kg/min:\n5 × 70 / 4000 × 60 = 5.25 mL/hr"],
["Vasopressin", "20 U in 100mL NS (0.2 U/mL)",
"0.03–0.04 U/min (fixed)",
"0.04 U/min / 0.2 U/mL × 60 = 12 mL/hr"],
["Dobutamine", "250mg in 50mL NS (5000 mcg/mL)",
"2–20 mcg/kg/min",
"For 70kg at 5 mcg/kg/min:\n5 × 70 / 5000 × 60 = 4.2 mL/hr"],
["Propofol 1%", "1g in 100mL (10 mg/mL)",
"0.3–4 mg/kg/hr",
"For 70kg at 1 mg/kg/hr:\n70 / 10 = 7 mL/hr"],
["Dexmedetomidine", "200mcg in 50mL NS (4 mcg/mL)",
"0.2–1.5 mcg/kg/hr",
"For 70kg at 0.5 mcg/kg/hr:\n0.5 × 70 / 4 = 8.75 mL/hr"],
["Midazolam", "50mg in 50mL NS (1 mg/mL)",
"0.02–0.1 mg/kg/hr",
"For 70kg at 0.05 mg/kg/hr:\n0.05 × 70 / 1 = 3.5 mL/hr"],
["Morphine", "50mg in 50mL NS (1 mg/mL)",
"1–5 mg/hr (adult)",
"2 mg/hr = 2 mL/hr"],
["Fentanyl", "500mcg in 50mL NS (10 mcg/mL)",
"25–200 mcg/hr",
"50 mcg/hr / 10 mcg/mL = 5 mL/hr"],
["Heparin (UFH)", "25,000 U in 50mL NS (500 U/mL)",
"Weight-based protocol\n18 U/kg/hr start",
"For 70kg: 18 × 70 / 500 = 2.52 mL/hr"],
["Amiodarone (maintenance)", "900mg in 500mL D5W (1.8 mg/mL)",
"1 mg/min for 6h, then 0.5 mg/min",
"1mg/min: 33 mL/hr\n0.5mg/min: 16.5 mL/hr"],
["Insulin (regular)", "50U in 50mL NS (1 U/mL)",
"0.05–0.2 U/kg/hr (DKA)\nor sliding scale",
"For DKA 70kg at 0.1 U/kg/hr:\n7 U/hr = 7 mL/hr"],
["Hydrocortisone", "200mg in 48mL NS (4 mg/mL)",
"200 mg/24hr continuous\nor 50mg q6h bolus",
"200mg/24hr = 8.3 mL/hr (4mg/mL)"],
]
story.append(data_table(drip_data[0], drip_data[1:],
col_widths=[3.5*cm, 4*cm, 3.5*cm, 6.5*cm]))
story.append(PageBreak())
# ──────────── SECTION 9: DAILY ICU ROUTINE ────────────
story.append(section_banner("9. DAILY ICU ROUNDS — SYSTEMS-BASED APPROACH", ICU_DARK_BLUE))
story.append(SP(8))
story.append(info_box("Morning ICU Round Checklist — FAST HUGS BID", [
"F — Feeding: Is enteral nutrition running? Target 25–30 kcal/kg/day. NG or OG tube?",
"A — Analgesia: Pain score? NRS ≤3. Opioid review. Multimodal analgesia.",
"S — Sedation: RASS score? Target -1 to 0. SAT performed? Benzodiazepine minimization.",
"T — Thromboembolic prophylaxis: LMWH (enoxaparin) daily? SCDs active? Contraindication?",
"H — Head of bed elevation: ≥30–45° (VAP prevention). Unless contraindicated.",
"U — Ulcer prophylaxis: PPI or H2 blocker for ventilated patients or at-risk patients.",
"G — Glucose control: BSL 6–10 mmol/L. Insulin infusion if >10 mmol/L.",
"S — Spontaneous Breathing Trial (SBT): Is patient ready for weaning? SAT first.",
"B — Bowel care: Last bowel movement? Aperients? NG/OG on free drainage?",
"I — IV line care: All lines still necessary? Change date? CLABSI bundle compliance.",
"D — De-escalation: Can antibiotics be narrowed? Is any line/tube/catheter ready to remove?",
]))
story.append(SP(8))
story.append(Paragraph("9A. Weaning from Ventilator — SBT Protocol", H2))
wean_data = [
["Step", "Criteria", "Action"],
["1. SAT (Spontaneous\nAwakening Trial)", "No active seizures\nNo ETOH withdrawal\nNo high sedation dependency",
"Stop sedation infusion\nAssess awakening within 30 min"],
["2. Screen for SBT", "FiO2 ≤50% AND PEEP ≤8 cmH2O\nSpO2 ≥90%\nHaemodynamically stable\nPatient able to initiate breaths",
"Proceed to SBT if all criteria met"],
["3. SBT Trial\n(30–120 min)", "T-piece or CPAP 5 cmH2O\nor PS 5–7 cmH2O",
"Monitor: RR, SpO2, HR, BP\nSBT failed if: RR>35, SpO2<90%, ↑work of breathing, agitation, ↑CO2"],
["4. SBT Passed", "Tolerates 30–120 min without distress",
"Assess swallow, cough, GCS\nExtubate if all criteria met\nHigh-flow O2 post-extubation"],
["5. SBT Failed", "Criteria for failure above",
"Resume ventilation (supportive settings)\nInvestigate cause\nRetry next day"],
["6. Extubation failure", "Return to ventilation <48h",
"Early tracheostomy consideration if prolonged wean likely"],
]
story.append(data_table(wean_data[0], wean_data[1:],
col_widths=[3*cm, 6*cm, 8.5*cm]))
story.append(SP(8))
story.append(Paragraph("9B. ICU Nutrition Quick Guide", H2))
nutrition_data = [
["Parameter", "Recommendation", "Notes"],
["Energy target", "25–30 kcal/kg/day", "Reduce to 20 kcal/kg in acute phase (day 1–2)"],
["Protein target", "1.2–2 g/kg/day", "Increase to 2 g/kg in burns, trauma, sepsis"],
["Route", "Enteral preferred (NG/OG/NJ)", "Start within 24–48h of ICU admission if gut works"],
["Parenteral nutrition", "Only if enteral contraindicated or insufficient (>60% target unmet >5 days)",
"CVC required\n↑infection risk"],
["Glucose control", "6–10 mmol/L", "Avoid hypoglycaemia (<4) — check q1-2h on insulin"],
["Refeeding Syndrome", "Watch for in malnourished patients restarting feeds",
"Low phosphate, K+, Mg2+ within 24–48h of starting feeds\nSupplement electrolytes"],
]
story.append(data_table(nutrition_data[0], nutrition_data[1:],
col_widths=[4*cm, 5.5*cm, 8*cm]))
story.append(PageBreak())
# ──────────── SECTION 10: TIPS ────────────
story.append(section_banner("10. TOP TIPS FOR THE NEW ICU DOCTOR", colors.HexColor("#7D3C98")))
story.append(SP(8))
tips = [
info_box("Clinical Wisdom", [
"Always examine the patient yourself — never rely solely on numbers. Trends matter more than single values.",
"When in doubt, sit at the bedside for 5 minutes. Most answers become clearer.",
"Write clear orders. Verbal orders in ICU are high-risk for errors.",
"Brief the nursing staff on your concerns — they will call you faster when they are worried.",
"If something doesn't add up, don't dismiss it. Re-examine and get help.",
], bg=colors.HexColor("#F5EEF8"), title_color=colors.HexColor("#7D3C98")),
SP(6),
info_box("Communication Tips", [
"Use ISBAR for all handovers: Identify | Situation | Background | Assessment | Recommendation.",
"When escalating to a senior: know the patient's name, reason for admission, current problem, vitals, and your assessment.",
"Document conversations with consultants — time, name, what was communicated.",
"Talk to families daily. Uncertainty is acceptable — silence is not.",
], bg=colors.HexColor("#EBF5FB"), title_color=ICU_DARK_BLUE),
SP(6),
info_box("Safety Reminders", [
"Check drug doses with pharmacist when unsure — especially renal/hepatic dose adjustments.",
"Triple-check vasopressor concentrations before programming a pump.",
"Always flush a line after medication to ensure full delivery.",
"If a patient deteriorates unexpectedly, call for senior help early. It is never a sign of weakness.",
"Review allergies before every drug order.",
], bg=colors.HexColor("#FDEDEC"), title_color=ICU_RED),
SP(6),
info_box("Wellbeing", [
"ICU is emotionally demanding. Debrief with your team after difficult cases.",
"Eat, drink water, and take breaks. You cannot care for others if you are depleted.",
"Ask questions freely — every ICU consultant was a beginner once.",
], bg=colors.HexColor("#EAFAF1"), title_color=ICU_GREEN),
]
for item in tips:
story.append(item)
story.append(SP(10))
story.append(HRFlowable(width="100%", thickness=1, color=ICU_DARK_BLUE))
story.append(SP(4))
story.append(Paragraph(
"ICU Beginner's Guide v1.0 | June 2026 | "
"Sources: Washington Manual of Medical Therapeutics, Tintinalli's Emergency Medicine, "
"Goldman-Cecil Medicine, Harrison's Internal Medicine 22E, Current Surgical Therapy 14e | "
"For educational purposes — always verify with institution-specific protocols.",
SMALL
))
doc.build(story)
print(f"PDF generated: {OUTPUT}")
if __name__ == "__main__":
build_pdf()
cd /home/daytona/workspace/icu-guide && python3 generate_icu_pdf.py 2>&1
ls -lh /home/daytona/workspace/icu-guide/ICU_Beginners_Guide.pdf
ICU Beginners Guide
PDF Document · PDF