Make a note for cardiac system

Asking for Preferences
Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Running Command

mkdir -p /home/daytona/workspace/cardiac-note && ls /home/daytona/workspace/cardiac-note/

Writing File

~/cardiac-note/generate_cardiac_pdf.py

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, ListFlowable, ListItem, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate
from reportlab.lib.colors import HexColor

OUTPUT = "/home/daytona/workspace/cardiac-note/Cardiac_System_Nursing_Notes.pdf"

# ── Colour palette ──────────────────────────────────────────────────────────
RED       = HexColor("#C0392B")
DARK_RED  = HexColor("#922B21")
BLUE      = HexColor("#1A5276")
LIGHT_BLUE= HexColor("#D6EAF8")
MED_BLUE  = HexColor("#2E86C1")
TEAL      = HexColor("#1ABC9C")
LIGHT_TEAL= HexColor("#D1F2EB")
ORANGE    = HexColor("#E67E22")
LIGHT_ORG = HexColor("#FDEBD0")
PURPLE    = HexColor("#7D3C98")
LIGHT_PUR = HexColor("#E8DAEF")
GREEN     = HexColor("#1E8449")
LIGHT_GRN = HexColor("#D5F5E3")
YELLOW    = HexColor("#F1C40F")
LIGHT_YEL = HexColor("#FEF9E7")
GREY_BG   = HexColor("#F2F3F4")
DARK_GREY = HexColor("#2C3E50")
MID_GREY  = HexColor("#7F8C8D")

# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

def s(name, **kw):
    return ParagraphStyle(name, parent=styles['Normal'], **kw)

TITLE_STYLE = s('Title', fontSize=26, textColor=colors.white,
                alignment=TA_CENTER, leading=32, fontName='Helvetica-Bold')
SUBTITLE_STYLE = s('Subtitle', fontSize=12, textColor=HexColor("#D6EAF8"),
                   alignment=TA_CENTER, leading=16, fontName='Helvetica')
H1 = s('H1', fontSize=15, textColor=colors.white,
        fontName='Helvetica-Bold', leading=20, spaceAfter=4)
H2 = s('H2', fontSize=12, textColor=DARK_GREY,
        fontName='Helvetica-Bold', leading=16, spaceBefore=8, spaceAfter=4)
H3 = s('H3', fontSize=11, textColor=BLUE,
        fontName='Helvetica-Bold', leading=14, spaceBefore=6, spaceAfter=3)
BODY = s('Body', fontSize=10, leading=14, textColor=DARK_GREY,
         fontName='Helvetica', spaceAfter=4, alignment=TA_JUSTIFY)
BODY_BOLD = s('BodyBold', fontSize=10, leading=14, textColor=DARK_GREY,
              fontName='Helvetica-Bold', spaceAfter=2)
BULLET = s('Bullet', fontSize=10, leading=14, textColor=DARK_GREY,
           leftIndent=14, bulletIndent=0, spaceAfter=2)
SMALL = s('Small', fontSize=9, leading=12, textColor=MID_GREY,
          fontName='Helvetica-Oblique')
TABLE_HDR = s('TblHdr', fontSize=9, textColor=colors.white,
              fontName='Helvetica-Bold', alignment=TA_CENTER, leading=12)
TABLE_CELL = s('TblCell', fontSize=9, textColor=DARK_GREY,
               fontName='Helvetica', alignment=TA_LEFT, leading=12)
TABLE_CELL_C = s('TblCellC', fontSize=9, textColor=DARK_GREY,
                 fontName='Helvetica', alignment=TA_CENTER, leading=12)
WARNING = s('Warning', fontSize=10, leading=14, textColor=RED,
            fontName='Helvetica-Bold', spaceAfter=4)
NOTE = s('Note', fontSize=9, leading=13, textColor=DARK_GREY,
         fontName='Helvetica-Oblique', leftIndent=8)

def para(text, style=BODY):
    return Paragraph(text, style)

def bullet(text, style=BULLET):
    return Paragraph(f"• {text}", style)

def sp(h=0.2):
    return Spacer(1, h * cm)

def hr(color=BLUE, thickness=1):
    return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=4)

def section_header(title, bg_color=BLUE):
    data = [[Paragraph(title, H1)]]
    t = Table(data, colWidths=[17.5*cm])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), bg_color),
        ('ROUNDEDCORNERS', [6]),
        ('TOPPADDING', (0,0), (-1,-1), 8),
        ('BOTTOMPADDING', (0,0), (-1,-1), 8),
        ('LEFTPADDING', (0,0), (-1,-1), 14),
        ('RIGHTPADDING', (0,0), (-1,-1), 8),
    ]))
    return t

def info_box(title, items, bg=LIGHT_BLUE, border=MED_BLUE):
    rows = [[Paragraph(title, s('IH', parent=H2, textColor=border,
                                 fontName='Helvetica-Bold', fontSize=10))]]
    for item in items:
        rows.append([Paragraph(f"• {item}", TABLE_CELL)])
    t = Table(rows, colWidths=[16.5*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), (0,0), 6),
        ('BOTTOMPADDING', (0,0), (0,0), 2),
        ('TOPPADDING', (0,1), (-1,-1), 2),
        ('BOTTOMPADDING', (0,1), (-1,-1), 2),
        ('BOTTOMPADDING', (0,-1), (-1,-1), 6),
        ('BOX', (0,0), (-1,-1), 1, border),
        ('ROUNDEDCORNERS', [4]),
    ]))
    return t

def two_col_table(headers, rows, col_widths=None, hdr_bg=BLUE):
    if col_widths is None:
        col_widths = [8.5*cm, 8.5*cm]
    hdr_row = [Paragraph(h, TABLE_HDR) for h in headers]
    data = [hdr_row]
    for row in rows:
        data.append([Paragraph(str(c), TABLE_CELL) for c in row])
    t = Table(data, colWidths=col_widths)
    n = len(data)
    style = [
        ('BACKGROUND', (0,0), (-1,0), hdr_bg),
        ('BACKGROUND', (0,1), (-1,-1), colors.white),
        ('GRID', (0,0), (-1,-1), 0.5, HexColor("#BDC3C7")),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('RIGHTPADDING', (0,0), (-1,-1), 6),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]
    for i in range(1, n, 2):
        style.append(('BACKGROUND', (0,i), (-1,i), GREY_BG))
    t.setStyle(TableStyle(style))
    return t

