Give notes on mi

Reading File
Finding Sources
Searching PubMed

"myocardial infarction"[MeSH Terms] AND "management"[MeSH Terms]

Reading File
Reading File
Reading File
Reading File
Reading File
Finding Sources
Reading File
Finding Sources
Reading File
I have a comprehensive body of content. Now let me compile the full notes.

Myocardial Infarction (MI) - Complete Notes


1. Definition & Epidemiology

MI (commonly called a "heart attack") is the death of cardiac muscle due to prolonged ischemia. The major underlying cause is atherosclerosis.
  • ~800,000 individuals in the US experience an MI each year (nearly one MI every 40 seconds)
  • Causes almost 400,000 deaths annually
  • 10% occur in people younger than 40 years; 45% in people younger than 65 years
  • Male sex increases relative risk through middle age; females are protected during reproductive years due to estrogen
  • Post-menopausal women lose this protection - IHD is the most common cause of death in older females
  • Post-menopausal hormone replacement therapy is NOT protective and may be detrimental (pro-thrombotic)
  • Robbins, Cotran & Kumar Pathologic Basis of Disease, p. 511

2. Pathogenesis

Step-by-Step Mechanism:

  1. An atheromatous plaque is eroded or suddenly disrupted by endothelial injury, intraplaque hemorrhage, or mechanical forces - exposing subendothelial collagen and necrotic plaque contents to blood
  2. Platelets adhere, aggregate, and are activated - releasing thromboxane A2, ADP, and serotonin - causing further platelet aggregation and vasospasm
  3. Coagulation is activated by tissue factor and other mechanisms, adding to the growing thrombus
  4. Within minutes, the thrombus can completely occlude the coronary artery lumen
Key fact: When angiography is performed within 4 hours of onset, coronary thrombosis is demonstrable in almost 90% of cases. By 12-24 hours, this falls to only ~60% (some thrombi clear spontaneously via lysis or spasm relaxation).

MI Without Typical Atherothrombosis (~10% of cases):

  • Vasospasm - with or without atherosclerosis (e.g., cocaine, ephedrine use)
  • Embolism - from mural thrombus (AF), infective endocarditis vegetations, prosthetic material, or patent foramen ovale
  • Uncommon causes: vasculitis, sickle cell disease, amyloid deposition, aortic dissection, marked LVH (e.g., aortic stenosis), severe hypotension (shock), or inadequate myocardial protection during cardiac surgery
  • Robbins, Cotran & Kumar Pathologic Basis of Disease, p. 511

3. Myocardial Response to Ischemia

TimeEvent
SecondsCessation of aerobic metabolism; inadequate ATP production; accumulation of lactic acid
Within ~1 minuteLoss of myocardial contractility
MinutesUltrastructural changes: myofibrillar relaxation, glycogen depletion, cell/mitochondrial swelling - still reversible
20-30 min of severe ischemia (flow ≤10% normal)Irreversible necrosis begins
6-12 hoursProgressive loss of viability becomes complete
"The benefits of reperfusion are greatest when it is achieved quickly." - Robbins

Why subendocardium is most vulnerable:

  • Last area to receive blood from epicardial vessels
  • Exposed to relatively high intramural pressures (impedes blood inflow)
  • Necrosis begins here and spreads as a "wavefront" outward toward the epicardium

4. Coronary Artery Territory & Infarct Location

ArteryFrequencyArea Infarcted
LAD (Left Anterior Descending)40-50%Anterior wall of LV near apex; anterior ventricular septum; apex circumferentially
RCA (Right Coronary Artery)30-40%Inferior/posterior wall of LV; posterior ventricular septum; inferior/posterior RV free wall
LCX (Left Circumflex)15-20%Lateral wall of LV (except apex)
  • ~80% of individuals have right-dominant circulation (RCA supplies posterior septum)
  • Isolated RV infarction: only 1-3% of cases
  • Atrial infarction is rare

5. Types of Infarction

Transmural Infarction

  • Full wall thickness involvement
  • Associated with epicardial coronary artery occlusion
  • ECG: ST elevation → pathological Q waves
  • Also called STEMI clinically

Subendocardial Infarction

  • Limited to inner one-third to one-half of the ventricular wall
  • More prone to hypotension + diffuse coronary disease (no single occlusion necessary)
  • ECG: ST depression / T wave changes (no Q waves)
  • Also called NSTEMI clinically

6. Morphological (Pathological) Changes Over Time

Table 12.5 from Robbins - Temporal Evolution:
TimeGross ChangesMicroscopic Changes
0-4 hoursNone (unstained pale zone on TTC staining from ~2-3 hrs)None visible on H&E
4-12 hoursReddish-blue (congestion)Early coagulative necrosis; "wavy fibers" (non-infarcted myocardium pulling on necrotic fibers)
12-24 hoursReddish-blue discolorationCoagulative necrosis with pyknosis of nuclei; marginal contraction band necrosis
1-3 daysYellow-tan softeningCoagulative necrosis; neutrophilic infiltration begins
3-7 daysRimmed by a hyperemic zone (yellow center, red-brown border)Dense neutrophilic infiltration; early macrophage infiltration
7-10 daysMaximally soft; yellow-tan; depressed borderMacrophages prominent; granulation tissue at margins
10-14 daysPale gray depression with red-tan rimGranulation tissue with collagen deposition
2-8 weeksGray-white scar (at margins)Increased collagen; reduced cellularity
>2 monthsFirm white scarDense collagen scar; few/no cells

Key Histological Points:

  • TTC stain: Brick-red = viable tissue (intact LDH); Pale/unstained = infarcted tissue (LDH leaked out)
  • Earliest detectable necrosis marker: sarcolemmal membrane disruption → leakage of intracellular proteins (basis for cardiac troponin, CK-MB tests)
  • Contraction band necrosis: characteristic of reperfusion injury - eosinophilic transverse bands of contracted sarcomeres

