Common heart disorder with ecg and explanation
ECG electrocardiogram common heart disorders arrhythmia
atrial fibrillation ECG 12 lead
myocardial infarction STEMI ST elevation ECG
heart block complete AV block third degree ECG
ventricular tachycardia ECG wide complex tachycardia
left bundle branch block right bundle branch block ECG pattern
| Feature | Finding |
|---|---|
| P waves | Absent β replaced by fine fibrillatory (f) waves |
| Rhythm | Irregularly irregular R-R intervals |
| QRS | Narrow (<120 ms) unless aberrant conduction |
| Rate | Variable; rapid if uncontrolled (>100 bpm = AF with RVR) |

| Stage | ECG Finding |
|---|---|
| Hyperacute (minutes) | Tall, peaked (hyperacute) T waves |
| Acute (hours) | ST elevation β₯1 mm in β₯2 contiguous leads; convex ("tombstone") morphology |
| Established | Q waves develop (>40 ms, >25% of R height) |
| Reperfusion/old | T-wave inversion, persistent Q waves |
| Territory | Leads with ST Elevation | Artery |
|---|---|---|
| Anterior | V1βV4 | LAD |
| Inferior | II, III, aVF | RCA |
| Lateral | I, aVL, V5βV6 | LCx |
| Posterior | Tall R in V1βV2 + ST depression | RCA/LCx |

| Feature | Finding |
|---|---|
| P waves | Present, regular, at normal atrial rate (~60β100/min) |
| QRS | Present, regular, but SLOWER and independent of P waves |
| PR interval | No fixed PR interval β complete AV dissociation |
| QRS width | Narrow if junctional escape; wide (>120 ms) if ventricular escape |

| Feature | Finding |
|---|---|
| Rate | 100β250 bpm |
| Rhythm | Regular |
| QRS | Wide (>120 ms), bizarre morphology |
| P waves | May be dissociated (AV dissociation) or absent |
| Fusion/capture beats | Pathognomonic when present |


| Disorder | Rate | Rhythm | P Waves | QRS | Key Feature |
|---|---|---|---|---|---|
| Atrial Fibrillation | Variable | Irregularly irregular | Absent (f waves) | Narrow | No P waves |
| STEMI | Normal | Regular | Normal | Normal (early) | ST elevation β₯1 mm |
| 3Β° AV Block | 20β60 | Regular (escape) | Present, unrelated | Wide or narrow | AV dissociation |
| Ventricular Tachycardia | 100β250 | Regular | Dissociated | Wide >120 ms | Wide-complex tachycardia |
| RBBB | Normal | Regular | Normal | Wide (rSR' V1) | Rabbit ears in V1 |
| LBBB | Normal | Regular | Normal | Wide (notched R) | Broad R in V5/V6 |
Sources: Braunwald's Heart Disease (10th ed.); Harrison's Principles of Internal Medicine (21st ed.)
With images

| Stroke risk | High β blood pools in the left atrial appendage β thrombus β embolism |
| Rate control | Beta-blockers, diltiazem, verapamil, digoxin |
| Rhythm control | Cardioversion (electrical or chemical), ablation |
| Anticoagulation | DOACs or warfarin (CHAβDSβ-VASc score guides use) |

| Territory | Leads with STβ | Culprit Artery |
|---|---|---|
| Anterior | V1βV4 | LAD |
| Inferior | II, III, aVF | RCA |
| Lateral | I, aVL, V5βV6 | LCx |
| Posterior | Tall R + STβ in V1βV2 | RCA/LCx |
β‘ Emergency: Call cath lab immediately. Door-to-balloon time <90 min saves lives.

β‘ Emergency: Transcutaneous pacing β transvenous pacing β permanent pacemaker.

| Feature | Points 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.

| RBBB | LBBB | |
|---|---|---|
| V1 | rSR' ("rabbit ears") | Deep broad QS or rS |
| V6 | Broad slurred S wave | Broad notched R wave |
| QRS duration | β₯120 ms | β₯120 ms |
| T-wave | Inverted in V1βV3 | Inverted in V5βV6, I, aVL |
| Septal Q waves | Present in I, V5βV6 | Absent |
| RBBB | LBBB | |
|---|---|---|
| May be normal | β (isolated RBBB) | β (usually pathological) |
| New = Emergency | Only if with MI | β New LBBB = STEMI equivalent |
| Causes | PE, ASD, aging | IHD, HTN, cardiomyopathy, LBBB |

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)
| Disorder | Rate | Rhythm | P Waves | QRS | Signature Finding |
|---|---|---|---|---|---|
| Atrial Fibrillation | Variable | Irreg. irreg. | Absent (f waves) | Narrow | No P waves |
| STEMI | Normal | Regular | Normal | Normal | ST elevation |
| 3Β° AV Block | 20β60 | Regular (escape) | Present, unrelated | Wide | AV dissociation |
| Ventricular Tachycardia | 100β250 | Regular | Dissociated | Wide >120 ms | Wide-complex tachycardia |
| RBBB | Normal | Regular | Normal | Wide | rSR' in V1 |
| LBBB | Normal | Regular | Normal | Wide | Broad 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
mkdir -p /home/daytona/workspace/ecg-pdf && cd /home/daytona/workspace/ecg-pdf &β¦
~/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!")
cd /home/daytona/workspace/ecg-pdf && python annotate.py
~/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><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}")