def multi_col_table(headers, rows, col_widths, hdr_bg=BLUE):
    hdr_row = [Paragraph(h, TABLE_HDR) for h in headers]
    data = [hdr_row]
    for row in rows:
        data.append([Paragraph(str(c), TABLE_CELL) for c in row])
    t = Table(data, colWidths=col_widths)
    n = len(data)
    style = [
        ('BACKGROUND', (0,0), (-1,0), hdr_bg),
        ('BACKGROUND', (0,1), (-1,-1), colors.white),
        ('GRID', (0,0), (-1,-1), 0.5, HexColor("#BDC3C7")),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 5),
        ('RIGHTPADDING', (0,0), (-1,-1), 5),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]
    for i in range(1, n, 2):
        style.append(('BACKGROUND', (0,i), (-1,i), GREY_BG))
    t.setStyle(TableStyle(style))
    return t

# ── Cover page helper ────────────────────────────────────────────────────────
def cover_page():
    elements = []
    # Red banner
    data = [[Paragraph("CARDIAC SYSTEM", TITLE_STYLE),
             Paragraph("Nursing Study Notes", SUBTITLE_STYLE),
             Paragraph("Comprehensive Review • 2026", SUBTITLE_STYLE)]]
    # flatten into rows
    banner_rows = [
        [Paragraph("CARDIAC SYSTEM", TITLE_STYLE)],
        [Paragraph("Nursing Study Notes", SUBTITLE_STYLE)],
        [Paragraph("Comprehensive Review  •  June 2026", SUBTITLE_STYLE)],
    ]
    t = Table(banner_rows, colWidths=[17.5*cm])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), RED),
        ('TOPPADDING', (0,0), (0,0), 30),
        ('BOTTOMPADDING', (0,-1), (-1,-1), 30),
        ('TOPPADDING', (0,1), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-2), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 20),
        ('RIGHTPADDING', (0,0), (-1,-1), 20),
    ]))
    elements.append(t)
    elements.append(sp(0.6))

    # Topics covered box
    topics = [
        "1. Anatomy of the Heart",
        "2. Cardiac Physiology & Blood Flow",
        "3. Cardiac Cycle",
        "4. Conduction System & Action Potential",
        "5. ECG Basics & Interpretation",
        "6. Common Cardiac Diseases",
        "7. Cardiac Pharmacology",
        "8. Nursing Assessments & Interventions",
    ]
    rows = [[Paragraph("Topics Covered", s('TC', parent=H2, textColor=RED, fontSize=12,
                                             fontName='Helvetica-Bold'))]]
    for t_ in topics:
        rows.append([Paragraph(t_, TABLE_CELL)])
    tbl = Table(rows, colWidths=[17.5*cm])
    tbl.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), LIGHT_BLUE),
        ('LEFTPADDING', (0,0), (-1,-1), 16),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('BOX', (0,0), (-1,-1), 1.5, MED_BLUE),
    ]))
    elements.append(tbl)
    elements.append(sp(0.5))
    elements.append(para("Reference: Braunwald's Heart Disease (11e) • Fuster and Hurst's The Heart (15e)", SMALL))
    elements.append(PageBreak())
    return elements