7. ECG Changes in MI

(From Ganong's Review of Medical Physiology)
Three major membrane abnormalities in infarcted cells cause ECG changes:
Defect in Infarcted CellsCurrent FlowECG Change (leads over infarct)
Rapid repolarization (K+ channel opening)Out of infarctST segment elevation
Decreased resting membrane potential (K+ loss)Into infarct during diastoleTQ depression → recorded as ST elevation
Delayed depolarizationOut of infarctST segment elevation

ECG Evolution:

  1. Hyperacute T waves (first minutes - often missed)
  2. ST elevation (acute phase) - hallmark of STEMI
  3. T wave inversion (hours to days)
  4. Pathological Q waves (days to weeks) - permanent in most cases; indicate electrically silent necrotic tissue
    • Leads opposite the infarct show ST depression (reciprocal changes)

ECG Localization:

TerritoryECG Leads
Anterior (LAD)V1-V4
Anterolateral (LAD + LCX)V4-V6, I, aVL
Inferior (RCA)II, III, aVF
Lateral (LCX)I, aVL, V5-V6
Posterior (RCA/LCX)Tall R in V1-V2 (reciprocal)
Right ventricular (RCA)V1, V3R-V4R

8. Clinical Features

Symptoms:

  • Chest pain: severe, crushing/squeezing, retrosternal, radiating to left arm, jaw, neck, back (epigastric in inferior MI)
  • Duration: >20-30 minutes (unlike stable angina)
  • NOT relieved by nitrates (key differentiator)
  • Associated: diaphoresis, nausea/vomiting, dyspnea, anxiety ("sense of impending doom")
  • Silent MI: ~20-30% (especially in diabetics, elderly, women) - may present with fatigue, dyspnea only

Signs:

  • Anxiety, pallor, diaphoresis
  • Tachycardia (or bradycardia in inferior MI due to vagal stimulation)
  • Hypotension (cardiogenic shock in severe cases)
  • S4 gallop (decreased LV compliance)
  • New murmur (papillary muscle dysfunction, VSD)
  • Lung crepitations (pulmonary edema)

9. Cardiac Biomarkers

MarkerRisesPeaksReturns to NormalNotes
Troponin I/T3-4 hrs24-48 hrs7-14 daysMost sensitive and specific; gold standard
CK-MB4-6 hrs18-24 hrs48-72 hrsUsed to detect re-infarction
Myoglobin1-2 hrs4-6 hrs12-24 hrsFirst to rise, least specific
LDH8-12 hrs24-72 hrs7-10 daysHistorical use; now rarely used
Troponin is the preferred biomarker. High-sensitivity troponin (hs-cTnT/cTnI) allows diagnosis within 1-2 hours.

10. Complications

(From Robbins Pathologic Basis of Disease)
TimeComplication
First 24-72 hoursArrhythmias (most common cause of early death - VF); cardiogenic shock; acute LV failure/pulmonary edema
2-3 daysFibrinous/hemorrhagic pericarditis (Dressler syndrome early form)
3-7 daysFree wall rupture (most common in days 3-7; tamponade); papillary muscle rupture (acute MR); interventricular septal defect
Days-weeksMural thrombus → systemic embolism; LV aneurysm (late complication - dilated, thinned scar)
Weeks-monthsDressler syndrome (autoimmune pericarditis, pleuritis, fever)

"Complications by Mechanism":

  • Contractile dysfunction: pump failure, shock, pulmonary edema
  • Arrhythmias: due to ischemic irritability / conduction system damage (AV block in inferior MI affecting AV node blood supply)
  • Structural rupture: free wall (hemopericardium/tamponade), papillary muscle (acute severe MR), septum (VSD)
  • Expansion/remodeling: early infarct expansion (wall thinning + dilation) → LV aneurysm

11. Management

Immediate (First Hours):

  • MONA (historical mnemonic): Morphine, Oxygen (only if SpO2 <90%), Nitrates, Aspirin
  • Antiplatelet: Aspirin 300 mg loading + P2Y12 inhibitor (clopidogrel, ticagrelor, or prasugrel)
  • Anticoagulation: Heparin (UFH or LMWH) or fondaparinux
  • Reperfusion is the most critical intervention:
    • Primary PCI (percutaneous coronary intervention): preferred if available within 90 minutes of first medical contact ("door-to-balloon time <90 min")
    • Thrombolysis (fibrinolysis): if PCI not available within 120 minutes; streptokinase, alteplase (tPA), tenecteplase - best given within 12 hours of symptom onset

Long-Term Medications (Post-MI):

DrugReason
Aspirin + P2Y12 inhibitor (DAPT x 12 months)Prevent stent thrombosis and recurrent MI
Beta-blockerReduce mortality; prevent arrhythmias; limit infarct size
ACE inhibitor / ARBPrevent LV remodeling; reduce mortality esp. if EF reduced
Statin (high-intensity)Plaque stabilization, LDL reduction
Aldosterone antagonist (eplerenone)If EF ≤40% with HF or diabetes

12. Classification

STEMI (ST-Elevation MI):

  • Complete coronary occlusion
  • Transmural ischemia
  • ST elevation on ECG + positive biomarkers
  • Requires immediate reperfusion

NSTEMI (Non-ST-Elevation MI):

  • Partial/subtotal occlusion
  • Subendocardial ischemia
  • ST depression or T wave changes + elevated troponin (distinguishes from unstable angina)
  • Managed with early invasive strategy (PCI within 24-72 hours based on risk)

Unstable Angina:

  • Plaque disruption with partial occlusion
  • No biomarker rise
  • High risk of progression to MI

13. Key Mnemonics & High-Yield Points

  • "Time is muscle": every 30-minute delay in reperfusion increases mortality by ~7.5%
  • Irreversible necrosis begins after 20-30 min of severe ischemia
  • Full infarct extent achieved within 6-12 hours
  • Most common cause of death early post-MI: ventricular fibrillation
  • Most common cause of death in hospital: pump failure / cardiogenic shock
  • Free wall rupture: peaks 3-7 days (time of maximum neutrophil infiltration/softening)
  • Dressler's syndrome: autoimmune pericarditis, 2-10 weeks post-MI
  • RCA occlusion → inferior MI → may cause AV block (AV node supplied by RCA in 90%)
  • Wavy fibers on histology = earliest microscopic change (4-12 hours)
  • TTC stain: pale/white = infarct (LDH leaks out); brick-red = normal (LDH intact)

Sources: Robbins, Cotran & Kumar Pathologic Basis of Disease; Robbins & Kumar Basic Pathology; Ganong's Review of Medical Physiology (26th ed.); Braunwald's Heart Disease; Goldman-Cecil Medicine

Create a quick reference PDF with ECG changes by MI location

Reading File
Running Command

ls -la /home/daytona/workspace/

Running Command

mkdir -p /home/daytona/workspace/mi-ecg-ref

Writing File

~/mi-ecg-ref/create_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.graphics.shapes import Drawing, Rect, Line, String, Circle, Polygon
from reportlab.graphics import renderPDF
from reportlab.platypus import Flowable
import math

# ─── Colour palette ────────────────────────────────────────────────────────────
RED        = colors.HexColor("#C0392B")
DARK_RED   = colors.HexColor("#922B21")
BLUE       = colors.HexColor("#1A5276")
LIGHT_BLUE = colors.HexColor("#D6EAF8")
TEAL       = colors.HexColor("#1ABC9C")
ORANGE     = colors.HexColor("#E67E22")
PURPLE     = colors.HexColor("#7D3C98")
GREEN      = colors.HexColor("#1E8449")
LIGHT_GREEN= colors.HexColor("#D5F5E3")
LIGHT_RED  = colors.HexColor("#FADBD8")
LIGHT_YELLOW = colors.HexColor("#FEF9E7")
YELLOW     = colors.HexColor("#F39C12")
DARK_GRAY  = colors.HexColor("#2C3E50")
MID_GRAY   = colors.HexColor("#7F8C8D")
LIGHT_GRAY = colors.HexColor("#F2F3F4")
WHITE      = colors.white
BLACK      = colors.black

# ─── ECG Waveform Flowable ─────────────────────────────────────────────────────
class ECGWaveform(Flowable):
    """Draws a schematic ECG strip for a given infarct pattern."""
    def __init__(self, pattern, width=120, height=55, color=RED):
        super().__init__()
        self.pattern = pattern  # 'st_elevation', 'st_depression', 'q_wave', 'hyperacute_t', 'tall_r'
        self.width = width
        self.height = height
        self.color = color

    def wrap(self, *args):
        return self.width, self.height

    def draw(self):
        c = self.canv
        w, h = self.width, self.height
        mid = h / 2

        # Grid background
        c.setFillColor(colors.HexColor("#FDF9F0"))
        c.setStrokeColor(colors.HexColor("#F5CBA7"))
        c.rect(0, 0, w, h, fill=1, stroke=1)

        # Grid lines
        c.setStrokeColor(colors.HexColor("#FADBD8"))
        c.setLineWidth(0.4)
        for x in range(0, int(w)+1, 10):
            c.line(x, 0, x, h)
        for y in range(0, int(h)+1, 10):
            c.line(0, y, w, y)

        # Draw ECG trace
        c.setStrokeColor(self.color)
        c.setLineWidth(1.8)
        c.setLineCap(1)

        p = self.pattern
        path = c.beginPath()

        # Baseline left
        path.moveTo(0, mid)
        path.lineTo(15, mid)

        # P wave
        path.curveTo(16, mid, 18, mid+6, 20, mid+6)
        path.curveTo(22, mid+6, 24, mid, 25, mid)

        # PR segment
        path.lineTo(30, mid)

        if p == 'st_elevation':
            # QRS + elevated ST
            path.lineTo(32, mid)
            path.lineTo(33, mid - 6)   # Q
            path.lineTo(35, mid + 28)  # R
            path.lineTo(37, mid + 10)  # S (elevated)
            path.lineTo(40, mid + 12)  # ST elevated
            path.lineTo(55, mid + 12)  # ST plateau elevated
            path.curveTo(60, mid+12, 62, mid+22, 65, mid+22)  # T peak
            path.curveTo(68, mid+22, 72, mid+8, 76, mid)
            path.lineTo(w, mid)

        elif p == 'st_depression':
            # QRS + depressed ST
            path.lineTo(32, mid)
            path.lineTo(33, mid - 5)
            path.lineTo(35, mid + 26)
            path.lineTo(37, mid - 12)  # deep S
            path.lineTo(40, mid - 10)  # ST depressed
            path.lineTo(55, mid - 9)
            path.curveTo(58, mid-9, 60, mid-3, 63, mid-3)  # inverted T
            path.curveTo(66, mid-3, 70, mid, 75, mid)
            path.lineTo(w, mid)

        elif p == 'q_wave':
            # Pathological Q wave + normal ST
            path.lineTo(31, mid)
            path.lineTo(32, mid - 18)  # deep Q
            path.lineTo(34, mid)
            path.lineTo(35, mid + 22)  # small R
            path.lineTo(37, mid - 2)
            path.lineTo(40, mid)
            path.lineTo(58, mid)
            path.curveTo(60, mid, 62, mid+10, 65, mid+10)
            path.curveTo(68, mid+10, 72, mid, 76, mid)
            path.lineTo(w, mid)

        elif p == 'hyperacute_t':
            # Normal QRS + tall peaked T
            path.lineTo(32, mid)
            path.lineTo(33, mid - 5)
            path.lineTo(35, mid + 25)
            path.lineTo(37, mid - 4)
            path.lineTo(40, mid)
            path.lineTo(50, mid)
            path.curveTo(52, mid, 55, mid+32, 58, mid+32)  # very tall T
            path.curveTo(61, mid+32, 65, mid, 70, mid)
            path.lineTo(w, mid)

        elif p == 'tall_r':
            # Tall R in V1 (posterior MI pattern)
            path.lineTo(32, mid)
            path.lineTo(33, mid + 2)   # no Q
            path.lineTo(36, mid + 30)  # tall R
            path.lineTo(38, mid + 4)   # small S
            path.lineTo(40, mid)
            path.lineTo(52, mid)
            path.curveTo(54, mid, 57, mid+14, 60, mid+14)  # upright T
            path.curveTo(63, mid+14, 68, mid, 73, mid)
            path.lineTo(w, mid)

        elif p == 'normal':
            path.lineTo(32, mid)
            path.lineTo(33, mid - 4)
            path.lineTo(35, mid + 22)
            path.lineTo(37, mid - 3)
            path.lineTo(40, mid)
            path.lineTo(52, mid)
            path.curveTo(54, mid, 57, mid+10, 60, mid+10)
            path.curveTo(63, mid+10, 67, mid, 72, mid)
            path.lineTo(w, mid)

        c.drawPath(path, stroke=1, fill=0)

        # Label
        c.setFont("Helvetica-Bold", 7)
        c.setFillColor(self.color)
        label_map = {
            'st_elevation': 'ST Elevation',
            'st_depression': 'ST Depression',
            'q_wave': 'Pathological Q',
            'hyperacute_t': 'Hyperacute T',
            'tall_r': 'Tall R (V1)',
            'normal': 'Normal'
        }
        c.drawCentredString(w/2, 3, label_map.get(self.pattern, ''))


# ─── Heart Diagram Flowable ────────────────────────────────────────────────────
class HeartZoneDiagram(Flowable):
    """Simple schematic heart with coloured zones."""
    def __init__(self, highlight='anterior', width=130, height=110):
        super().__init__()
        self.highlight = highlight
        self.width = width
        self.height = height

    def wrap(self, *args):
        return self.width, self.height

    def draw(self):
        c = self.canv
        w, h = self.width, self.height

        zone_colors = {
            'anterior':   colors.HexColor("#E74C3C"),
            'inferior':   colors.HexColor("#E67E22"),
            'lateral':    colors.HexColor("#8E44AD"),
            'posterior':  colors.HexColor("#2980B9"),
            'septal':     colors.HexColor("#27AE60"),
            'rv':         colors.HexColor("#F39C12"),
        }
        zone_labels = {
            'anterior':  'Anterior',
            'inferior':  'Inferior',
            'lateral':   'Lateral',
            'posterior': 'Posterior',
            'septal':    'Septal',
            'rv':        'Right Ventricular',
        }

        cx, cy = w/2, h/2 + 5
        rx, ry = 38, 32

        # Base heart oval (LV)
        c.setFillColor(colors.HexColor("#FDFEFE"))
        c.setStrokeColor(DARK_GRAY)
        c.setLineWidth(1.2)
        c.ellipse(cx - rx, cy - ry, cx + rx, cy + ry, fill=1, stroke=1)

        # Highlight zone
        hc = zone_colors.get(self.highlight, RED)
        c.setFillColor(hc)
        c.setStrokeColor(hc)
        c.setLineWidth(0)

        if self.highlight == 'anterior':
            # top-left arc segment
            c.wedge(cx - rx, cy - ry, cx + rx, cy + ry, 60, 120, fill=1, stroke=0)
        elif self.highlight == 'inferior':
            c.wedge(cx - rx, cy - ry, cx + rx, cy + ry, 240, 80, fill=1, stroke=0)
        elif self.highlight == 'lateral':
            c.wedge(cx - rx, cy - ry, cx + rx, cy + ry, 150, 90, fill=1, stroke=0)
        elif self.highlight == 'posterior':
            c.wedge(cx - rx, cy - ry, cx + rx, cy + ry, 260, 60, fill=1, stroke=0)
        elif self.highlight == 'septal':
            # inner right strip
            c.rect(cx - 8, cy - ry + 4, 14, ry*2 - 8, fill=1, stroke=0)
        elif self.highlight == 'rv':
            c.ellipse(cx + rx - 4, cy - 18, cx + rx + 22, cy + 18, fill=1, stroke=0)

        # Redraw heart border
        c.setFillColor(colors.Color(0, 0, 0, 0))
        c.setStrokeColor(DARK_GRAY)
        c.setLineWidth(1.5)
        c.ellipse(cx - rx, cy - ry, cx + rx, cy + ry, fill=0, stroke=1)

        # Septum line
        c.setStrokeColor(colors.HexColor("#7F8C8D"))
        c.setLineWidth(0.8)
        c.setDash([3, 2])
        c.line(cx, cy - ry, cx, cy + ry)
        c.setDash([])

        # RV outline
        c.setStrokeColor(DARK_GRAY)
        c.setLineWidth(1)
        c.ellipse(cx + rx - 4, cy - 18, cx + rx + 22, cy + 18, fill=0, stroke=1)

        # Labels
        c.setFont("Helvetica-Bold", 6.5)
        c.setFillColor(DARK_GRAY)
        c.drawCentredString(cx - 14, cy + ry + 4, "ANT")
        c.drawCentredString(cx - 14, cy - ry - 9, "INF")
        c.setFont("Helvetica", 6)
        c.drawCentredString(cx - rx - 10, cy, "LAT")
        c.drawCentredString(cx + 6, cy + 5, "SEPT")
        c.drawCentredString(cx + rx + 12, cy, "RV")

        # Zone label below
        c.setFont("Helvetica-Bold", 8)
        c.setFillColor(hc)
        c.drawCentredString(w/2, 3, zone_labels.get(self.highlight, ''))


# ─── Build Document ─────────────────────────────────────────────────────────────
def build_pdf(output_path):
    doc = SimpleDocTemplate(
        output_path,
        pagesize=A4,
        rightMargin=15*mm,
        leftMargin=15*mm,
        topMargin=12*mm,
        bottomMargin=12*mm,
    )

    styles = getSampleStyleSheet()

    # Custom styles
    title_style = ParagraphStyle(
        'Title', parent=styles['Normal'],
        fontName='Helvetica-Bold', fontSize=20,
        textColor=WHITE, alignment=TA_CENTER,
        spaceAfter=2,
    )
    subtitle_style = ParagraphStyle(
        'Subtitle', parent=styles['Normal'],
        fontName='Helvetica', fontSize=10,
        textColor=colors.HexColor("#AED6F1"), alignment=TA_CENTER,
        spaceAfter=0,
    )
    section_title = ParagraphStyle(
        'SectionTitle', parent=styles['Normal'],
        fontName='Helvetica-Bold', fontSize=12,
        textColor=WHITE, alignment=TA_LEFT,
        leftIndent=4,
    )
    lead_style = ParagraphStyle(
        'Lead', parent=styles['Normal'],
        fontName='Helvetica-Bold', fontSize=8.5,
        textColor=DARK_GRAY,
    )
    body_style = ParagraphStyle(
        'Body', parent=styles['Normal'],
        fontName='Helvetica', fontSize=8,
        textColor=DARK_GRAY, leading=11,
    )
    small_style = ParagraphStyle(
        'Small', parent=styles['Normal'],
        fontName='Helvetica', fontSize=7,
        textColor=MID_GRAY, leading=10,
    )
    note_style = ParagraphStyle(
        'Note', parent=styles['Normal'],
        fontName='Helvetica-Oblique', fontSize=7.5,
        textColor=colors.HexColor("#5D6D7E"), leading=11,
    )

    story = []

    # ── Header Banner ──────────────────────────────────────────────────────────
    header_data = [[
        Paragraph("🫀 ECG Changes by MI Location", title_style),
    ]]
    header_table = Table(header_data, colWidths=[180*mm])
    header_table.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), BLUE),
        ('ROUNDEDCORNERS', [6, 6, 6, 6]),
        ('TOPPADDING', (0,0), (-1,-1), 10),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 8),
        ('RIGHTPADDING', (0,0), (-1,-1), 8),
    ]))
    story.append(header_table)

    sub_data = [[Paragraph("Quick Reference Card  •  Acute Myocardial Infarction  •  ECG Localization", subtitle_style)]]
    sub_table = Table(sub_data, colWidths=[180*mm])
    sub_table.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), DARK_GRAY),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
    ]))
    story.append(sub_table)
    story.append(Spacer(1, 5*mm))

    # ── ECG Evolution Banner ───────────────────────────────────────────────────
    evo_title = [[Paragraph(" ECG Evolution in STEMI", section_title)]]
    evo_t = Table(evo_title, colWidths=[180*mm])
    evo_t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), RED),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('ROUNDEDCORNERS', [4,4,4,4]),
    ]))
    story.append(evo_t)
    story.append(Spacer(1, 2*mm))

    # Evolution table
    evo_headers = ["Phase", "Timing", "ECG Finding", "Mechanism"]
    evo_rows = [
        evo_headers,
        ["Hyperacute", "0 – 30 min\n(often missed)", "Tall, broad, peaked\nT waves", "Intracellular K+ release\ncauses slow repolarization"],
        ["Acute / Injury", "Min to hrs", "ST elevation ≥1 mm\n(≥2 mm in V1–V3)", "Current of injury —\nthree membrane defects"],
        ["Evolving", "Hrs – 2 days", "T wave inversion;\nST normalising", "Repolarisation changes\nover necrotic zone"],
        ["Established", "Days – weeks", "Pathological Q waves\n(≥40 ms / ≥25% R)", "Electrically silent\nnecrotic tissue"],
        ["Old / Healed", "> 6 weeks", "Persistent Q waves;\nST/T may normalise", "Fibrotic scar;\nno electrical activity"],
    ]

    evo_col = [35*mm, 32*mm, 60*mm, 53*mm]
    evo_table = Table(evo_rows, colWidths=evo_col, repeatRows=1)
    evo_table.setStyle(TableStyle([
        # Header
        ('BACKGROUND', (0,0), (-1,0), DARK_GRAY),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
        ('FONTSIZE', (0,0), (-1,0), 8.5),
        ('ALIGN', (0,0), (-1,0), 'CENTER'),
        # Alternating rows
        ('BACKGROUND', (0,1), (-1,1), LIGHT_RED),
        ('BACKGROUND', (0,2), (-1,2), LIGHT_GRAY),
        ('BACKGROUND', (0,3), (-1,3), LIGHT_RED),
        ('BACKGROUND', (0,4), (-1,4), LIGHT_GRAY),
        ('BACKGROUND', (0,5), (-1,5), LIGHT_RED),
        # All cells
        ('FONTNAME', (0,1), (-1,-1), 'Helvetica'),
        ('FONTSIZE', (0,1), (-1,-1), 8),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('ALIGN', (0,0), (0,-1), 'CENTER'),
        ('ALIGN', (1,0), (1,-1), 'CENTER'),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CACFD2")),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('LEFTPADDING', (0,0), (-1,-1), 5),
        ('RIGHTPADDING', (0,0), (-1,-1), 5),
        # Bold first col
        ('FONTNAME', (0,1), (0,-1), 'Helvetica-Bold'),
        ('TEXTCOLOR', (0,1), (0,-1), RED),
    ]))
    story.append(evo_table)
    story.append(Spacer(1, 5*mm))

    # ── Localization Table ─────────────────────────────────────────────────────
    loc_title = [[Paragraph(" ECG Localization of MI", section_title)]]
    loc_t = Table(loc_title, colWidths=[180*mm])
    loc_t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), BLUE),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('ROUNDEDCORNERS', [4,4,4,4]),
    ]))
    story.append(loc_t)
    story.append(Spacer(1, 2*mm))

    loc_headers = ["MI Territory", "Culprit Artery", "ECG Leads Affected", "Key ECG Changes", "Clinical Pearls"]
    loc_data = [
        loc_headers,
        [
            "ANTERIOR",
            "LAD\n(proximal)",
            "V1, V2, V3, V4",
            "ST↑ V1–V4\nPathological Q V1–V4\nReciprocal ST↓ II, III, aVF",
            "Worst prognosis; large\nLV territory; risk of\nLV failure & VF"
        ],
        [
            "SEPTAL",
            "LAD\n(septal perforators)",
            "V1, V2",
            "ST↑ V1–V2\nLoss of septal Q in\nV5–V6 (early sign)\nNew LBBB possible",
            "Watch for AV block;\nBBB may mask diagnosis;\nnew LBBB = STEMI equivalent"
        ],
        [
            "ANTEROLATERAL",
            "LAD + LCX\nor Diagonal",
            "V4, V5, V6,\nI, aVL",
            "ST↑ V4–V6, I, aVL\nPathological Q waves\nReciprocal ST↓ II, III, aVF",
            "High lateral (I, aVL)\nmay be subtle;\ncheck for diagonal occlusion"
        ],
        [
            "INFERIOR",
            "RCA (80%)\nor LCX (20%)",
            "II, III, aVF",
            "ST↑ II, III, aVF\n(III > II in RCA)\nReciprocal ST↓ I, aVL",
            "Always check V3R/V4R\nfor RV involvement;\nbradycardia/AV block common"
        ],
        [
            "RIGHT VENTRICULAR",
            "RCA (proximal,\nbefore RV branch)",
            "V1, V3R, V4R,\nV5R, V6R",
            "ST↑ V1 ≥1 mm\nST↑ V3R–V4R ≥1 mm\n(most sensitive sign)",
            "AVOID nitrates (↓ preload);\nvolume loading critical;\nusually with inferior MI"
        ],
        [
            "LATERAL",
            "LCX",
            "I, aVL, V5, V6",
            "ST↑ I, aVL, V5–V6\nReciprocal ST↓ V1–V2",
            "May be subtle / missed;\ncheck posterior leads\n(V7–V9) if suspicious"
        ],
        [
            "POSTERIOR",
            "RCA or LCX\n(dominant)",
            "V1–V3\n(Reciprocal)\n+ V7, V8, V9",
            "Tall R V1–V2 (≥0.04s)\nST↓ V1–V3 (≥0.5 mm)\nUpright T V1–V2\nST↑ V7–V9",
            "Most commonly missed;\nalways check posterior\nleads; ST↑ in V7–V9\nconfirms diagnosis"
        ],
    ]

    loc_col_w = [28*mm, 22*mm, 28*mm, 56*mm, 46*mm]
    loc_table = Table(loc_data, colWidths=loc_col_w, repeatRows=1)

    row_colors = [
        colors.HexColor("#FDEDEC"),  # anterior - red tint
        colors.HexColor("#EBF5FB"),  # septal - blue tint
        colors.HexColor("#F4ECF7"),  # anterolateral - purple tint
        colors.HexColor("#FEF9E7"),  # inferior - yellow tint
        colors.HexColor("#E8F8F5"),  # RV - teal tint
        colors.HexColor("#F0F3FF"),  # lateral - lavender
        colors.HexColor("#FDFEFE"),  # posterior - white
    ]

    territory_colors = [
        RED, BLUE, PURPLE, ORANGE, TEAL, colors.HexColor("#5B6BBA"), MID_GRAY
    ]

    loc_table.setStyle(TableStyle([
        # Header
        ('BACKGROUND', (0,0), (-1,0), DARK_GRAY),
        ('TEXTCOLOR', (0,0), (-1,0), WHITE),
        ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
        ('FONTSIZE', (0,0), (-1,0), 8.5),
        ('ALIGN', (0,0), (-1,0), 'CENTER'),
        # Row bgs
        *[('BACKGROUND', (0, i+1), (-1, i+1), row_colors[i]) for i in range(7)],
        # All cells
        ('FONTNAME', (0,1), (-1,-1), 'Helvetica'),
        ('FONTSIZE', (0,1), (-1,-1), 8),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CACFD2")),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 5),
        ('RIGHTPADDING', (0,0), (-1,-1), 5),
        # Territory col bold + colored
        *[('FONTNAME', (0, i+1), (0, i+1), 'Helvetica-Bold') for i in range(7)],
        *[('TEXTCOLOR', (0, i+1), (0, i+1), territory_colors[i]) for i in range(7)],
        # Align territory
        ('ALIGN', (0,1), (0,-1), 'CENTER'),
        ('ALIGN', (1,1), (1,-1), 'CENTER'),
        ('ALIGN', (2,1), (2,-1), 'CENTER'),
    ]))
    story.append(loc_table)
    story.append(Spacer(1, 5*mm))

    # ── ECG Waveforms Row ──────────────────────────────────────────────────────
    wave_title = [[Paragraph(" Characteristic ECG Waveform Patterns", section_title)]]
    wave_t = Table(wave_title, colWidths=[180*mm])
    wave_t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), colors.HexColor("#117A65")),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('ROUNDEDCORNERS', [4,4,4,4]),
    ]))
    story.append(wave_t)
    story.append(Spacer(1, 2*mm))

    wave_patterns = [
        ('hyperacute_t', 'Hyperacute T', TEAL,    '0–30 min\nEarly STEMI'),
        ('st_elevation', 'ST Elevation',  RED,     'Acute phase\nSTEMI hallmark'),
        ('st_depression','ST Depression', ORANGE,  'Reciprocal changes\nor NSTEMI'),
        ('q_wave',       'Pathological Q', PURPLE, 'Established\ninfarct'),
        ('tall_r',       'Tall R (V1)',   BLUE,    'Posterior MI\nreciprocal'),
    ]

    wform_cells = []
    label_cells = []
    for pat, lbl, col, desc in wave_patterns:
        wform_cells.append(ECGWaveform(pat, width=120, height=55, color=col))
        label_cells.append(Paragraph(f"<b><font color='#{col.hexval()[2:]}'>■</font> {lbl}</b><br/><font size='7'>{desc}</font>", body_style))

    wave_row = Table(
        [wform_cells, label_cells],
        colWidths=[36*mm]*5,
    )
    wave_row.setStyle(TableStyle([
        ('ALIGN', (0,0), (-1,-1), 'CENTER'),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 3),
        ('BOTTOMPADDING', (0,0), (-1,-1), 3),
        ('BACKGROUND', (0,0), (-1,-1), LIGHT_GRAY),
        ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#D5D8DC")),
    ]))
    story.append(wave_row)
    story.append(Spacer(1, 5*mm))

    # ── Quick Tip Boxes Row ────────────────────────────────────────────────────
    tip_title = [[Paragraph(" High-Yield Clinical Pearls", section_title)]]
    tip_t = Table(tip_title, colWidths=[180*mm])
    tip_t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), ORANGE),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('ROUNDEDCORNERS', [4,4,4,4]),
    ]))
    story.append(tip_t)
    story.append(Spacer(1, 2*mm))

    tips = [
        ("🔴 STEMI Definition",
         "• ST↑ ≥1 mm in ≥2 contiguous limb leads\n"
         "• ST↑ ≥2 mm in ≥2 contiguous precordial leads\n"
         "• New LBBB with ischemic symptoms = STEMI equivalent\n"
         "• Posterior ST↑ ≥0.5 mm in V7–V9",
         LIGHT_RED, RED),
        ("🟠 Reciprocal Changes",
         "• Inferior MI: ST↓ in I, aVL (reciprocal)\n"
         "• Anterior MI: ST↓ in II, III, aVF (reciprocal)\n"
         "• Posterior MI: ST↓ V1–V3 is the primary finding\n"
         "• Reciprocal changes confirm MI (vs pericarditis)",
         LIGHT_YELLOW, ORANGE),
        ("🟣 Mimics & Pitfalls",
         "• LBBB masks Q waves & ST changes\n"
         "• LVH: ST↑ in V1–V3 (strain pattern)\n"
         "• Pericarditis: diffuse ST↑, concave, no Q waves\n"
         "• Brugada: coved ST↑ V1–V3, no ischaemia hx\n"
         "• Benign early repolarisation: notched J-point",
         colors.HexColor("#F5EEF8"), PURPLE),
        ("🔵 Special Situations",
         "• RV MI: IV fluids, avoid nitrates & diuretics\n"
         "• Posterior MI: flip V1–V3 (ST↓ + tall R = ST↑ + Q)\n"
         "• LAD 'De Winter' pattern: upsloping ST↓ + tall T\n"
         "• Wellens syndrome: deep symmetric T V2–V3 = LAD\n"
         "• Aslanger pattern: inferior MI + lateral involvement",
         LIGHT_BLUE, BLUE),
    ]

    tip_rows = []
    for t_title, t_body, bg, tc in tips:
        cell_data = [
            [Paragraph(f"<b>{t_title}</b>", ParagraphStyle('TH', fontName='Helvetica-Bold',
                fontSize=8, textColor=tc, spaceAfter=3))],
            [Paragraph(t_body.replace('\n', '<br/>'), ParagraphStyle('TB', fontName='Helvetica',
                fontSize=7.5, textColor=DARK_GRAY, leading=11))],
        ]
        cell_table = Table(cell_data, colWidths=[42*mm])
        cell_table.setStyle(TableStyle([
            ('BACKGROUND', (0,0), (-1,-1), bg),
            ('BOX', (0,0), (-1,-1), 1, tc),
            ('TOPPADDING', (0,0), (-1,-1), 5),
            ('BOTTOMPADDING', (0,0), (-1,-1), 5),
            ('LEFTPADDING', (0,0), (-1,-1), 5),
            ('RIGHTPADDING', (0,0), (-1,-1), 5),
            ('ROUNDEDCORNERS', [4,4,4,4]),
        ]))
        tip_rows.append(cell_table)

    tips_row = Table([tip_rows], colWidths=[45.5*mm]*4)
    tips_row.setStyle(TableStyle([
        ('ALIGN', (0,0), (-1,-1), 'LEFT'),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
        ('LEFTPADDING', (0,0), (-1,-1), 0),
        ('RIGHTPADDING', (0,0), (-1,-1), 2),
    ]))
    story.append(tips_row)
    story.append(Spacer(1, 5*mm))

    # ── Artery → Territory → Leads Quick Grid ─────────────────────────────────
    art_title = [[Paragraph(" Coronary Artery → Territory → Leads at a Glance", section_title)]]
    art_t = Table(art_title, colWidths=[180*mm])
    art_t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), DARK_GRAY),
        ('TOPPADDING', (0,0), (-1,-1), 4),
        ('BOTTOMPADDING', (0,0), (-1,-1), 4),
        ('ROUNDEDCORNERS', [4,4,4,4]),
    ]))
    story.append(art_t)
    story.append(Spacer(1, 2*mm))

    art_data = [
        [
            Paragraph("<b>LAD</b>", ParagraphStyle('AH', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
            Paragraph("<b>RCA</b>", ParagraphStyle('AH', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
            Paragraph("<b>LCX</b>", ParagraphStyle('AH', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
        ],
        [
            Paragraph("Anterior + Septal\n<font size='8' color='red'>V1 – V4</font>", ParagraphStyle('AC', fontName='Helvetica', fontSize=8, textColor=DARK_GRAY, alignment=TA_CENTER, leading=12)),
            Paragraph("Inferior + Posterior + RV\n<font size='8' color='orange'>II, III, aVF + V3R/V4R</font>", ParagraphStyle('AC', fontName='Helvetica', fontSize=8, textColor=DARK_GRAY, alignment=TA_CENTER, leading=12)),
            Paragraph("Lateral + Posterior\n<font size='8' color='purple'>I, aVL, V5, V6</font>", ParagraphStyle('AC', fontName='Helvetica', fontSize=8, textColor=DARK_GRAY, alignment=TA_CENTER, leading=12)),
        ],
        [
            Paragraph("40–50% of MIs", ParagraphStyle('AS', fontName='Helvetica-Oblique', fontSize=7.5, textColor=MID_GRAY, alignment=TA_CENTER)),
            Paragraph("30–40% of MIs", ParagraphStyle('AS', fontName='Helvetica-Oblique', fontSize=7.5, textColor=MID_GRAY, alignment=TA_CENTER)),
            Paragraph("15–20% of MIs", ParagraphStyle('AS', fontName='Helvetica-Oblique', fontSize=7.5, textColor=MID_GRAY, alignment=TA_CENTER)),
        ],
    ]

    art_table = Table(art_data, colWidths=[60*mm, 60*mm, 60*mm])
    art_table.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (0,0), RED),
        ('BACKGROUND', (1,0), (1,0), ORANGE),
        ('BACKGROUND', (2,0), (2,0), PURPLE),
        ('BACKGROUND', (0,1), (0,1), LIGHT_RED),
        ('BACKGROUND', (1,1), (1,1), LIGHT_YELLOW),
        ('BACKGROUND', (2,1), (2,1), colors.HexColor("#F5EEF8")),
        ('BACKGROUND', (0,2), (-1,2), LIGHT_GRAY),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CACFD2")),
        ('ALIGN', (0,0), (-1,-1), 'CENTER'),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
    ]))
    story.append(art_table)
    story.append(Spacer(1, 5*mm))

    # ── Footer ─────────────────────────────────────────────────────────────────
    footer_data = [[
        Paragraph(
            "<font size='7' color='#AEB6BF'>Sources: Robbins Pathologic Basis of Disease | Ganong's Review of Medical Physiology | "
            "Braunwald's Heart Disease   •   Created with Orris Medical AI</font>",
            ParagraphStyle('Footer', fontName='Helvetica', fontSize=7, textColor=MID_GRAY, alignment=TA_CENTER)
        )
    ]]
    footer_table = Table(footer_data, colWidths=[180*mm])
    footer_table.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), DARK_GRAY),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
    ]))
    story.append(footer_table)

    doc.build(story)
    print(f"PDF saved to: {output_path}")


