Common heart disorder with ecg and explanation

Reading File
Finding Sources
Finding Sources
Searching Images

ECG electrocardiogram common heart disorders arrhythmia

Finding Sources
Finding Sources
Finding Sources
Searching Images

atrial fibrillation ECG 12 lead

Reading File
Searching Images

myocardial infarction STEMI ST elevation ECG

Searching Images

heart block complete AV block third degree ECG

Searching Images

ventricular tachycardia ECG wide complex tachycardia

Searching Images

left bundle branch block right bundle branch block ECG pattern

I now have excellent ECG images and content. Let me compile a comprehensive, well-illustrated guide to common heart disorders with their ECG findings.

Common Heart Disorders: ECG Findings & Explanations

Understanding the ECG is central to diagnosing cardiac conditions. Below are the most clinically important heart disorders, each with their characteristic ECG pattern, explanation, and a real ECG example.

1. πŸ«€ Atrial Fibrillation (AF)

The most common sustained cardiac arrhythmia β€” affects over 33 million people worldwide.

Mechanism

Chaotic, disorganized electrical firing from multiple foci within the atria (often near the pulmonary vein ostia) replaces the coordinated P-wave generated by the sinoatrial node. The AV node is bombarded with impulses at 350–600/min and conducts them irregularly to the ventricles.

ECG Features

FeatureFinding
P wavesAbsent β€” replaced by fine fibrillatory (f) waves
RhythmIrregularly irregular R-R intervals
QRSNarrow (<120 ms) unless aberrant conduction
RateVariable; rapid if uncontrolled (>100 bpm = AF with RVR)

Clinical Significance

  • Reduces cardiac output by ~20% (loss of atrial "kick")
  • High stroke risk (Virchow's triad: stasis in left atrial appendage)
  • Rate control: beta-blockers, calcium channel blockers, digoxin
  • Anticoagulation: warfarin or DOACs (dabigatran, rivaroxaban, apixaban)
Atrial Fibrillation ECG β€” classic irregularly irregular rhythm with absent P waves
Classic AF: absent P waves, fine fibrillatory baseline, irregularly irregular narrow QRS complexes with rapid ventricular response.

2. ❀️‍πŸ”₯ ST-Elevation Myocardial Infarction (STEMI)

A cardiac emergency requiring immediate reperfusion (door-to-balloon <90 min).

Mechanism

Complete occlusion of a coronary artery (most commonly the Left Anterior Descending = LAD) causes transmural ischemia. Injured myocytes alter their ion channel behavior, producing the characteristic ST changes.

ECG Features β€” Evolving Sequence

StageECG Finding
Hyperacute (minutes)Tall, peaked (hyperacute) T waves
Acute (hours)ST elevation β‰₯1 mm in β‰₯2 contiguous leads; convex ("tombstone") morphology
EstablishedQ waves develop (>40 ms, >25% of R height)
Reperfusion/oldT-wave inversion, persistent Q waves

Localization by Lead

TerritoryLeads with ST ElevationArtery
AnteriorV1–V4LAD
InferiorII, III, aVFRCA
LateralI, aVL, V5–V6LCx
PosteriorTall R in V1–V2 + ST depressionRCA/LCx
STEMI β€” anterior wall ST elevation ECG
Acute anterior STEMI: convex ST elevation in V1–V6 (greatest in V2–V4), consistent with LAD occlusion. Note reciprocal changes in inferior leads.

3. 🚨 Complete (Third-Degree) AV Block

Life-threatening conduction failure β€” the atria and ventricles beat independently.

Mechanism

No impulses pass from the atria through the AV node to the ventricles. The ventricles maintain themselves via a slow escape rhythm (junctional at 40–60 bpm, or ventricular at 20–40 bpm).

ECG Features

FeatureFinding
P wavesPresent, regular, at normal atrial rate (~60–100/min)
QRSPresent, regular, but SLOWER and independent of P waves
PR intervalNo fixed PR interval β€” complete AV dissociation
QRS widthNarrow if junctional escape; wide (>120 ms) if ventricular escape

Classic Sign

"P waves marching through QRS complexes" β€” P waves appear before, within, and after QRS complexes with no consistent relationship.
Complete (Third-Degree) AV Block ECG
Complete heart block: regular P waves and regular (but slower, wide) QRS complexes occurring independently β€” classic AV dissociation pattern.

Management

Urgent pacing (transcutaneous β†’ permanent pacemaker).

4. ⚑ Ventricular Tachycardia (VT)

A life-threatening ventricular arrhythmia, especially in structural heart disease.

Mechanism

A reentrant circuit or automatic focus within the ventricular myocardium fires rapidly (>100 bpm), bypassing the normal His-Purkinje system β†’ wide, aberrant QRS complexes.

ECG Features

FeatureFinding
Rate100–250 bpm
RhythmRegular
QRSWide (>120 ms), bizarre morphology
P wavesMay be dissociated (AV dissociation) or absent
Fusion/capture beatsPathognomonic when present

Brugada Criteria (VT vs SVT with aberrancy)

  • AV dissociation β†’ VT
  • QRS >160 ms β†’ VT
  • Concordance (all QRS same direction V1–V6) β†’ VT
Wide-Complex Ventricular Tachycardia ECG
Monomorphic VT: rapid rate, wide bizarre QRS complexes (~200 ms), no clear P waves β€” this is a medical emergency.

5. πŸ”€ Bundle Branch Blocks (BBB)

Conduction delay in either the left (LBBB) or right (RBBB) bundle branch causes delayed ventricular activation.

Right Bundle Branch Block (RBBB)

  • QRS β‰₯120 ms
  • rSR' ("rabbit ears") in V1
  • Broad slurred S wave in leads I, V5, V6
  • Secondary T-wave inversion in V1–V3
  • Causes: pulmonary embolism, ASD, right heart strain

Left Bundle Branch Block (LBBB)

  • QRS β‰₯120 ms
  • Broad notched R wave in V5–V6, I, aVL
  • Deep QS or rS in V1
  • No septal Q waves in lateral leads
  • New LBBB = treat as STEMI equivalent
RBBB vs LBBB QRS-T patterns in V1 and V6
Harrison's diagram comparing normal QRS-T morphology (top) vs RBBB (middle: rSR' in V1, broad S in V6) vs LBBB (bottom: broad R in V6, deep S/QS in V1).