# ─────────────────────────────────────────────────────────────────────────────
# BUILD DOCUMENT
# ─────────────────────────────────────────────────────────────────────────────
def build():
    doc = SimpleDocTemplate(
        OUTPUT,
        pagesize=A4,
        leftMargin=2*cm, rightMargin=2*cm,
        topMargin=2*cm, bottomMargin=2*cm,
        title="Cardiac System – Nursing Notes",
        author="Orris Medical Study Aid",
    )
    E = []  # elements list

    # ── COVER ─────────────────────────────────────────────────────────────────
    E += cover_page()

    # ═══════════════════════════════════════════════════════════════════════════
    # 1. ANATOMY
    # ═══════════════════════════════════════════════════════════════════════════
    E.append(section_header("1.  ANATOMY OF THE HEART", RED))
    E.append(sp(0.3))

    E.append(para(
        "The heart is a hollow, muscular organ located in the <b>mediastinum</b> of the thoracic cavity, "
        "slightly left of the midline. It is enclosed in a double-walled sac called the <b>pericardium</b>. "
        "The adult heart weighs approximately 250–350 g.", BODY))
    E.append(sp(0.2))

    E.append(para("<b>Layers of the Heart Wall</b>", H2))
    E.append(multi_col_table(
        ["Layer", "Location", "Description"],
        [
            ["Epicardium", "Outermost", "Visceral layer of pericardium; contains coronary vessels and fat"],
            ["Myocardium", "Middle", "Thick cardiac muscle; responsible for pumping action"],
            ["Endocardium", "Innermost", "Smooth inner lining of chambers and valves; continuous with blood vessel endothelium"],
        ],
        [4*cm, 4*cm, 9.5*cm], hdr_bg=RED
    ))
    E.append(sp(0.3))

    E.append(para("<b>Four Chambers</b>", H2))
    E.append(multi_col_table(
        ["Chamber", "Wall Thickness", "Function"],
        [
            ["Right Atrium (RA)", "Thin", "Receives deoxygenated blood from SVC, IVC, and coronary sinus"],
            ["Right Ventricle (RV)", "Moderate", "Pumps deoxygenated blood to lungs via pulmonary artery"],
            ["Left Atrium (LA)", "Thin", "Receives oxygenated blood from 4 pulmonary veins"],
            ["Left Ventricle (LV)", "Thick (12–15 mm)", "Pumps oxygenated blood to systemic circulation; generates highest pressure"],
        ],
        [3.5*cm, 4*cm, 10*cm], hdr_bg=RED
    ))
    E.append(sp(0.3))

    E.append(para("<b>Heart Valves</b>", H2))
    E.append(multi_col_table(
        ["Valve", "Type", "Location", "Function"],
        [
            ["Tricuspid", "Atrioventricular (AV)", "Between RA and RV", "Prevents backflow from RV → RA"],
            ["Pulmonary (Pulmonic)", "Semilunar", "RV → Pulmonary artery", "Prevents backflow from PA → RV"],
            ["Mitral (Bicuspid)", "Atrioventricular (AV)", "Between LA and LV", "Prevents backflow from LV → LA"],
            ["Aortic", "Semilunar", "LV → Aorta", "Prevents backflow from Aorta → LV"],
        ],
        [3.5*cm, 4*cm, 5*cm, 5*cm], hdr_bg=RED
    ))
    E.append(sp(0.3))

    E.append(para("<b>Coronary Arteries</b>", H2))
    E.append(two_col_table(
        ["Artery", "Areas Supplied"],
        [
            ["Left Anterior Descending (LAD)", "Anterior LV wall, interventricular septum, apex — 'Widow maker'"],
            ["Left Circumflex (LCx)", "Lateral and posterior LV wall, LA"],
            ["Right Coronary Artery (RCA)", "RV, inferior LV wall, SA node (60%), AV node (85–90%)"],
        ],
        hdr_bg=RED
    ))
    E.append(sp(0.2))
    E.append(info_box("Nursing Key Point — Heart Sounds",
        ["S1 ('lub') = Closure of mitral & tricuspid (AV) valves — marks start of systole",
         "S2 ('dub') = Closure of aortic & pulmonary (semilunar) valves — marks start of diastole",
         "S3 = Ventricular gallop — early diastole; normal in young; pathological in heart failure (HF)",
         "S4 = Atrial gallop — late diastole; suggests reduced ventricular compliance (hypertension, HCM)"],
        bg=LIGHT_GRN, border=GREEN))

    E.append(PageBreak())

    # ═══════════════════════════════════════════════════════════════════════════
    # 2. PHYSIOLOGY & BLOOD FLOW
    # ═══════════════════════════════════════════════════════════════════════════
    E.append(section_header("2.  CARDIAC PHYSIOLOGY & BLOOD FLOW", DARK_RED))
    E.append(sp(0.3))

    E.append(para("<b>Pulmonary vs. Systemic Circulation</b>", H2))
    E.append(two_col_table(
        ["Pulmonary Circulation", "Systemic Circulation"],
        [
            ["RV → Pulmonary artery → Lungs → Pulmonary veins → LA",
             "LV → Aorta → Body tissues → Venae cavae → RA"],
            ["Low pressure (15–25/8–12 mmHg)", "High pressure (120/80 mmHg)"],
            ["Gas exchange: CO₂ out, O₂ in", "Delivers O₂ & nutrients; removes CO₂ & waste"],
        ],
        hdr_bg=DARK_RED
    ))
    E.append(sp(0.3))

    E.append(para("<b>Key Haemodynamic Parameters</b>", H2))
    E.append(multi_col_table(
        ["Parameter", "Normal Value", "Definition / Significance"],
        [
            ["Heart Rate (HR)", "60–100 bpm", "Number of cardiac contractions per minute"],
            ["Stroke Volume (SV)", "60–100 mL/beat", "Volume ejected per contraction"],
            ["Cardiac Output (CO)", "4–8 L/min", "CO = HR × SV"],
            ["Ejection Fraction (EF)", ">55%", "% of end-diastolic volume ejected per beat; key in HF assessment"],
            ["Preload", "LVEDP 8–12 mmHg", "Ventricular filling pressure; determined by venous return"],
            ["Afterload", "SVR 800–1200 dyne·s/cm⁵", "Resistance the LV must overcome to eject blood"],
            ["Cardiac Index (CI)", "2.5–4.0 L/min/m²", "CO adjusted for body surface area"],
        ],
        [4*cm, 4*cm, 9.5*cm], hdr_bg=DARK_RED
    ))
    E.append(sp(0.3))

    E.append(para("<b>Frank-Starling Law</b>", H3))
    E.append(para(
        "As ventricular <b>end-diastolic volume (preload)</b> increases, the myocardium stretches, "
        "leading to a stronger subsequent contraction and higher stroke volume — up to a physiological limit. "
        "This is the basis for fluid resuscitation in hypotension.", BODY))
    E.append(sp(0.2))

    E.append(para("<b>Factors Affecting Cardiac Output</b>", H3))
    E.append(two_col_table(
        ["Increases CO", "Decreases CO"],
        [
            ["Increased HR (sympathetic, exercise)", "Bradycardia, heart block"],
            ["Increased preload (fluid loading)", "Hypovolaemia, diuretics"],
            ["Increased contractility (catecholamines, digoxin)", "Negative inotropes (beta-blockers, CCBs)"],
            ["Decreased afterload (vasodilators)", "Increased afterload (hypertension, stenosis)"],
        ],
        hdr_bg=DARK_RED
    ))
    E.append(sp(0.2))
    E.append(info_box("Nursing Key Point — Monitoring Haemodynamics",
        ["Monitor BP, HR, SpO₂ regularly — report HR <60 or >100, SBP <90 or >180 mmHg",
         "Assess for signs of low CO: cool/clammy skin, confusion, decreased urine output (<0.5 mL/kg/hr), hypotension",
         "Daily weights: 1 kg gain = ~1 L fluid retention — critical in HF management"],
        bg=LIGHT_BLUE, border=MED_BLUE))

    E.append(PageBreak())

    # ═══════════════════════════════════════════════════════════════════════════
    # 3. CARDIAC CYCLE
    # ═══════════════════════════════════════════════════════════════════════════
    E.append(section_header("3.  THE CARDIAC CYCLE", TEAL))
    E.append(sp(0.3))
    E.append(para(
        "The cardiac cycle represents the sequence of events in one complete heartbeat (~0.8 seconds at 75 bpm), "
        "divided into <b>systole</b> (contraction) and <b>diastole</b> (relaxation).", BODY))
    E.append(sp(0.2))

    E.append(multi_col_table(
        ["Phase", "Event", "Valves", "Pressure"],
        [
            ["1. Isovolumetric Contraction", "Ventricles start contracting; no volume change",
             "All valves CLOSED", "LV pressure rising rapidly"],
            ["2. Rapid Ejection", "Aortic & pulmonic valves open; blood ejected",
             "Semilunar OPEN; AV CLOSED", "LV pressure peaks (~120 mmHg)"],
            ["3. Reduced Ejection", "Slower ejection as pressure gradient decreases",
             "Semilunar OPEN", "LV pressure begins to fall"],
            ["4. Isovolumetric Relaxation", "Ventricles relax; no volume change",
             "All valves CLOSED", "LV pressure drops rapidly"],
            ["5. Rapid Ventricular Filling", "Mitral/tricuspid open; passive filling",
             "AV valves OPEN", "Low ventricular pressure"],
            ["6. Slow Filling (Diastasis)", "Slow passive filling", "AV valves OPEN", "Equalising pressures"],
            ["7. Atrial Systole ('Atrial Kick')", "Atria contract; final 20–30% filling",
             "AV valves OPEN", "Slight pressure rise"],
        ],
        [4*cm, 4.5*cm, 4.5*cm, 4.5*cm], hdr_bg=TEAL
    ))
    E.append(sp(0.3))

    E.append(info_box("Nursing Key Point — Atrial Kick",
        ["Atrial fibrillation (AF) eliminates the atrial kick, reducing CO by up to 25–30%",
         "This is why patients in AF with poor LV function can decompensate rapidly",
         "Assess rhythm regularly; rate-control vs. rhythm-control is a key clinical decision"],
        bg=LIGHT_TEAL, border=TEAL))

    E.append(PageBreak())

    # ═══════════════════════════════════════════════════════════════════════════
    # 4. CONDUCTION SYSTEM
    # ═══════════════════════════════════════════════════════════════════════════
    E.append(section_header("4.  CONDUCTION SYSTEM & ACTION POTENTIAL", ORANGE))
    E.append(sp(0.3))

    E.append(para("<b>Normal Conduction Pathway</b>", H2))
    pathway_data = [
        ["1", "SA Node", "Right atrial wall near SVC", "60–100/min", "Pacemaker of the heart"],
        ["2", "AV Node", "Interatrial septum (Koch's triangle)", "40–60/min", "Delays impulse 0.1 sec to allow atrial filling"],
        ["3", "Bundle of His", "Upper interventricular septum", "—", "Transmits impulse to ventricles"],
        ["4", "Right & Left Bundle Branches", "Along interventricular septum", "—", "Distribute impulse to each ventricle"],
        ["5", "Purkinje Fibres", "Ventricular myocardium", "20–40/min", "Rapid conduction; ensures synchronised ventricular contraction"],
    ]
    E.append(multi_col_table(
        ["Step", "Structure", "Location", "Intrinsic Rate", "Function"],
        pathway_data,
        [1*cm, 3.5*cm, 4*cm, 2.5*cm, 6.5*cm], hdr_bg=ORANGE
    ))
    E.append(sp(0.3))

    E.append(para("<b>Cardiac Action Potential (Ventricular Myocyte)</b>", H2))
    ap_data = [
        ["Phase 0", "Rapid Depolarisation", "Fast Na⁺ channels OPEN — Na⁺ rushes in"],
        ["Phase 1", "Early Repolarisation", "Na⁺ channels close; transient K⁺ outflow"],
        ["Phase 2", "Plateau", "Ca²⁺ influx (slow channels) balances K⁺ outflow — unique to cardiac muscle"],
        ["Phase 3", "Rapid Repolarisation", "Ca²⁺ channels close; K⁺ rapidly exits"],
        ["Phase 4", "Resting Membrane Potential", "Na⁺/K⁺ ATPase restores balance (−90 mV in ventricular cells)"],
    ]
    E.append(multi_col_table(
        ["Phase", "Name", "Ion Movement"],
        ap_data,
        [2*cm, 5*cm, 10.5*cm], hdr_bg=ORANGE
    ))
    E.append(sp(0.2))
    E.append(info_box("Nursing Key Point — Refractory Period",
        ["The long refractory period (Phase 2 plateau) prevents re-stimulation during contraction — protective against tetanic contractions",
         "Hypokalaemia shortens repolarisation → risk of arrhythmia; hyperkalaemia prolongs it → risk of bradycardia/asystole",
         "Monitor K⁺ levels in patients on diuretics (furosemide) or digoxin — target K⁺ 3.5–5.0 mmol/L"],
        bg=LIGHT_ORG, border=ORANGE))

    E.append(PageBreak())

    # ═══════════════════════════════════════════════════════════════════════════
    # 5. ECG
    # ═══════════════════════════════════════════════════════════════════════════
    E.append(section_header("5.  ECG BASICS & INTERPRETATION", PURPLE))
    E.append(sp(0.3))

    E.append(para("<b>ECG Waveform Components</b>", H2))
    ecg_data = [
        ["P wave", "0.06–0.12 s; <2.5 mm", "Atrial depolarisation (SA node firing → atrial contraction)"],
        ["PR interval", "0.12–0.20 s", "AV node conduction time; prolonged in heart block"],
        ["QRS complex", "<0.12 s; <25 mm", "Ventricular depolarisation; wide = bundle branch block or VT"],
        ["ST segment", "Isoelectric", "Ventricular plateau; elevation = STEMI; depression = ischaemia"],
        ["T wave", "Upright (I, II, V4–6)", "Ventricular repolarisation; inversion = ischaemia; peaked = hyperkalaemia"],
        ["QT interval", "QTc < 0.44 s (male), <0.46 s (female)", "Total ventricular electrical activity; prolonged = Torsades de Pointes risk"],
    ]
    E.append(multi_col_table(
        ["Component", "Normal Values", "Clinical Significance"],
        ecg_data,
        [3.5*cm, 5*cm, 9*cm], hdr_bg=PURPLE
    ))
    E.append(sp(0.3))

    E.append(para("<b>Common ECG Rhythms — Nursing Recognition</b>", H2))
    rhythm_data = [
        ["Normal Sinus Rhythm (NSR)", "60–100 bpm, regular, P before each QRS", "Normal"],
        ["Sinus Bradycardia", "<60 bpm, regular, P before each QRS", "Consider if symptomatic; atropine 0.5 mg IV"],
        ["Sinus Tachycardia", ">100 bpm, regular", "Treat cause (pain, fever, hypovolaemia, anxiety)"],
        ["Atrial Fibrillation (AF)", "Irregularly irregular, no distinct P waves, wavy baseline", "Rate control (beta-blockers, digoxin); anticoagulation"],
        ["Atrial Flutter", "Regular ~150 bpm, sawtooth P waves (300/min), 2:1 block", "Rate/rhythm control; cardioversion"],
        ["1° AV Block", "PR >0.20 s, regular", "Monitor; usually benign"],
        ["2° AV Block (Mobitz I)", "Progressive PR lengthening until QRS dropped", "Monitor; may need pacing if symptomatic"],
        ["2° AV Block (Mobitz II)", "Constant PR, sudden QRS drop", "High risk → pacemaker usually needed"],
        ["3° (Complete) AV Block", "No relationship between P waves & QRS", "Emergency pacing required"],
        ["Ventricular Tachycardia (VT)", ">3 wide QRS beats >100 bpm", "Pulseless: CPR + defibrillation; with pulse: amiodarone"],
        ["Ventricular Fibrillation (VF)", "Chaotic, no organised activity", "CPR + immediate defibrillation (200J)"],
        ["Asystole", "Flat line", "CPR + adrenaline (epinephrine) 1 mg IV every 3–5 min"],
    ]
    E.append(multi_col_table(
        ["Rhythm", "ECG Features", "Nursing Action"],
        rhythm_data,
        [4*cm, 6*cm, 7.5*cm], hdr_bg=PURPLE
    ))

    E.append(PageBreak())

    # ═══════════════════════════════════════════════════════════════════════════
    # 6. COMMON CARDIAC DISEASES
    # ═══════════════════════════════════════════════════════════════════════════
    E.append(section_header("6.  COMMON CARDIAC DISEASES", MED_BLUE))
    E.append(sp(0.3))

    # 6a - MI
    E.append(para("<b>A. Myocardial Infarction (MI / Heart Attack)</b>", H2))
    E.append(para(
        "<b>Definition:</b> Irreversible myocardial cell death due to prolonged ischaemia, usually from plaque rupture "
        "and coronary artery occlusion.", BODY))
    E.append(sp(0.1))
    E.append(two_col_table(
        ["STEMI", "NSTEMI"],
        [
            ["Complete occlusion of coronary artery", "Partial occlusion / demand ischaemia"],
            ["ST elevation ≥1 mm in ≥2 contiguous leads", "ST depression, T-wave inversion, or normal ECG"],
            ["Troponin elevated (may take 3–6h)", "Troponin elevated"],
            ["Target: Reperfusion within 90 min (PCI) or 30 min (thrombolysis)", "Medical management ± urgent PCI"],
        ],
        hdr_bg=MED_BLUE
    ))
    E.append(sp(0.15))
    E.append(info_box("MONA-B Mnemonic (Initial MI Management)",
        ["M – Morphine (4–8 mg IV; for unrelieved pain — use cautiously)",
         "O – Oxygen (only if SpO₂ <94%; avoid hyperoxia)",
         "N – Nitrates (GTN sublingual/IV for pain — contraindicated in hypotension, RV infarct, PDE5 inhibitor use)",
         "A – Aspirin 300 mg stat (loading dose) + Ticagrelor/Clopidogrel (dual antiplatelet)",
         "B – Beta-blocker (oral, once stable; reduces myocardial O₂ demand)"],
        bg=LIGHT_BLUE, border=MED_BLUE))
    E.append(sp(0.2))

    # 6b - HF
    E.append(para("<b>B. Heart Failure (HF)</b>", H2))
    E.append(para(
        "<b>Definition:</b> Inability of the heart to pump sufficient blood to meet the body's metabolic needs. "
        "Classified by ejection fraction: <b>HFrEF</b> (EF <40%), <b>HFmrEF</b> (40–49%), <b>HFpEF</b> (EF ≥50%).", BODY))
    E.append(sp(0.1))
    E.append(two_col_table(
        ["Left Heart Failure (LHF)", "Right Heart Failure (RHF)"],
        [
            ["Backward failure → pulmonary oedema", "Backward failure → systemic venous congestion"],
            ["Dyspnoea, orthopnoea, PND, crackles", "Peripheral oedema, JVD, hepatomegaly, ascites"],
            ["Pink frothy sputum (acute pulmonary oedema)", "Weight gain, right upper quadrant pain"],
            ["CXR: Cardiomegaly, Kerley B lines, bat-wing infiltrates", "CXR: Cardiomegaly, pleural effusions"],
        ],
        hdr_bg=MED_BLUE
    ))
    E.append(sp(0.15))
    E.append(para("<b>NYHA Classification</b>", H3))
    E.append(multi_col_table(
        ["Class", "Symptoms", "Clinical"],
        [
            ["I", "No symptoms with ordinary activity", "Asymptomatic HF"],
            ["II", "Slight limitation; comfortable at rest", "Mild HF"],
            ["III", "Marked limitation; comfortable at rest only", "Moderate HF"],
            ["IV", "Symptoms at rest; unable to carry on any activity", "Severe HF"],
        ],
        [2*cm, 8*cm, 7.5*cm], hdr_bg=MED_BLUE
    ))
    E.append(sp(0.2))

    # 6c - Hypertension
    E.append(para("<b>C. Hypertension (HTN)</b>", H2))
    E.append(multi_col_table(
        ["Stage", "Systolic (mmHg)", "Diastolic (mmHg)", "Action"],
        [
            ["Normal", "<120", "<80", "Lifestyle only"],
            ["Elevated", "120–129", "<80", "Lifestyle modification"],
            ["Stage 1 HTN", "130–139", "80–89", "Lifestyle ± medication"],
            ["Stage 2 HTN", "≥140", "≥90", "Medication + lifestyle"],
            ["Hypertensive Crisis", "≥180", "≥120", "Immediate medical intervention"],
        ],
        [3*cm, 3.5*cm, 3.5*cm, 7.5*cm], hdr_bg=MED_BLUE
    ))
    E.append(sp(0.2))

    # 6d - Other conditions
    E.append(para("<b>D. Other Common Conditions</b>", H2))
    other_cond = [
        ["Angina Pectoris", "Stable: exertional chest pain relieved by rest/GTN; Unstable: at rest, increasing severity — ACS until proved otherwise",
         "Rest, GTN, O₂, ECG, troponin; aspirin; refer if unstable"],
        ["Atrial Fibrillation (AF)", "Irregular pulse, palpitations, dyspnoea, embolic risk; commonest sustained arrhythmia",
         "Rate/rhythm control; anticoagulation (CHA₂DS₂-VASc ≥1); stroke prevention"],
        ["Cardiogenic Shock", "SBP <90 mmHg, cold/clammy, confusion, oliguria despite adequate filling — severe pump failure",
         "IV inotropes (dobutamine), vasopressors (noradrenaline), IABP, urgent revascularisation"],
        ["Cardiac Arrest", "Pulseless, unresponsive, apnoeic — VF/VT (shockable) or PEA/Asystole (non-shockable)",
         "CPR 30:2, defibrillation (shockable), adrenaline 1 mg IV, treat reversible causes (4Hs & 4Ts)"],
        ["Infective Endocarditis", "Fever, new murmur, embolic phenomena, Osler nodes, Janeway lesions, Roth spots",
         "Blood cultures x3 before antibiotics; prolonged IV antibiotics; echo for vegetation"],
    ]
    E.append(multi_col_table(
        ["Condition", "Key Features", "Initial Management"],
        other_cond,
        [4*cm, 7*cm, 6.5*cm], hdr_bg=MED_BLUE
    ))

    E.append(PageBreak())

    # ═══════════════════════════════════════════════════════════════════════════
    # 7. PHARMACOLOGY
    # ═══════════════════════════════════════════════════════════════════════════
    E.append(section_header("7.  CARDIAC PHARMACOLOGY", GREEN))
    E.append(sp(0.3))

    drug_classes = [
        ("A. Beta-Blockers (β-Blockers)", [
            ["Drug (Example)", "Mechanism", "Indications", "Key Nursing Points"],
            [
                ["Metoprolol, Atenolol, Carvedilol, Bisoprolol",
                 "Block β1 (and β2) adrenoreceptors → ↓ HR, ↓ contractility, ↓ BP, ↓ renin release",
                 "HTN, Angina, MI, HFrEF, AF rate control, Arrhythmias",
                 "Monitor HR (hold if <60 bpm), BP; do NOT stop abruptly (rebound); caution in asthma/COPD; check glucose in diabetics"],
            ]
        ]),
        ("B. ACE Inhibitors (ACEi)", [
            ["Drug (Example)", "Mechanism", "Indications", "Key Nursing Points"],
            [
                ["Ramipril, Lisinopril, Enalapril, Perindopril",
                 "Inhibit ACE → ↓ Angiotensin II → vasodilation, ↓ aldosterone, ↓ preload & afterload",
                 "HTN, HFrEF, post-MI, diabetic nephropathy",
                 "Monitor BP (1st dose hypotension), K⁺ (hyperkalaemia), creatinine (renal function); persistent dry cough → switch to ARB; contraindicated in pregnancy"],
            ]
        ]),
        ("C. Angiotensin Receptor Blockers (ARBs)", [
            ["Drug (Example)", "Mechanism", "Indications", "Key Nursing Points"],
            [
                ["Losartan, Valsartan, Candesartan",
                 "Block AT1 receptors directly → similar effects to ACEi but without bradykinin (no cough)",
                 "HTN, HFrEF (if ACEi-intolerant), post-MI",
                 "Monitor BP, K⁺, renal function; contraindicated in pregnancy; do NOT combine with ACEi routinely"],
            ]
        ]),
        ("D. Diuretics", [
            ["Drug (Example)", "Mechanism", "Indications", "Key Nursing Points"],
            [
                ["Furosemide (loop), Spironolactone (K⁺-sparing), Hydrochlorothiazide (thiazide)",
                 "Loop: Inhibit Na⁺/K⁺/2Cl⁻ in ascending limb; Thiazide: Inhibit NaCl in DCT; Spiro: Aldosterone antagonist",
                 "HF (fluid overload), HTN, oedema, hyperaldosteronism",
                 "Monitor fluid balance, daily weight, electrolytes (K⁺ esp.); furosemide → hypokalaemia; spironolactone → hyperkalaemia; monitor creatinine"],
            ]
        ]),
        ("E. Calcium Channel Blockers (CCBs)", [
            ["Drug (Example)", "Mechanism", "Indications", "Key Nursing Points"],
            [
                ["Amlodipine (DHP), Diltiazem, Verapamil (non-DHP)",
                 "Block L-type Ca²⁺ channels; DHP: primarily vascular smooth muscle → vasodilation; Non-DHP: also cardiac (↓ HR, ↓ AV conduction)",
                 "HTN, Angina, AF rate control (diltiazem/verapamil), vasospastic angina",
                 "DHP: monitor for ankle oedema, flushing, headache; Non-DHP: DO NOT combine with beta-blockers (risk of complete heart block); monitor HR/PR interval"],
            ]
        ]),
        ("F. Nitrates", [
            ["Drug (Example)", "Mechanism", "Indications", "Key Nursing Points"],
            [
                ["GTN (sublingual, IV, patch), Isosorbide mononitrate",
                 "Release NO → venous & arterial dilation → ↓ preload & afterload → ↓ myocardial O₂ demand",
                 "Angina (acute & chronic), Acute HF, STEMI",
                 "Headache is common initially; tolerance develops with continuous use — provide 8–12 h nitrate-free period for patches; contraindicated with PDE5 inhibitors (sildenafil); hold if SBP <90 mmHg"],
            ]
        ]),
        ("G. Antiplatelets & Anticoagulants", [
            ["Drug (Example)", "Mechanism", "Indications", "Key Nursing Points"],
            [
                ["Aspirin, Clopidogrel, Ticagrelor (antiplatelet); Warfarin, Apixaban, Rivaroxaban (anticoagulant)",
                 "Antiplatelets: inhibit platelet aggregation (COX-1, P2Y12); Anticoagulants: inhibit clotting cascade (Vit K-dependent factors, Xa, thrombin)",
                 "ACS/MI (DAPT), AF (anticoagulation), DVT/PE, mechanical valves",
                 "Bleeding risk — assess skin, stool, urine for blood; do not give NSAIDs with aspirin; DOAC — no routine INR monitoring but check renal function; warfarin — target INR 2–3 (AF), 2.5–3.5 (mechanical valves)"],
            ]
        ]),
        ("H. Digoxin", [
            ["Drug (Example)", "Mechanism", "Indications", "Key Nursing Points"],
            [
                ["Digoxin",
                 "Inhibits Na⁺/K⁺ ATPase → ↑ intracellular Ca²⁺ → ↑ contractility; also ↑ vagal tone → ↓ HR & AV conduction",
                 "HFrEF with AF (rate control), AF rate control",
                 "NARROW THERAPEUTIC INDEX (0.5–2 ng/mL); toxicity: nausea, vomiting, visual changes (yellow/green halos), bradycardia, AV block; hold if HR <60; hypokalaemia and renal impairment increase toxicity risk"],
            ]
        ]),
        ("I. Antiarrhythmics (Vaughan Williams Classes)", [
            ["Class / Drug", "Mechanism", "Use"],
            [
                ["Ia: Quinidine, Procainamide", "Na⁺ channel block (intermediate)", "VT, AF, VF"],
                ["Ib: Lidocaine, Mexiletine", "Na⁺ channel block (fast)", "Ventricular arrhythmias"],
                ["Ic: Flecainide, Propafenone", "Na⁺ channel block (slow)", "AF, SVT (avoid in structural heart disease)"],
                ["II: Beta-blockers", "β-adrenoreceptor block", "SVT, VT, rate control"],
                ["III: Amiodarone, Sotalol", "K⁺ channel block → ↑ action potential duration", "VT, VF, AF — amiodarone is most effective broad-spectrum"],
                ["IV: Verapamil, Diltiazem", "Ca²⁺ channel block (non-DHP)", "SVT, AF rate control"],
                ["Adenosine (unclassified)", "AV nodal block (transient)", "First-line for SVT termination"],
            ]
        ]),
    ]

    for title, table_data in drug_classes:
        E.append(para(f"<b>{title}</b>", H2))
        hdrs = table_data[0]
        rows = table_data[1]
        if len(hdrs) == 4:
            E.append(multi_col_table(hdrs, rows, [3.5*cm, 4.5*cm, 4*cm, 5.5*cm], hdr_bg=GREEN))
        elif len(hdrs) == 3:
            if title.startswith("I."):
                E.append(multi_col_table(hdrs, rows, [5*cm, 7*cm, 5.5*cm], hdr_bg=GREEN))
            else:
                E.append(multi_col_table(hdrs, rows, [4*cm, 7*cm, 6.5*cm], hdr_bg=GREEN))
        E.append(sp(0.2))

    E.append(PageBreak())

    # ═══════════════════════════════════════════════════════════════════════════
    # 8. NURSING ASSESSMENT & INTERVENTIONS
    # ═══════════════════════════════════════════════════════════════════════════
    E.append(section_header("8.  NURSING ASSESSMENTS & INTERVENTIONS", DARK_GREY))
    E.append(sp(0.3))

    E.append(para("<b>Cardiovascular Assessment — IPPA Approach</b>", H2))
    E.append(multi_col_table(
        ["Step", "Action", "What to Assess"],
        [
            ["Inspection", "Observe patient", "JVD (raised >4 cm above sternal angle = elevated CVP), peripheral oedema, cyanosis, skin colour/temperature, chest deformities, capillary refill (normal <2 sec)"],
            ["Palpation", "Feel", "Apex beat (5th ICS, MCL), peripheral pulses (rate, rhythm, volume, character), pitting oedema grade"],
            ["Percussion", "Tap", "Cardiac dullness borders; lung fields for pleural effusion (stony dull)"],
            ["Auscultation", "Listen", "Heart sounds (S1, S2, extra sounds, murmurs); lung fields (crackles = pulmonary oedema, wheeze = bronchospasm)"],
        ],
        [2.5*cm, 3*cm, 12*cm], hdr_bg=DARK_GREY
    ))
    E.append(sp(0.3))

    E.append(para("<b>Critical Nursing Observations</b>", H2))
    E.append(multi_col_table(
        ["Observation", "Normal", "Action if Abnormal"],
        [
            ["Blood Pressure", "100–140 / 60–90 mmHg", "SBP <90: fluid challenge/vasopressors; SBP >180: antihypertensives; report both"],
            ["Heart Rate", "60–100 bpm", "HR <60 (symptomatic): atropine; HR >150: investigate rhythm; defibrillate if pulseless VT/VF"],
            ["SpO₂", "≥94% (≥88% in COPD)", "Supplemental O₂; target 94–98%; mask if severe"],
            ["Urine Output", ">0.5 mL/kg/hr", "Oliguria suggests ↓ CO or AKI; notify doctor; fluid balance review"],
            ["ECG", "Sinus rhythm, normal intervals", "Print 12-lead; escalate per rhythm; continuous monitoring in ACS/arrhythmia"],
            ["Troponin", "<0.04 ng/mL (hs-Troponin)", "Elevated at 0 & 3h = myocardial injury; serial measurements; treat as ACS"],
            ["BNP / NT-proBNP", "BNP <100 pg/mL", "Elevated in HF; higher = worse prognosis; guides diuretic therapy"],
        ],
        [4*cm, 3.5*cm, 10*cm], hdr_bg=DARK_GREY
    ))
    E.append(sp(0.3))

    E.append(para("<b>4 Hs and 4 Ts — Reversible Causes of Cardiac Arrest</b>", H2))
    E.append(two_col_table(
        ["4 Hs", "4 Ts"],
        [
            ["Hypoxia", "Tension Pneumothorax"],
            ["Hypovolaemia", "Tamponade (Cardiac)"],
            ["Hypo/Hyperkalaemia (+ other metabolic)", "Toxins (drugs/overdose)"],
            ["Hypothermia", "Thrombosis (PE or Coronary)"],
        ],
        hdr_bg=DARK_GREY
    ))
    E.append(sp(0.3))

    E.append(para("<b>Patient Education Checklist</b>", H2))
    E.append(info_box("Discharge Teaching Topics",
        ["Medication compliance: explain each drug, timing, side effects, importance of NOT stopping suddenly",
         "Diet: low sodium (<2 g/day in HF), Mediterranean diet, limit saturated fats and alcohol",
         "Activity: gradual return; cardiac rehab referral post-MI/HF; report exertional symptoms",
         "Weight monitoring: daily weights; report >2 kg gain in 2 days (fluid retention)",
         "Smoking cessation: most modifiable risk factor — refer to cessation programme",
         "BP and glucose monitoring at home (HTN/DM patients)",
         "When to seek emergency care: chest pain, sudden dyspnoea, syncope, palpitations, oedema"],
        bg=LIGHT_GRN, border=GREEN))
    E.append(sp(0.3))

    # Quick reference: Murmurs
    E.append(para("<b>Common Cardiac Murmurs — Quick Reference</b>", H2))
    E.append(multi_col_table(
        ["Murmur", "Timing", "Best Heard", "Radiation", "Cause"],
        [
            ["Aortic Stenosis (AS)", "Systolic ejection (crescendo-decrescendo)", "Right 2nd ICS", "Carotids", "Calcified aortic valve; most common in elderly"],
            ["Aortic Regurgitation (AR)", "Early diastolic (decrescendo)", "Left 3rd/4th ICS (Erb's point)", "—", "Rheumatic fever, aortic dissection, infective endocarditis"],
            ["Mitral Stenosis (MS)", "Mid-diastolic, low-pitched", "Apex (left lateral decubitus)", "—", "Rheumatic heart disease; 'rumble' with opening snap"],
            ["Mitral Regurgitation (MR)", "Pansystolic (holosystolic)", "Apex", "Axilla", "Mitral valve prolapse, ischaemic papillary muscle dysfunction"],
        ],
        [3.5*cm, 4*cm, 3.5*cm, 2.5*cm, 4*cm], hdr_bg=DARK_GREY
    ))

    E.append(sp(0.5))
    E.append(hr(DARK_GREY))
    E.append(para(
        "<i>Sources: Braunwald's Heart Disease 11e (Elsevier) • Fuster and Hurst's The Heart 15e (McGraw-Hill) • "
        "AHA/ACC 2022 Guidelines • ESC 2023 Guidelines. These notes are intended as a study aid — "
        "always consult current clinical guidelines for patient care.</i>",
        s('Footer', parent=SMALL, fontSize=8, textColor=MID_GREY, alignment=TA_CENTER)
    ))

    # ── BUILD ─────────────────────────────────────────────────────────────────
    doc.build(E)
    print(f"PDF created: {OUTPUT}")