if __name__ == "__main__":
    build_pdf("/home/daytona/workspace/mi-ecg-ref/MI_ECG_Quick_Reference.pdf")
Running Command

cd /home/daytona/workspace/mi-ecg-ref && python create_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/mi-ecg-ref/MI_ECG_Quick_Reference.pdf

Your quick reference PDF is ready:

MI ECG Quick Reference

PDF Document · PDF


What's inside the PDF (single A4 page):
  1. ECG Evolution in STEMI - a table covering all 5 phases from hyperacute T waves (0-30 min) through to the healed scar, with timing, ECG findings, and mechanism
  2. ECG Localization Table - all 7 MI territories with colour-coded rows:
    • Anterior (LAD), Septal (LAD perforators), Anterolateral (LAD+LCX), Inferior (RCA/LCX), Right Ventricular (proximal RCA), Lateral (LCX), Posterior (RCA/LCX dominant)
    • Culprit artery, exact leads affected, ECG changes, and clinical pearls for each
  3. Characteristic ECG Waveform Diagrams - 5 schematic ECG strips drawn to scale: Hyperacute T, ST Elevation, ST Depression, Pathological Q wave, Tall R (posterior MI)
  4. High-Yield Clinical Pearls - 4 colour-coded boxes covering STEMI definition criteria, reciprocal change logic, mimics/pitfalls (LBBB, LVH, pericarditis, Brugada), and special situations (RV MI, De Winter, Wellens, Aslanger)
  5. Coronary Artery at-a-Glance Grid - LAD / RCA / LCX with territory, leads, and frequency of each
This is a shared conversation. Sign in to Orris to start your own chat.