6. πŸ“ˆ Comparative Summary Table

DisorderRateRhythmP WavesQRSKey Feature
Atrial FibrillationVariableIrregularly irregularAbsent (f waves)NarrowNo P waves
STEMINormalRegularNormalNormal (early)ST elevation β‰₯1 mm
3Β° AV Block20–60Regular (escape)Present, unrelatedWide or narrowAV dissociation
Ventricular Tachycardia100–250RegularDissociatedWide >120 msWide-complex tachycardia
RBBBNormalRegularNormalWide (rSR' V1)Rabbit ears in V1
LBBBNormalRegularNormalWide (notched R)Broad R in V5/V6

Quick ECG Reading Framework

  1. Rate β€” count R-R intervals (300 Γ· large squares)
  2. Rhythm β€” regular or irregular?
  3. P waves β€” present? morphology? relationship to QRS?
  4. PR interval β€” 120–200 ms (3–5 small squares)
  5. QRS duration β€” <120 ms = narrow; β‰₯120 ms = wide
  6. ST segment β€” elevation or depression?
  7. T waves β€” peaked, inverted, or biphasic?
  8. QT interval β€” corrected QTc <440 ms (male), <460 ms (female)
Sources: Braunwald's Heart Disease (10th ed.); Harrison's Principles of Internal Medicine (21st ed.)

With images

Loading Image
Loading Image
Loading Image
Loading Image
Loading Image
Loading Image
All 6 ECG images are now loaded. Here is the complete illustrated guide:

Common Heart Disorders β€” ECG with Images & Explanation


1. πŸ«€ Atrial Fibrillation (AF)

Atrial Fibrillation ECG

What you see on the ECG

  • No P waves β€” replaced by a chaotic, irregular fibrillatory baseline (best seen in V1 and lead II)
  • Irregularly irregular R-R intervals (no two beats are equally spaced)
  • Narrow QRS complexes (unless aberrant conduction exists)
  • Rapid ventricular rate (here ~120 bpm = AF with rapid ventricular response)

Why it happens

Multiple chaotic electrical wavelets circulate through the atria at 350–600 impulses/min. The AV node acts as a gatekeeper, letting through random impulses β€” producing the hallmark irregularly irregular rhythm. The atria quiver rather than contract, eliminating the "atrial kick" that contributes ~20% of cardiac output.

Key Clinical Points

Stroke riskHigh β€” blood pools in the left atrial appendage β†’ thrombus β†’ embolism
Rate controlBeta-blockers, diltiazem, verapamil, digoxin
Rhythm controlCardioversion (electrical or chemical), ablation
AnticoagulationDOACs or warfarin (CHAβ‚‚DSβ‚‚-VASc score guides use)

2. ❀️‍πŸ”₯ ST-Elevation Myocardial Infarction (STEMI)

Anterior STEMI ECG

What you see on the ECG

  • Massive ST elevation across V1–V6 (precordial leads) with a convex "tombstone" morphology
  • Hyperacute T waves (tall, peaked) in V2–V4
  • Reciprocal ST depression in inferior leads (II, III, aVF)
  • Sinus rhythm maintained

Why it happens

A complete coronary artery occlusion (here the Left Anterior Descending artery) cuts off blood supply to the anterior wall. Ischemic myocytes leak K⁺ and accumulate Ca²⁺, altering their resting membrane potential β€” this shifts the ST segment above the isoelectric line. The longer the occlusion, the more cells die β†’ Q waves develop (irreversible necrosis).

Localization Table

TerritoryLeads with ST↑Culprit Artery
AnteriorV1–V4LAD
InferiorII, III, aVFRCA
LateralI, aVL, V5–V6LCx
PosteriorTall R + ST↓ in V1–V2RCA/LCx
⚑ Emergency: Call cath lab immediately. Door-to-balloon time <90 min saves lives.

3. 🚨 Complete (Third-Degree) AV Block

Complete Heart Block ECG

What you see on the ECG

  • P waves are present β€” regular, at normal atrial rate (~80–100/min)
  • QRS complexes are present β€” regular, but slower (~30–40/min here)
  • No fixed PR interval β€” P waves "march through" QRS complexes completely independently
  • Wide QRS complexes β€” indicating a ventricular escape rhythm (infra-Hisian origin)

Why it happens

The AV node or His-Purkinje system is completely diseased β€” zero impulses cross from atria to ventricles. The ventricles rely on a slow escape pacemaker (junctional at 40–60 bpm, or ventricular at 20–40 bpm) to keep beating. This is called AV dissociation.

Causes

Inferior MI (RCA occlusion), Lyme disease, surgical/procedural trauma, degenerative conduction disease (Lenègre disease), hyperkalemia, drugs (digoxin toxicity, beta-blockers in excess).
⚑ Emergency: Transcutaneous pacing β†’ transvenous pacing β†’ permanent pacemaker.

4. ⚑ Ventricular Tachycardia (VT)

Ventricular Tachycardia ECG

What you see on the ECG

  • Rapid rate (~116 bpm here)
  • Very wide, bizarre QRS complexes (~200 ms) β€” markedly abnormal morphology
  • Tall, peaked R waves in V1–V2; deep S waves in V4–V6 β€” discordant T waves
  • No identifiable P waves β€” AV dissociation

Why it happens

A reentrant circuit or automatic focus fires within the ventricular myocardium, bypassing the normal His-Purkinje system. Activation spreads slowly cell-to-cell β†’ wide QRS. The fast ventricular rate reduces filling time, drops cardiac output, and can degenerate into ventricular fibrillation (VF) β†’ sudden cardiac death.

VT vs SVT with Aberrancy β€” Key Differentiators

FeaturePoints to VT
AV dissociationβœ… Highly specific
QRS >160 msβœ…
Concordance (all V1–V6 same direction)βœ…
Fusion beatsβœ… Pathognomonic
History of structural heart diseaseβœ…
⚑ Emergency: If unstable β†’ synchronized cardioversion. If stable β†’ amiodarone, lidocaine.

5. πŸ”€ Bundle Branch Blocks β€” RBBB & LBBB

RBBB vs LBBB β€” Harrison's diagram
Harrison's Principles of Internal Medicine β€” Figure 240-10: QRS-T patterns in RBBB and LBBB compared to normal, in leads V₁ and V₆.

What you see

RBBBLBBB
V1rSR' ("rabbit ears")Deep broad QS or rS
V6Broad slurred S waveBroad notched R wave
QRS durationβ‰₯120 msβ‰₯120 ms
T-waveInverted in V1–V3Inverted in V5–V6, I, aVL
Septal Q wavesPresent in I, V5–V6Absent

Why it happens

  • RBBB: Impulse can't travel down the right bundle β†’ right ventricle activated late via slow cell-to-cell spread β†’ terminal R' in V1
  • LBBB: Impulse can't travel down the left bundle β†’ left ventricle activated late β†’ the septum activates rightβ†’left (opposite of normal), erasing normal septal Q waves, creating broad R in lateral leads

Clinical Significance

RBBBLBBB
May be normalβœ… (isolated RBBB)❌ (usually pathological)
New = EmergencyOnly if with MIβœ… New LBBB = STEMI equivalent
CausesPE, ASD, agingIHD, HTN, cardiomyopathy, LBBB

6. πŸ“Š Multi-Arrhythmia Comparison

Multi-arrhythmia comparison ECG strip
Comparative rhythm strips: (a) Normal sinus rhythm; (b) Isolated PVCs; (c) Multifocal PVCs; (d) Atrial tachycardia; (e) Sinus arrhythmia; (f) Frequent PVCs; (g) Left Bundle Branch Block (LBBB) β€” widened QRS with secondary ST-T changes.

Quick ECG Reading Checklist

1. RATE          β†’ 300 Γ· (large squares between R waves)
2. RHYTHM        β†’ Regular? Irregularly irregular?
3. P WAVES       β†’ Present? Morphology? Each followed by QRS?
4. PR INTERVAL   β†’ 120–200 ms (3–5 small squares) normal
5. QRS WIDTH     β†’ <120 ms = narrow; β‰₯120 ms = wide (BBB or VT)
6. ST SEGMENT    β†’ Elevation β‰₯1mm? Depression?
7. T WAVES       β†’ Peaked (hyperacute)? Inverted?
8. QTc           β†’ <440 ms (male), <460 ms (female)

Summary Table

DisorderRateRhythmP WavesQRSSignature Finding
Atrial FibrillationVariableIrreg. irreg.Absent (f waves)NarrowNo P waves
STEMINormalRegularNormalNormalST elevation
3Β° AV Block20–60Regular (escape)Present, unrelatedWideAV dissociation
Ventricular Tachycardia100–250RegularDissociatedWide >120 msWide-complex tachycardia
RBBBNormalRegularNormalWiderSR' in V1
LBBBNormalRegularNormalWideBroad R in V5/V6
Sources: Braunwald's Heart Disease (11th ed.); Harrison's Principles of Internal Medicine (21st ed.)

Where is defect in ecg mark it and make pdf

Reading File
Running Command

mkdir -p /home/daytona/workspace/ecg-pdf && cd /home/daytona/workspace/ecg-pdf &…

Writing File

~/ecg-pdf/annotate.py

from PIL import Image, ImageDraw, ImageFont
import os

BASE = "/home/daytona/workspace/ecg-pdf"

def load_font(size):
    try:
        return ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", size)
    except:
        return ImageFont.load_default()

def arrow(draw, x1, y1, x2, y2, color, width=3):
    """Draw an arrow from (x1,y1) pointing to (x2,y2)"""
    import math
    draw.line([(x1,y1),(x2,y2)], fill=color, width=width)
    angle = math.atan2(y2-y1, x2-x1)
    arrow_len = 18
    angle1 = angle + math.radians(150)
    angle2 = angle - math.radians(150)
    draw.polygon([
        (x2, y2),
        (x2 + arrow_len*math.cos(angle1), y2 + arrow_len*math.sin(angle1)),
        (x2 + arrow_len*math.cos(angle2), y2 + arrow_len*math.sin(angle2)),
    ], fill=color)

def label_box(draw, x, y, text, color, font, bg=(255,255,0,200)):
    bbox = font.getbbox(text)
    w = bbox[2]-bbox[0]+12
    h = bbox[3]-bbox[1]+8
    draw.rectangle([x-2, y-2, x+w+2, y+h+2], fill=(0,0,0,180))
    draw.rectangle([x, y, x+w, y+h], fill=color)
    draw.text((x+6, y+4), text, fill="black", font=font)

# ─────────────────────────────────────────────
# 1. ATRIAL FIBRILLATION
# ─────────────────────────────────────────────
img = Image.open(f"{BASE}/af.jpg").convert("RGBA")
W, H = img.size
overlay = Image.new("RGBA", img.size, (0,0,0,0))
draw = ImageDraw.Draw(overlay)
f_sm = load_font(18)
f_md = load_font(22)
f_lg = load_font(26)

# Highlight fibrillatory baseline zone (Lead II rhythm strip bottom row)
# Bottom strip spans roughly y=680-720, full width
fy1, fy2 = int(H*0.82), int(H*0.90)
draw.rectangle([30, fy1, int(W*0.55), fy2], outline=(255,50,50,220), width=4)
# Arrow pointing to absent P wave region
arrow(draw, 180, fy1-10, 180, fy1+5, (255,50,50,220), width=3)
label_box(draw, 50, fy1-48, "No P waves β€” Fibrillatory baseline", (255,80,80,230), f_sm)

# Highlight irregular R-R interval in lead I (top strip)
# Mark two wide gaps between QRS
rx1, ry = int(W*0.10), int(H*0.07)
draw.line([(rx1, ry), (rx1+80, ry)], fill=(255,200,0,220), width=3)
draw.line([(rx1+150, ry), (rx1+200, ry)], fill=(255,200,0,220), width=3)
label_box(draw, rx1-10, ry-35, "Irregular R-R intervals", (255,200,0,230), f_sm)

# Title annotation
label_box(draw, 20, 10, "ATRIAL FIBRILLATION β€” KEY DEFECTS MARKED", (255,50,50,240), f_lg)

img = Image.alpha_composite(img, overlay)
img.convert("RGB").save(f"{BASE}/af_annotated.jpg", quality=92)
print("AF done")

# ─────────────────────────────────────────────
# 2. STEMI
# ─────────────────────────────────────────────
img = Image.open(f"{BASE}/stemi.jpg").convert("RGBA")
W, H = img.size
overlay = Image.new("RGBA", img.size, (0,0,0,0))
draw = ImageDraw.Draw(overlay)

# Image is 6-row layout: I, II, III, aVR, aVL, aVF on left; V1-V6 on right
# Each row ~H/6 tall; V2 starts at about row 2 right side
row_h = H // 6

# V2 row (row 1, right half) - ST elevation
v2_y_center = int(row_h * 1.5)
v2_x_start  = int(W * 0.50)
# Draw highlight rectangle over V2-V3 ST segments
draw.rectangle([v2_x_start+10, v2_y_center-50, v2_x_start+220, v2_y_center+50],
               outline=(255,0,0,230), width=4)
arrow(draw, v2_x_start+110, v2_y_center-90, v2_x_start+110, v2_y_center-52, (255,0,0,220))
label_box(draw, v2_x_start-60, v2_y_center-130, "ST ELEVATION V2-V3 (tombstone)", (255,60,60,230), f_sm)

# V4-V5 row
v4_y_center = int(row_h * 0.5)   # V1-V6 in right column, top to bottom
v4_x_start  = int(W * 0.68)
draw.rectangle([v4_x_start+5, v4_y_center-50, v4_x_start+180, v4_y_center+50],
               outline=(255,120,0,230), width=4)
arrow(draw, v4_x_start+90, v4_y_center-80, v4_x_start+90, v4_y_center-52, (255,120,0,220))
label_box(draw, v4_x_start-40, v4_y_center-118, "ST elevation V1 (anterior)", (255,150,0,230), f_sm)

# Reciprocal depression: aVF (left column, row 6 = bottom)
avf_y = int(H * 0.92)
avf_x = int(W * 0.13)
draw.rectangle([avf_x-20, avf_y-40, avf_x+160, avf_y+20],
               outline=(0,180,255,230), width=3)
label_box(draw, avf_x-20, avf_y-70, "Reciprocal ST depression", (0,180,255,230), f_sm)

label_box(draw, 20, 10, "STEMI (ANTERIOR) β€” KEY DEFECTS MARKED", (255,50,50,240), f_lg)

img = Image.alpha_composite(img, overlay)
img.convert("RGB").save(f"{BASE}/stemi_annotated.jpg", quality=92)
print("STEMI done")

# ─────────────────────────────────────────────
# 3. COMPLETE AV BLOCK
# ─────────────────────────────────────────────
img = Image.open(f"{BASE}/avblock.jpg").convert("RGBA")
W, H = img.size
overlay = Image.new("RGBA", img.size, (0,0,0,0))
draw = ImageDraw.Draw(overlay)

# The ECG has 5 rows (I, II, III, V1, II rhythm, V5 rhythm)
# Each row ~ H/5
row_h = H // 5

# Row 2 (II) β€” mark P waves marching independently
# P waves are small bumps; mark two of them
p_y = int(row_h * 1.5)
# Mark a P wave that falls ON top of QRS (dissociation evidence)
px1, px2 = int(W * 0.28), int(W * 0.52)
for px in [px1, px2]:
    draw.ellipse([px-18, p_y-25, px+18, p_y+10], outline=(255,255,0,230), width=3)
    arrow(draw, px, p_y-50, px, p_y-28, (255,255,0,220))
label_box(draw, int(W*0.18), p_y-88, "P waves β€” independent of QRS", (255,230,0,230), f_sm)

# Mark wide QRS complexes in row 4 (V1 rhythm strip)
qrs_y = int(row_h * 3.5)
for qx in [int(W*0.18), int(W*0.38), int(W*0.58)]:
    draw.rectangle([qx-25, qrs_y-55, qx+25, qrs_y+30], outline=(255,100,100,230), width=3)
arrow(draw, int(W*0.38), qrs_y+50, int(W*0.38), qrs_y+32, (255,100,100,220))
label_box(draw, int(W*0.22), qrs_y+55, "Wide QRS escape rhythm (ventricular)", (255,100,100,230), f_sm)

# Slow rate indicator
label_box(draw, int(W*0.62), qrs_y-20, "Slow rate ~35 bpm", (255,180,0,230), f_sm)

label_box(draw, 20, 10, "COMPLETE (3Β°) AV BLOCK β€” KEY DEFECTS MARKED", (255,50,50,240), f_lg)

img = Image.alpha_composite(img, overlay)
img.convert("RGB").save(f"{BASE}/avblock_annotated.jpg", quality=92)
print("AV Block done")

# ─────────────────────────────────────────────
# 4. VENTRICULAR TACHYCARDIA
# ─────────────────────────────────────────────
img = Image.open(f"{BASE}/vt.jpg").convert("RGBA")
W, H = img.size
overlay = Image.new("RGBA", img.size, (0,0,0,0))
draw = ImageDraw.Draw(overlay)

row_h = H // 4

# Highlight wide QRS in lead II (row 2) β€” mark 2 complexes
qrs_y = int(row_h * 1.5)
for qx in [int(W*0.20), int(W*0.43), int(W*0.66)]:
    draw.rectangle([qx-30, qrs_y-70, qx+30, qrs_y+40], outline=(255,50,50,230), width=4)
arrow(draw, int(W*0.43), qrs_y-100, int(W*0.43), qrs_y-73, (255,50,50,220))
label_box(draw, int(W*0.30), qrs_y-135, "WIDE QRS >200ms (bizarre morphology)", (255,50,50,230), f_sm)

# No P waves β€” mark flat region in lead I (row 1)
p_y2 = int(row_h * 0.5)
draw.rectangle([int(W*0.08), p_y2-20, int(W*0.32), p_y2+20], outline=(255,200,0,220), width=3)
label_box(draw, int(W*0.08), p_y2-55, "No visible P waves (AV dissociation)", (255,200,0,230), f_sm)

# Rapid rate indicator
label_box(draw, int(W*0.60), int(H*0.05), "Rapid rate ~116 bpm", (255,120,0,230), f_md)

# Discordant T waves in V2
tv_y = int(row_h * 0.9)
tv_x = int(W * 0.68)
draw.ellipse([tv_x-22, tv_y-30, tv_x+60, tv_y+30], outline=(0,220,100,220), width=3)
label_box(draw, tv_x-30, tv_y+35, "Discordant T waves", (0,200,100,230), f_sm)

label_box(draw, 20, 10, "VENTRICULAR TACHYCARDIA β€” KEY DEFECTS MARKED", (255,50,50,240), f_lg)

img = Image.alpha_composite(img, overlay)
img.convert("RGB").save(f"{BASE}/vt_annotated.jpg", quality=92)
print("VT done")

# ─────────────────────────────────────────────
# 5. BUNDLE BRANCH BLOCK (Harrison diagram)
# ─────────────────────────────────────────────
img = Image.open(f"{BASE}/bbb.png").convert("RGBA")
W, H = img.size
overlay = Image.new("RGBA", img.size, (0,0,0,0))
draw = ImageDraw.Draw(overlay)

# RBBB rSR' in V1 β€” middle row left panel (approx)
rbbb_x, rbbb_y = int(W*0.18), int(H*0.46)
draw.ellipse([rbbb_x-30, rbbb_y-50, rbbb_x+70, rbbb_y+30], outline=(255,50,50,230), width=4)
arrow(draw, rbbb_x+80, rbbb_y-80, rbbb_x+40, rbbb_y-35, (255,50,50,220))
label_box(draw, rbbb_x+85, rbbb_y-100, "rSR' rabbit ears (RBBB)", (255,80,80,230), f_sm)

# LBBB broad R in V6 β€” bottom row right panel
lbbb_x, lbbb_y = int(W*0.70), int(H*0.70)
draw.ellipse([lbbb_x-30, lbbb_y-60, lbbb_x+60, lbbb_y+30], outline=(255,150,0,230), width=4)
arrow(draw, lbbb_x-70, lbbb_y-90, lbbb_x-15, lbbb_y-45, (255,150,0,220))
label_box(draw, lbbb_x-160, lbbb_y-115, "Broad notched R (LBBB V6)", (255,150,0,230), f_sm)

# T wave inversion arrows
t_rbbb_x, t_rbbb_y = int(W*0.32), int(H*0.55)
draw.ellipse([t_rbbb_x-18, t_rbbb_y-20, t_rbbb_x+18, t_rbbb_y+20], outline=(0,180,255,220), width=3)
label_box(draw, t_rbbb_x+22, t_rbbb_y-15, "T inv", (0,180,255,220), f_sm)

label_box(draw, 20, 10, "BUNDLE BRANCH BLOCKS β€” KEY DEFECTS MARKED", (255,100,0,240), f_lg)

img = Image.alpha_composite(img, overlay)
img.convert("RGB").save(f"{BASE}/bbb_annotated.png", quality=92)
print("BBB done")
print("All annotations complete!")
Running Command

cd /home/daytona/workspace/ecg-pdf && python annotate.py

Writing File

~/ecg-pdf/make_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer,
                                 Image as RLImage, Table, TableStyle,
                                 PageBreak, HRFlowable)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import KeepTogether