if __name__ == "__main__":
    build()
Running Command

cd /home/daytona/workspace/cardiac-note && python generate_cardiac_pdf.py 2>&1

Editing File

~/cardiac-note/generate_cardiac_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/cardiac-note/generate_cardiac_pdf.py'
Searching Content

"s('IH', parent=" in ~/cardiac-note

Editing File

~/cardiac-note/generate_cardiac_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/cardiac-note/generate_cardiac_pdf.py'
Editing File

~/cardiac-note/generate_cardiac_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/cardiac-note/generate_cardiac_pdf.py'
Running Command

cd /home/daytona/workspace/cardiac-note && python generate_cardiac_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/cardiac-note/Cardiac_System_Nursing_Notes.pdf

Your PDF is ready! Download it here:

Cardiac System Nursing Notes

PDF Document · PDF


Here's what the note covers across 8 sections:
SectionContents
1. AnatomyHeart wall layers, 4 chambers, 4 valves, coronary arteries, heart sounds (S1–S4)
2. Physiology & Blood FlowPulmonary vs. systemic circulation, haemodynamic parameters (CO, SV, EF, preload, afterload), Frank-Starling law
3. Cardiac Cycle7 phases from isovolumetric contraction to atrial kick, valve states, pressures, atrial fibrillation impact
4. Conduction SystemSA → AV → Bundle of His → Purkinje pathway, intrinsic rates, ventricular action potential phases (0–4) with ion movements
5. ECG BasicsNormal waveform values (P, PR, QRS, ST, T, QT), 12 common rhythms with ECG features and nursing actions
6. Cardiac DiseasesMI (STEMI vs. NSTEMI, MONA-B), Heart Failure (LHF vs. RHF, NYHA), HTN staging, Angina, AF, Cardiogenic Shock, Arrest, Endocarditis
7. PharmacologyBeta-blockers, ACEi, ARBs, Diuretics, CCBs, Nitrates, Antiplatelets/Anticoagulants, Digoxin, Antiarrhythmics (Vaughan Williams Classes I–IV + Adenosine)
8. Nursing AssessmentsIPPA cardiovascular assessment, critical observations with action thresholds, 4Hs & 4Ts, discharge education, murmur guide
This is a shared conversation. Sign in to Orris to start your own chat.