import os

BASE = "/home/daytona/workspace/ecg-pdf"
OUT  = f"{BASE}/Common_Heart_Disorders_ECG.pdf"

# ── Page setup ──────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUT, pagesize=A4,
    leftMargin=1.5*cm, rightMargin=1.5*cm,
    topMargin=1.8*cm,  bottomMargin=1.8*cm,
    title="Common Heart Disorders β€” ECG with Annotated Defects",
    author="Orris Medical AI"
)

W_PAGE = A4[0] - 3*cm   # usable width

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

TITLE_STYLE = ParagraphStyle("title",
    fontSize=22, leading=28, alignment=TA_CENTER,
    textColor=colors.HexColor("#1a1a2e"), fontName="Helvetica-Bold",
    spaceAfter=6)

SUBTITLE_STYLE = ParagraphStyle("subtitle",
    fontSize=12, leading=16, alignment=TA_CENTER,
    textColor=colors.HexColor("#e94560"), fontName="Helvetica",
    spaceAfter=12)

H1 = ParagraphStyle("h1",
    fontSize=16, leading=20, fontName="Helvetica-Bold",
    textColor=colors.white, spaceBefore=8, spaceAfter=4,
    backColor=colors.HexColor("#c0392b"),
    leftIndent=-4, rightIndent=-4,
    borderPad=6)

H2 = ParagraphStyle("h2",
    fontSize=12, leading=16, fontName="Helvetica-Bold",
    textColor=colors.HexColor("#c0392b"), spaceBefore=6, spaceAfter=2)

BODY = ParagraphStyle("body",
    fontSize=10, leading=14, fontName="Helvetica",
    textColor=colors.HexColor("#333333"),
    alignment=TA_JUSTIFY, spaceAfter=4)

BULLET = ParagraphStyle("bullet",
    fontSize=10, leading=14, fontName="Helvetica",
    textColor=colors.HexColor("#333333"),
    leftIndent=16, spaceAfter=2,
    bulletIndent=4)

CAPTION = ParagraphStyle("caption",
    fontSize=9, leading=12, fontName="Helvetica-Oblique",
    textColor=colors.HexColor("#555555"), alignment=TA_CENTER,
    spaceAfter=8)

DEFECT_BOX = ParagraphStyle("defect",
    fontSize=10, leading=14, fontName="Helvetica-Bold",
    textColor=colors.HexColor("#7d0000"),
    backColor=colors.HexColor("#fff3f3"),
    leftIndent=8, rightIndent=8, spaceBefore=4, spaceAfter=4,
    borderColor=colors.HexColor("#c0392b"), borderWidth=1, borderPad=6,
    borderRadius=4)

def ecg_image(filename, width=W_PAGE):
    path = os.path.join(BASE, filename)
    img = RLImage(path, width=width, height=width*0.6)
    img.hAlign = "CENTER"
    return img

def tbl(data, col_widths=None, header_bg=colors.HexColor("#2c3e50")):
    t = Table(data, colWidths=col_widths or [W_PAGE/len(data[0])]*len(data[0]))
    style = [
        ("BACKGROUND",  (0,0), (-1,0),  header_bg),
        ("TEXTCOLOR",   (0,0), (-1,0),  colors.white),
        ("FONTNAME",    (0,0), (-1,0),  "Helvetica-Bold"),
        ("FONTSIZE",    (0,0), (-1,0),  10),
        ("ALIGN",       (0,0), (-1,-1), "CENTER"),
        ("VALIGN",      (0,0), (-1,-1), "MIDDLE"),
        ("ROWBACKGROUNDS",(0,1),(-1,-1),[colors.HexColor("#fdfefe"), colors.HexColor("#f2f3f4")]),
        ("FONTNAME",    (0,1), (-1,-1), "Helvetica"),
        ("FONTSIZE",    (0,1), (-1,-1), 9),
        ("GRID",        (0,0), (-1,-1), 0.5, colors.HexColor("#bdc3c7")),
        ("TOPPADDING",  (0,0), (-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
    ]
    t.setStyle(TableStyle(style))
    return t

def hr():
    return HRFlowable(width="100%", thickness=1,
                      color=colors.HexColor("#c0392b"), spaceAfter=6, spaceBefore=6)

# ── Content ───────────────────────────────────────────────────────────────────
story = []

# ── Cover Page ────────────────────────────────────────────────────────────────
story.append(Spacer(1, 2*cm))
story.append(Paragraph("Common Heart Disorders", TITLE_STYLE))
story.append(Paragraph("ECG Findings with Annotated Defects", SUBTITLE_STYLE))
story.append(Spacer(1, 0.4*cm))
story.append(hr())
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "A comprehensive visual reference for identifying ECG defects in the five most "
    "clinically important cardiac conditions. Each disorder includes a real 12-lead ECG "
    "with defects <b>marked and labelled</b>, plus a structured clinical explanation.",
    BODY))
story.append(Spacer(1, 0.6*cm))

# Contents table
toc_data = [
    ["#", "Disorder", "Key ECG Defect"],
    ["1", "Atrial Fibrillation",          "Absent P waves Β· Irregularly irregular rhythm"],
    ["2", "STEMI (Anterior)",              "ST elevation V1–V6 Β· Reciprocal depression"],
    ["3", "Complete (3Β°) AV Block",        "AV dissociation Β· Wide escape QRS"],
    ["4", "Ventricular Tachycardia",       "Wide QRS >120 ms Β· No P waves Β· Rapid rate"],
    ["5", "Bundle Branch Block (RBBB/LBBB)","rSR' V1 (RBBB) Β· Broad notched R V6 (LBBB)"],
]
story.append(tbl(toc_data, col_widths=[1.2*cm, 6*cm, W_PAGE-7.2*cm]))
story.append(Spacer(1, 0.5*cm))
story.append(hr())
story.append(Spacer(1, 0.3*cm))

# Quick ECG reading guide box
guide_data = [
    [Paragraph("<b>Quick ECG Reading Framework</b>", ParagraphStyle("qh",fontSize=11,fontName="Helvetica-Bold",textColor=colors.white))]
]
guide_rows = [
    ["Step", "Parameter", "Normal Value", "Abnormal Clue"],
    ["1", "Rate",         "60–100 bpm",   "<60 = bradycardia  |  >100 = tachycardia"],
    ["2", "Rhythm",       "Regular",      "Irregular β†’ AF, PVCs"],
    ["3", "P waves",      "Upright in II", "Absent β†’ AF  |  No relation to QRS β†’ AV Block"],
    ["4", "PR interval",  "120–200 ms",   ">200 ms = 1Β° block  |  Absent = 3Β° block"],
    ["5", "QRS width",    "<120 ms",      "β‰₯120 ms = BBB or VT"],
    ["6", "ST segment",   "Isoelectric",  "Elevation β†’ STEMI  |  Depression β†’ ischaemia"],
    ["7", "T waves",      "Upright",      "Peaked = hyperacute  |  Inverted = ischaemia/BBB"],
    ["8", "QTc",          "β™‚<440 ♀<460 ms","Prolonged β†’ TdP risk"],
]
story.append(tbl(guide_rows, col_widths=[1*cm, 3.2*cm, 3.5*cm, W_PAGE-7.7*cm]))
story.append(PageBreak())

# ═══════════════════════════════════════════════════════════════
# DISORDER 1 β€” ATRIAL FIBRILLATION
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("1.  Atrial Fibrillation (AF)", H1))
story.append(Spacer(1, 0.2*cm))
story.append(ecg_image("af_annotated.jpg"))
story.append(Paragraph(
    "β–² Real 12-lead ECG of atrial fibrillation with rapid ventricular response. "
    "<font color='red'><b>Red box</b></font>: fibrillatory baseline with absent P waves in lead II rhythm strip. "
    "<font color='#e6b800'><b>Yellow lines</b></font>: irregularly irregular R-R intervals in lead I.",
    CAPTION))

story.append(Paragraph("Defects Identified", H2))
defects_af = [
    ["πŸ”΄ Absent P waves",       "No organized atrial depolarization β€” replaced by chaotic f-waves (350–600/min)"],
    ["🟑 Irregular R-R intervals","AV node conducts randomly β†’ no two beats equally spaced"],
    ["πŸ”΅ Narrow QRS",           "Ventricular conduction is normal (unless aberrancy/BBB co-exists)"],
    ["⚑ Rapid ventricular rate", "Here ~120 bpm = AF with rapid ventricular response (RVR)"],
]
story.append(tbl(defects_af, col_widths=[5.5*cm, W_PAGE-5.5*cm]))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Mechanism", H2))
story.append(Paragraph(
    "Multiple micro-reentrant wavelets circulate the atrial myocardium simultaneously. "
    "The pulmonary vein ostia are the most common trigger sites. The AV node acts as a "
    "gatekeeper, passing impulses irregularly to the ventricles. Loss of the atrial "
    "kick reduces cardiac output by ~20% and causes stasis in the left atrial appendage "
    "β€” the primary source of cardioembolic stroke.", BODY))

story.append(Paragraph("Clinical Management", H2))
mgmt_af = [
    ["Goal",         "Strategy",                   "Agents"],
    ["Rate control", "Slow ventricular response",  "Beta-blockers, diltiazem, digoxin"],
    ["Rhythm control","Restore sinus rhythm",       "Cardioversion, flecainide, amiodarone, ablation"],
    ["Anticoagulation","Prevent stroke",            "DOACs (apixaban, rivaroxaban) or warfarin"],
]
story.append(tbl(mgmt_af))
story.append(PageBreak())

# ═══════════════════════════════════════════════════════════════
# DISORDER 2 β€” STEMI
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("2.  ST-Elevation Myocardial Infarction (Anterior STEMI)", H1))
story.append(Spacer(1, 0.2*cm))
story.append(ecg_image("stemi_annotated.jpg"))
story.append(Paragraph(
    "β–² Acute anterior STEMI. "
    "<font color='red'><b>Red boxes</b></font>: massive convex ST elevation in V2–V3 ('tombstone' pattern). "
    "<font color='#e67300'><b>Orange box</b></font>: ST elevation in V1. "
    "<font color='#0099cc'><b>Blue box</b></font>: reciprocal ST depression in aVF.",
    CAPTION))

story.append(Paragraph("Defects Identified", H2))
defects_stemi = [
    ["πŸ”΄ ST elevation V1–V6",    "Convex (tombstone) morphology β€” hallmark of transmural injury"],
    ["🟠 Hyperacute T waves",    "Tall, peaked Ts in V2–V4 β€” earliest sign of occlusion"],
    ["πŸ”΅ Reciprocal ST depression","In aVF/inferior leads β€” mirror image of anterior elevation"],
    ["⚠️ No pathological Q waves (yet)", "This is an acute/early tracing β€” Qs form within hours-days"],
]
story.append(tbl(defects_stemi, col_widths=[5.5*cm, W_PAGE-5.5*cm]))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Localization by Territory", H2))
loc_data = [
    ["Territory",   "Leads with ST↑",     "Reciprocal Leads",  "Culprit Artery"],
    ["Anterior",    "V1–V4",              "II, III, aVF",      "LAD (proximal)"],
    ["Inferior",    "II, III, aVF",       "I, aVL",            "RCA (80%) / LCx"],
    ["Lateral",     "I, aVL, V5–V6",      "V1–V2",             "LCx"],
    ["Posterior",   "Tall R + ST↓ V1–V2", "None",              "RCA / LCx"],
]
story.append(tbl(loc_data))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "⚑ EMERGENCY: Activate cath lab immediately. Door-to-balloon (primary PCI) target <b>&lt;90 minutes</b>. "
    "Aspirin 300 mg + P2Y12 inhibitor loading immediately.", DEFECT_BOX))
story.append(PageBreak())

# ═══════════════════════════════════════════════════════════════
# DISORDER 3 β€” COMPLETE AV BLOCK
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("3.  Complete (Third-Degree) AV Block", H1))
story.append(Spacer(1, 0.2*cm))
story.append(ecg_image("avblock_annotated.jpg"))
story.append(Paragraph(
    "β–² Third-degree heart block. "
    "<font color='#cccc00'><b>Yellow circles</b></font>: P waves marching independently of QRS complexes. "
    "<font color='red'><b>Red boxes</b></font>: wide QRS escape complexes (ventricular origin). "
    "Note the very slow ventricular rate (~35 bpm).",
    CAPTION))

story.append(Paragraph("Defects Identified", H2))
defects_avb = [
    ["🟑 P waves present but independent", "Regular P-P intervals (~80/min) β€” atria beat normally"],
    ["πŸ”΄ No fixed PR interval",            "P waves precede, coincide with, or follow QRS randomly"],
    ["πŸ”΄ Wide QRS escape rhythm",          ">120 ms β€” ventricular escape pacemaker (infra-Hisian)"],
    ["⏱️ Bradycardia ~20–40 bpm",          "Ventricular rate slow enough to cause syncope/death"],
]
story.append(tbl(defects_avb, col_widths=[5.5*cm, W_PAGE-5.5*cm]))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("AV Block Comparison", H2))
avb_compare = [
    ["Degree",  "PR Interval",           "Dropped Beats?", "Action"],
    ["1Β°",      "Prolonged (>200 ms)",   "No",             "Monitor"],
    ["2Β° Mobitz I (Wenckebach)", "Progressive lengthening", "Yes (cyclic)", "Monitor / pacing if symptomatic"],
    ["2Β° Mobitz II", "Fixed, then sudden drop", "Yes (unpredictable)", "Pacemaker"],
    ["3Β° (Complete)", "AV dissociation",  "All blocked",    "Emergency pacemaker"],
]
story.append(tbl(avb_compare))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "⚑ EMERGENCY: Transcutaneous pacing immediately if haemodynamically unstable. "
    "IV atropine 0.5 mg (temporary measure). Arrange permanent pacemaker implantation.", DEFECT_BOX))
story.append(PageBreak())

# ═══════════════════════════════════════════════════════════════
# DISORDER 4 β€” VENTRICULAR TACHYCARDIA
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("4.  Ventricular Tachycardia (VT)", H1))
story.append(Spacer(1, 0.2*cm))
story.append(ecg_image("vt_annotated.jpg"))
story.append(Paragraph(
    "β–² Monomorphic ventricular tachycardia. "
    "<font color='red'><b>Red boxes</b></font>: wide bizarre QRS complexes (~200 ms) β€” ventricular origin. "
    "<font color='#cccc00'><b>Yellow box</b></font>: no visible P waves (AV dissociation). "
    "<font color='#00cc66'><b>Green circle</b></font>: discordant T waves in precordial leads.",
    CAPTION))

story.append(Paragraph("Defects Identified", H2))
defects_vt = [
    ["πŸ”΄ Wide QRS β‰₯120 ms",         "Bizarre morphology β€” ventricular myocardium activated cell-to-cell"],
    ["🟑 No P waves / AV dissociation", "Atria beat independently; no retrograde conduction"],
    ["⚑ Rapid rate ~100–250 bpm",   "Here ~116 bpm β€” reduces filling time and cardiac output"],
    ["🟒 Discordant T waves",        "T waves opposite to main QRS deflection β€” secondary repolarisation"],
    ["πŸ“ QRS concordance (V1–V6)",   "All precordial leads same direction β†’ strongly suggests VT"],
]
story.append(tbl(defects_vt, col_widths=[5.5*cm, W_PAGE-5.5*cm]))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("VT vs SVT with Aberrancy β€” Brugada Criteria", H2))
brugada = [
    ["Criterion",                    "If Present β†’ Diagnosis"],
    ["AV dissociation",              "VT (highly specific)"],
    ["QRS >160 ms",                  "VT"],
    ["Positive concordance V1–V6",   "VT"],
    ["Fusion / capture beats",       "VT (pathognomonic)"],
    ["No RS complex in V1–V6",       "VT"],
    ["RS interval >100 ms",          "VT"],
]
story.append(tbl(brugada, col_widths=[8*cm, W_PAGE-8*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "⚑ EMERGENCY: If pulseless β†’ CPR + defibrillation (unsynchronised). "
    "If pulse present but unstable β†’ synchronised cardioversion. "
    "If stable β†’ IV amiodarone 300 mg over 20–60 min.", DEFECT_BOX))
story.append(PageBreak())

# ═══════════════════════════════════════════════════════════════
# DISORDER 5 β€” BUNDLE BRANCH BLOCK
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("5.  Bundle Branch Block β€” RBBB & LBBB", H1))
story.append(Spacer(1, 0.2*cm))
story.append(ecg_image("bbb_annotated.png", width=W_PAGE*0.82))
story.append(Paragraph(
    "β–² Harrison's diagram (Fig. 240-10): Normal vs RBBB vs LBBB in V₁ and V₆. "
    "<font color='red'><b>Red circle</b></font>: RBBB rSR' 'rabbit ears' in V1. "
    "<font color='#e67300'><b>Orange circle</b></font>: LBBB broad notched R in V6. "
    "<font color='#0099cc'><b>Blue circle</b></font>: secondary T-wave inversion.",
    CAPTION))

story.append(Paragraph("Defects Identified", H2))
defects_bbb = [
    ["Feature",       "RBBB",                              "LBBB"],
    ["QRS duration",  "β‰₯120 ms",                          "β‰₯120 ms"],
    ["V1 pattern",    "rSR' β€” 'rabbit ears' βœ… CLASSIC",  "Deep broad QS or rS"],
    ["V6 pattern",    "Broad slurred S wave",              "Broad notched R wave βœ… CLASSIC"],
    ["Septal Q waves","Present in I, V5–V6",               "ABSENT (reversed septal activation)"],
    ["T-wave",        "Inverted V1–V3",                    "Inverted I, aVL, V5–V6"],
    ["Clinical",      "Often benign if isolated",          "Always pathological β€” investigate"],
    ["Emergency?",    "New + MI symptoms β†’ yes",           "New onset = STEMI equivalent ⚑"],
]
story.append(tbl(defects_bbb, col_widths=[4.5*cm, (W_PAGE-4.5*cm)/2, (W_PAGE-4.5*cm)/2]))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Common Causes", H2))
causes_bbb = [
    ["RBBB",                                     "LBBB"],
    ["Pulmonary embolism",                       "Ischaemic heart disease (most common)"],
    ["Atrial septal defect (ASD)",               "Hypertension"],
    ["Right heart strain / cor pulmonale",       "Dilated cardiomyopathy"],
    ["Congenital (isolated RBBB β€” benign)",      "Aortic stenosis"],
    ["Post-cardiac surgery",                     "Lenègre disease (degenerative)"],
]
story.append(tbl(causes_bbb, col_widths=[W_PAGE/2, W_PAGE/2]))
story.append(PageBreak())

# ═══════════════════════════════════════════════════════════════
# SUMMARY PAGE
# ═══════════════════════════════════════════════════════════════
story.append(Paragraph("Master Summary β€” All 5 Disorders", H1))
story.append(Spacer(1, 0.4*cm))

summary_data = [
    ["Disorder",           "Rate",        "Rhythm",           "P Waves",           "QRS",           "Primary ECG Defect"],
    ["Atrial Fibrillation","Variable",    "Irreg. Irreg.",    "Absent (f waves)",  "Narrow",        "No P waves + irregularity"],
    ["STEMI (Anterior)",   "Normal",      "Regular",          "Normal",            "Normal (early)","ST elevation V1–V6"],
    ["3Β° AV Block",        "20–40 bpm",   "Regular (escape)", "Present, unrelated","Wide",          "AV dissociation"],
    ["Ventricular Tachy.", "100–250 bpm", "Regular",          "Dissociated",       "Wide >120 ms",  "Wide bizarre QRS tachycardia"],
    ["RBBB",               "Normal",      "Regular",          "Normal",            "Wide",          "rSR' in V1"],
    ["LBBB",               "Normal",      "Regular",          "Normal",            "Wide",          "Broad notched R in V5–V6"],
]
story.append(tbl(summary_data,
    col_widths=[4*cm, 2*cm, 2.5*cm, 3.5*cm, 2*cm, W_PAGE-14*cm]))

story.append(Spacer(1, 0.6*cm))
story.append(hr())
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "<b>Sources:</b> Braunwald's Heart Disease: A Textbook of Cardiovascular Medicine (11th ed.); "
    "Harrison's Principles of Internal Medicine (21st ed.). "
    "ECG images from PMC Clinical Visual QA Dataset (open access) and Harrison's textbook. "
    "Compiled by Orris Medical AI β€” May 2026.",
    CAPTION))

# ── Build ────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUT}")
You've run out of free credits. Sign up for a free account to continue using Orris.
This is a shared conversation. Sign in to Orris to start your own chat.