metabolic encephalopathy via kidney

Reading File
Metabolic encephalopathy due to kidney disease = uremic encephalopathy. This is a neuropsychiatric syndrome caused by accumulation of uremic toxins, electrolyte disturbances, and other metabolic derangements in acute kidney injury (AKI) or end-stage renal disease (ESRD).
Searching sources...
Finding Sources
Finding Sources
Searching PubMed

uremic encephalopathy pathophysiology treatment

Good - I have 4 excellent textbook sources. Let me read the most authoritative ones in parallel.
Reading File
Reading File
Reading File
I now have rich content from three major textbooks. Let me also read the Adams & Victor and the Clinical Manifestations box from Comprehensive Clinical Nephrology.
Reading File
Reading File
Excellent - I now have comprehensive content from four major textbooks. Let me compile the full answer.

Uremic Encephalopathy (Metabolic Encephalopathy via Kidney Disease)

Uremic encephalopathy (UE) is the metabolic encephalopathy that results from renal failure - acute kidney injury (AKI) or end-stage kidney disease (ESKD). It represents a spectrum of brain dysfunction ranging from imperceptible cognitive changes to coma and death.

Pathophysiology

Uremic Toxin Accumulation

The central mechanism is the retention of solutes that are normally cleared by the kidney. Among the 75 solutes in the European Uremic Toxin (EUTox) database, ~9% (7 solutes) are directly associated with neurologic effects. - Comprehensive Clinical Nephrology, 7th Ed.
Guanidino compounds are the most important neurotoxins:
  • Guanidinouscinic acid and methylguanidine are increased 100-fold in uremic brain tissue and cerebrospinal fluid
  • They antagonize GABA receptors (inhibitory) while simultaneously acting as NMDA receptor agonists (excitatory)
  • Net effect: marked enhancement of cortical excitability and seizure threshold lowering
  • Several guanidine compounds (guanidinosuccinic acid, methylguanidine, homoarginine) can directly induce seizures via NMDA receptor modulation and calcium channel effects
Brenner & Rector's The Kidney; Bradley & Daroff's Neurology

Blood-Brain Barrier Disruption

Kidney injury activates inflammatory cytokines that cross or disrupt the blood-brain barrier (BBB), facilitating access of toxins to the brain. Animal models of uremic encephalopathy in AKI show increased brain inflammation in conjunction with vascular permeability - a pattern different from hepatic encephalopathy. - Brenner & Rector's The Kidney
Asymmetric dimethylarginine (ADMA), which is elevated in CKD, inhibits endothelial nitric oxide synthase (eNOS) and correlates with cerebrovascular complications. Gut microbial metabolites (phenylalanine, benzoate, glutamate metabolites) also link to cognitive impairment in dialysis patients.

Secondary Hyperparathyroidism

PTH has direct CNS effects:
  • Brain calcium content doubles within days of acute renal failure onset
  • EEG slowing correlates with elevation of N-terminal PTH fragment
  • PTH raises alkaline phosphatase in the brain, which promotes tau protein binding to muscarinic receptors in the hippocampus, increasing intracellular Ca²+ and causing neuronal cell death
  • Treatment with 1,25-dihydroxyvitamin D improves EEG and reduces PTH levels
Comprehensive Clinical Nephrology; Bradley & Daroff's Neurology

Neurotransmitter Disruption

  • Norepinephrine depletion and central dopamine suppression - linked to impaired motor activity
  • Serotonin excess - high tryptophan entry across the BBB in uremia increases serotonin synthesis, contributing to anorexia
  • Myoinositol, carnitine, indoxyl sulfate, and polyamines accumulate and impair neuronal function

Drug Accumulation

Reduced renal clearance leads to toxic accumulation of drug metabolites:
  • Meperidine metabolites (via cation secretory transport impairment)
  • Cimetidine, acyclovir (via OAT3 inhibition)
  • Metoclopramide, phenothiazines, antiepileptics (gabapentin), opioids - provoke asterixis and myoclonus in CKD patients

Anemia

Erythropoietin administration in short-term studies has been associated with improved cognitive function and electrophysiologic testing, suggesting anemia contributes to UE. - Brenner & Rector's The Kidney

Clinical Manifestations

Early Encephalopathy (Mental)

  • Mood swings, irritability, apathy, fatigue
  • Impaired concentration, loss of recent memory
  • Insomnia, depression (often underdiagnosed)
  • Subtle attention and visuospatial deficits

Early Encephalopathy (Motor)

  • Fine action tremor
  • Asterixis - intermittent loss of antigravity muscle tone (negative myoclonus); classically tested with hands outstretched; also visible in protruded tongue
  • Myoclonus - lightning-quick, arrhythmic, asynchronous jerks involving parts of muscles, whole muscles, or limbs; present during wakefulness AND sleep
  • Hyperreflexia, dysarthria, altered gait

Late / Severe Encephalopathy

  • Confusion, delirium, psychosis (hallucinations, delusions)
  • Seizures (the "uremic twitch-convulsive syndrome" described by Adams & Victor)
  • Stupor and coma (typically quiet, not agitated)
  • Kussmaul breathing → Cheyne-Stokes breathing (from concurrent metabolic acidosis)
Key point: The degree of azotemia alone correlates poorly with the presence or severity of encephalopathy. Symptoms characteristically fluctuate hour to hour or day to day. About 30% of dialysis patients have mild neuropsychiatric symptoms; ~10% have severe impairment.
Adams & Victor's Principles of Neurology, 12th Ed.; Comprehensive Clinical Nephrology, 7th Ed.

Investigations

TestFinding
EEGGeneralized slowing with excess theta and delta activity; bilateral spike-wave complexes possible; EEG severity tracks clinical status and improves with treatment
CSFIncreased protein (<1 g/L); slight pleocytosis (<25 cells/mL); pressure normal
Brain MRIWhite matter lesions (small vessel disease); brain edema on DWI; decreased brain volume in chronic cases; reduced frontal cortical perfusion
Brain imaging vs liverIn hepatic encephalopathy, characteristic signal changes (T1 hyperintensity in globus pallidus); in uremia, imaging is largely non-specific
Serum Ca, MgCheck - hypocalcemia and hypomagnesemia can mimic uremic encephalopathy
Bradley & Daroff's Neurology; Brenner & Rector's The Kidney

Diagnosis

Diagnosis requires:
  1. Characteristic symptoms (as above)
  2. Severe renal dysfunction
  3. Exclusion of other causes (hypertensive encephalopathy, subdural hematoma - important because uremic patients are prone to intracranial hemorrhage due to coagulopathy and hypertension; meningitis; drug toxicity; metabolic acidosis; hypo/hypercalcemia)
Confirmation: Symptoms disappear with successful renal replacement therapy.
Distinguish from:
  • Hypertensive encephalopathy (PRES): Myoclonic-twitch syndrome is NOT a feature of hypertensive encephalopathy - its presence points to true uremia. Volhard introduced the term "pseudouremia" for hypertensive cerebral effects.
  • Dialysis dysequilibrium syndrome: A separate entity from dialysis treatment itself

Treatment

Primary Treatment - Renal Replacement Therapy (RRT)

  • Hemodialysis or peritoneal dialysis: Symptoms typically regress within days to weeks after initiation
  • Renal transplantation: Most effective - results in symptom resolution within days; eliminates uremic solutes across a wide molecular-weight range
  • Mild symptoms may persist even after adequate dialysis

Supportive Management

  • Correct metabolic acidosis
  • Treat secondary hyperparathyroidism (1,25-dihydroxyvitamin D)
  • Treat anemia (erythropoietin)
  • Avoid or dose-adjust renally-cleared neurotoxic drugs (opioids especially meperidine, gabapentin, metoclopramide)
  • Seizure management: use antiepileptics with caution - many require dose adjustment in renal failure

Key Differences from Hepatic Encephalopathy

FeatureUremic EncephalopathyHepatic Encephalopathy
Primary toxinsGuanidino compoundsAmmonia
Receptor effectNMDA agonism + GABA antagonism (excitatory)GABAergic enhancement (inhibitory)
MotorMyoclonus, twitch-convulsive syndrome prominentAsterixis prominent
Brain imagingNon-specific, no characteristic signal changeT1 hyperintensity globus pallidus (Mn deposition)
Brain inflammationProminent (vascular permeability increased)Less prominent
TreatmentRRT / transplantLactulose, rifaximin, liver transplant

Sources:
  • Comprehensive Clinical Nephrology, 7th Edition (Elsevier)
  • Brenner and Rector's The Kidney (Elsevier) - dedicated chapter on neurologic complications
  • Bradley and Daroff's Neurology in Clinical Practice
  • Adams and Victor's Principles of Neurology, 12th Edition

copd

Reading File
COPD is a broad topic. Let me search for dedicated sections across the library in parallel.
Searching sources...
Finding Sources
Searching PubMed

"chronic obstructive pulmonary disease"[MeSH Terms] AND management

Good sources found. Let me read the key blocks in parallel - Fishman's (the pulmonary gold standard), Robbins (pathology), Katzung (pharmacology), and Costanzo (physiology).
Reading File
Reading File
Reading File
Reading File
Good foundation. Now let me get the Fishman's overview/definition block and search for GOLD staging + pathology details.
Reading File
Finding Sources
Finding Sources
Now let me get the key clinical/management content from Fishman's main COPD chapter and Murray & Nadel.
Reading File
Finding Sources
I now have comprehensive material from multiple top-tier textbooks. Let me compile the full, detailed answer.

Chronic Obstructive Pulmonary Disease (COPD)


Definition

COPD is a common, preventable, and treatable disease characterized by persistent, not fully reversible airflow limitation that is progressive and associated with an enhanced chronic inflammatory response of the lungs to noxious particles or gases - most importantly cigarette smoke. It encompasses two overlapping conditions: emphysema and chronic bronchitis.
  • Chronic bronchitis is defined clinically: persistent productive cough for at least 3 consecutive months in at least 2 consecutive years
  • Emphysema is defined anatomically: enlargement of airspaces distal to terminal bronchioles with destruction of alveolar walls
Robbins & Kumar Basic Pathology; Katzung's Basic & Clinical Pharmacology, 16th Ed.

Epidemiology & Risk Factors

  • Third most common cause of death in the United States
  • Accounts for >$40 billion/year in direct and indirect healthcare costs
  • Cigarette smoking is the major risk factor; historically assumed to affect only 15-30% of habitual smokers, but radiographic evidence shows progressive changes in bronchial wall thickness and loss of lung tissue even in smokers with normal spirometry
  • Other risk factors: air pollution, occupational dusts/fumes, recurrent respiratory infections, genetic factors
Key genetic risk factor: Alpha-1 antitrypsin (A1AT) deficiency - A1AT is a serine protease inhibitor that inactivates neutrophil elastase. Deficiency → unchecked protease activity → panacinar emphysema, particularly in lower lobes. Screen for A1AT deficiency in all patients with persistent airflow obstruction, especially young patients or non-smokers.
Katzung; Murray & Nadel's Textbook of Respiratory Medicine

Pathology

Emphysema Subtypes

SubtypeLocationPrimary Cause
Centriacinar (centrilobular)Central acinus, respiratory bronchioles; upper lobe predominantCigarette smoking (most common type)
Panacinar (panlobular)Entire acinus uniformly; lower lobe predominantAlpha-1 antitrypsin deficiency
ParaseptalDistal acinus, subpleuralAssociated with spontaneous pneumothorax in young adults
Mechanism of tissue destruction:
  • Neutrophils (and macrophages) recruited by cigarette smoke release proteases (especially neutrophil elastase and matrix metalloproteinases)
  • These destroy elastin in alveolar walls
  • A1AT (and other antiproteases) normally counterbalance this; when this balance is disrupted, emphysema results
  • "Protease-antiprotease imbalance" is the central theory

Chronic Bronchitis Pathology

  • Hyperplasia of mucus-secreting glands in the trachea and large airways (Reid index - ratio of gland thickness to wall thickness - increased)
  • Goblet cell metaplasia in small airways
  • Small airway inflammation = chronic bronchiolitis (this causes the obstruction, not the mucus gland hypertrophy)
  • Histology: enlarged mucous glands, goblet cell metaplasia, inflammatory infiltrate, bronchiolar wall fibrosis

Mucus in COPD

MUC5AC concentration is increased 10-fold and MUC5B 3-fold in severe COPD. Mucus hyperconcentration leads to failure of mucociliary transport and mucus adhesion to airway surfaces. Small airway mucus occlusion correlates with degree of airflow obstruction and predicts longevity.
Fishman's Pulmonary Diseases and Disorders; Robbins & Kumar

Pathophysiology

Airflow Obstruction

  • Reduced FEV1 with normal or near-normal FVC → reduced FEV1/FVC ratio (<0.70 post-bronchodilator = diagnostic criterion)
  • In emphysema: loss of elastic recoil → airways collapse on expiration → airtrapping
  • In chronic bronchitis: luminal narrowing from inflammation, mucus, and wall remodeling

Hyperinflation

  • Static hyperinflation: Increased lung compliance (emphysema) raises the equilibrium volume of the respiratory system
  • Dynamic hyperinflation: During exercise or increased ventilation demand, insufficient expiratory time → air trapping → end-expiratory lung volume (EELV) fails to decline, inspiratory reserve volume (IRV) shrinks, tidal volume augmentation is impaired
  • Results in: increased work of breathing, inspiratory muscle weakness (diaphragm flattened and mechanically disadvantaged), "neuromechanical uncoupling" - disparity between respiratory effort and ventilatory output
  • Classic sign: barrel chest (increased AP diameter)

Ventilation-Perfusion (V/Q) Mismatch

  • The major cause of hypoxemia in COPD
  • Underventilated units with continued perfusion → shunt-like effect → PaO2 falls
  • Alveolar gas equation demonstrates widened A-a gradient
  • Exercise-related desaturation is more common in emphysema-predominant than bronchitis-predominant disease

Gas Exchange Failure

  • Type 1 respiratory failure (hypoxemia alone): V/Q mismatch in early/moderate COPD; patient hyperventilates to compensate → PaCO2 normal or low, pH alkalotic
  • Type 2 respiratory failure (hypoxemia + hypercapnia): PaCO2 does not usually rise until FEV1 falls to 20-25% of predicted
    • Mechanisms: increased dead space (Vds/VT unfavorable), inspiratory muscle weakness, blunted ventilatory response to CO2, dynamic hyperinflation
    • Diaphragm muscle changes: reduced force per cross-sectional area, reduced myosin heavy chain content, decreased Ca²+ sensitivity, slower cross-bridge cycling
    • Persistent hypercapnia = poor prognostic indicator; survival is shorter than in normocapnic COPD
Fishman's; Costanzo Physiology 7th Ed.

Clinical Subtypes (Classic Phenotypes)

Feature"Pink Puffer" (Emphysema)"Blue Bloater" (Chronic Bronchitis)
BuildThin, cachecticOverweight
ColorPink (no cyanosis at rest)Cyanotic ("blue")
CoughMinimalProminent, productive
DyspneaSevereModerate
PaO2Near normal at restLow
PaCO2Low or normalElevated
Cor pulmonaleLateEarly
PolycythemiaAbsentPresent
Note: Most patients have a mixture of both; pure phenotypes are less common clinically.

Spirometry & GOLD Classification

Diagnosis requires: Post-bronchodilator FEV1/FVC < 0.70
GOLD Spirometric Grades (based on post-BD FEV1 % predicted):
GOLD GradeSeverityFEV1 % Predicted
GOLD 1Mild≥ 80%
GOLD 2Moderate50-79%
GOLD 3Severe30-49%
GOLD 4Very Severe< 30%
GOLD A/B/E Groups (symptom + exacerbation history assessment for treatment guidance):
  • Group A: Low symptoms (mCAT<10 or mMRC<2), 0-1 exacerbation (not leading to hospitalization)
  • Group B: High symptoms (mCAT≥10 or mMRC≥2), 0-1 exacerbation
  • Group E: ≥2 exacerbations OR ≥1 leading to hospitalization

Clinical Features

Symptoms:
  • Progressive exertional dyspnea (hallmark)
  • Chronic productive cough (especially morning sputum in bronchitis)
  • Wheezing
  • Exercise intolerance (reduced ventilatory capacity + increased ventilatory requirement)
Signs:
  • Barrel chest, increased AP diameter
  • Hyperresonance to percussion
  • Diminished breath sounds
  • Prolonged expiratory phase, expiratory wheeze
  • Use of accessory muscles
  • Cyanosis (bronchitic type)
  • Asterixis (in hypercapnic encephalopathy)
  • Signs of cor pulmonale: elevated JVP, peripheral edema, loud P2
ABG example in moderate COPD with hyperventilation:
  • pH 7.47 (alkalotic), PaO2 60 mmHg, PaCO2 30 mmHg, SaO2 90%
  • Interpretation: Hypoxemia from V/Q mismatch + compensatory respiratory alkalosis from hyperventilation driven by hypoxemia stimulating peripheral chemoreceptors
Costanzo Physiology; Fishman's

Complications

  • Cor pulmonale: Pulmonary hypertension from hypoxic vasoconstriction → right ventricular hypertrophy/failure
  • Polycythemia: Compensatory erythrocytosis from chronic hypoxemia
  • Acute exacerbations (AECOPD): Usually triggered by viral URTI (rhinovirus most common) or bacterial infection (H. influenzae, S. pneumoniae, M. catarrhalis); also air pollution, pulmonary embolism
  • Spontaneous pneumothorax (emphysema with bullae)
  • Respiratory failure: Type 1 or 2
  • Lung cancer: Risk independently elevated in smokers with COPD
  • Cardiovascular disease: Major comorbidity and leading cause of death in mild-moderate COPD
  • Cachexia, muscle wasting, osteoporosis, depression, anxiety

Treatment

Pharmacological (Stable COPD)

Bronchodilators are the cornerstone of therapy:
Drug ClassExamplesNotes
Short-acting β2 agonist (SABA)Albuterol (salbutamol)Rescue therapy; also effective in COPD despite incomplete reversibility
Short-acting anticholinergic (SAMA)Ipratropium bromideBlocks muscarinic receptors; SABA + SAMA combination more effective than either alone
Long-acting β2 agonist (LABA)Salmeterol, formoterol, indacaterolFor persistent dyspnea; can combine with LAMA
Long-acting anticholinergic/antimuscarinic (LAMA)Tiotropium, umeclidinium, glycopyrroniumPreferred long-acting bronchodilator in COPD; reduces exacerbations more than LABA alone
LABA + LAMA combinationIndacaterol/glycopyrronium, etc.Superior to monotherapy; first-line for Group B and many Group E
Inhaled corticosteroids (ICS):
  • Less central than in asthma; associated with increased pneumonia risk
  • Recommended only in: severe airflow obstruction, history of exacerbations, features of asthma-COPD overlap
  • Blood eosinophil count guides ICS use: higher eosinophils (≥300 cells/µL) = greater benefit from ICS; low eosinophils = little/no ICS benefit
Other agents:
  • Roflumilast: Selective PDE4 inhibitor; reduces exacerbation frequency; for severe COPD with chronic bronchitis phenotype
  • Theophylline: Older agent; possible diaphragm contractility benefit and corticosteroid sensitization, but a large RCT of low-dose theophylline failed to show benefit on exacerbation frequency
  • Azithromycin (long-term): Reduces exacerbations in selected patients; risk of hearing loss, cardiac arrhythmia, antibiotic resistance
Katzung's Basic & Clinical Pharmacology; GOLD guidelines

Non-Pharmacological

InterventionEvidence/Notes
Smoking cessationMost effective intervention to slow decline; reduces FEV1 loss rate
Long-term oxygen therapy (LTOT)For PaO2 ≤55 mmHg (or ≤59 mmHg with cor pulmonale); improves survival in hypoxemic COPD
Pulmonary rehabilitationImproves exercise tolerance, dyspnea, and quality of life; reduces hospitalizations
VaccinationInfluenza, pneumococcal, COVID-19, RSV (newer evidence)
Non-invasive ventilation (NIV/NIPPV)For chronic hypercapnia, especially nocturnal; reduces persistent hypercapnia
Lung volume reduction surgery (LVRS)Selected patients with upper-lobe emphysema and low exercise capacity after rehabilitation
Endobronchial valvesBronchoscopic lung volume reduction for suitable emphysema
Lung transplantationEnd-stage disease; improves quality of life

Acute Exacerbations of COPD (AECOPD)

  • Definition: Acute worsening of respiratory symptoms beyond normal day-to-day variation requiring change in therapy
  • Management differs from asthma exacerbations mainly by routine use of antibiotics (bacterial infection frequent)
    • Antibiotics: beta-lactams (amoxicillin-clavulanate), macrolides, doxycycline, or fluoroquinolones
    • Short-course systemic corticosteroids (5-day course equivalent to longer courses)
    • Bronchodilators (SABA ± SAMA)
    • Controlled oxygen therapy (target SpO2 88-92% to avoid suppressing hypoxic drive in chronic CO2 retainers)
    • NIV (BiPAP) for hypercapnic respiratory failure - reduces need for intubation and mortality
    • Invasive mechanical ventilation if NIV fails
  • Mortality of AECOPD is greater than asthma exacerbations due to older age and cardiovascular comorbidities
Katzung; Fishman's Pulmonary Diseases

Prognosis

BODE Index (Body mass index, airflow Obstruction, Dyspnea, Exercise capacity) - better predictor of mortality than FEV1 alone:
  • Incorporates: BMI, FEV1 %, mMRC dyspnea score, 6-minute walk distance
Persistent hypercapnia is a poor prognostic sign - survival shorter than normocapnic COPD patients.

Sources:
  • Robbins & Kumar Basic Pathology (Elsevier)
  • Fishman's Pulmonary Diseases and Disorders, 2-Volume Set (McGraw-Hill)
  • Katzung's Basic and Clinical Pharmacology, 16th Edition
  • Costanzo Physiology, 7th Edition
  • Murray & Nadel's Textbook of Respiratory Medicine
  • GOLD Guidelines - Global Initiative for Chronic Obstructive Lung Disease

give both in a pdf

Reading File
Running Command

mkdir -p /tmp/workspace/medical-notes && ls /tmp/workspace/medical-notes/

Writing File

~/medical-notes/generate_notes_pdf.py

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

OUTPUT = "/tmp/workspace/medical-notes/Medical_Notes_UE_COPD.pdf"

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=2*cm, rightMargin=2*cm,
    topMargin=2.2*cm, bottomMargin=2.2*cm,
    title="Medical Notes: Uremic Encephalopathy & COPD",
    author="Orris Medical Assistant"
)

W = A4[0] - 4*cm  # usable width

# ── Colour palette ──────────────────────────────────────────────────────────
C_DARK_BLUE  = colors.HexColor("#1a3a5c")
C_MID_BLUE   = colors.HexColor("#2c6fad")
C_LIGHT_BLUE = colors.HexColor("#d6e8f8")
C_ACCENT     = colors.HexColor("#e8f4e8")
C_ORANGE     = colors.HexColor("#e07b39")
C_TBL_HDR    = colors.HexColor("#2c6fad")
C_TBL_ALT    = colors.HexColor("#eef5fb")
C_RULE       = colors.HexColor("#2c6fad")
C_BOX_BG     = colors.HexColor("#fff8e1")
C_BOX_BORDER = colors.HexColor("#f0a500")

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

def make_style(name, parent="Normal", **kwargs):
    s = ParagraphStyle(name, parent=styles[parent])
    for k, v in kwargs.items():
        setattr(s, k, v)
    return s

sTitle       = make_style("sTitle",      fontName="Helvetica-Bold",   fontSize=22,
                           textColor=C_DARK_BLUE, alignment=TA_CENTER, spaceAfter=4)
sSubtitle    = make_style("sSubtitle",   fontName="Helvetica",        fontSize=11,
                           textColor=C_MID_BLUE,  alignment=TA_CENTER, spaceAfter=14)
sChapterHead = make_style("sChapterHead",fontName="Helvetica-Bold",   fontSize=17,
                           textColor=colors.white, spaceBefore=6, spaceAfter=6, leading=22)
sH1          = make_style("sH1",         fontName="Helvetica-Bold",   fontSize=13,
                           textColor=C_DARK_BLUE, spaceBefore=12, spaceAfter=4, leading=17)
sH2          = make_style("sH2",         fontName="Helvetica-Bold",   fontSize=11,
                           textColor=C_MID_BLUE,  spaceBefore=8,  spaceAfter=3, leading=15)
sBody        = make_style("sBody",       fontName="Helvetica",        fontSize=9.5,
                           leading=14, spaceAfter=4, alignment=TA_JUSTIFY)
sBullet      = make_style("sBullet",     fontName="Helvetica",        fontSize=9.5,
                           leading=13, spaceAfter=2, leftIndent=14, firstLineIndent=-10)
sNote        = make_style("sNote",       fontName="Helvetica-Oblique",fontSize=9,
                           textColor=colors.HexColor("#555555"), leading=13, spaceAfter=4)
sSource      = make_style("sSource",     fontName="Helvetica-Oblique",fontSize=8.5,
                           textColor=colors.HexColor("#444444"), leading=12, spaceAfter=2)
sTableHdr    = make_style("sTableHdr",   fontName="Helvetica-Bold",   fontSize=9,
                           textColor=colors.white, alignment=TA_CENTER, leading=12)
sTableCell   = make_style("sTableCell",  fontName="Helvetica",        fontSize=9,
                           leading=12, alignment=TA_LEFT)
sTableCellC  = make_style("sTableCellC", fontName="Helvetica",        fontSize=9,
                           leading=12, alignment=TA_CENTER)

# ── Helpers ───────────────────────────────────────────────────────────────────
def rule(color=C_RULE, thickness=1.2):
    return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=6, spaceBefore=2)

def h1(txt):
    return [Spacer(1, 4), Paragraph(txt, sH1), rule(C_MID_BLUE, 0.8)]

def h2(txt):
    return [Paragraph(txt, sH2)]

def body(txt):
    return Paragraph(txt, sBody)

def bullet(items):
    rows = []
    for it in items:
        rows.append(Paragraph(f"• {it}", sBullet))
    return rows

def spacer(h=6):
    return Spacer(1, h)

def chapter_banner(text, color=C_DARK_BLUE):
    """Full-width coloured banner for chapter heading."""
    tbl = Table([[Paragraph(text, sChapterHead)]], colWidths=[W])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), color),
        ("LEFTPADDING",  (0,0), (-1,-1), 12),
        ("RIGHTPADDING", (0,0), (-1,-1), 12),
        ("TOPPADDING",   (0,0), (-1,-1), 8),
        ("BOTTOMPADDING",(0,0), (-1,-1), 8),
        ("ROUNDEDCORNERS", [4]),
    ]))
    return tbl

def make_table(headers, rows, col_widths=None, alt=True):
    data = [[Paragraph(h, sTableHdr) for h in headers]]
    for i, row in enumerate(rows):
        data.append([Paragraph(str(c), sTableCell) for c in row])
    if col_widths is None:
        col_widths = [W / len(headers)] * len(headers)
    tbl = Table(data, colWidths=col_widths, repeatRows=1)
    style = [
        ("BACKGROUND",    (0,0), (-1,0),  C_TBL_HDR),
        ("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.white, C_TBL_ALT] if alt else [colors.white]),
        ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#bbbbbb")),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ("LEFTPADDING",   (0,0), (-1,-1), 6),
        ("RIGHTPADDING",  (0,0), (-1,-1), 6),
        ("TOPPADDING",    (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ]
    tbl.setStyle(TableStyle(style))
    return tbl

def key_box(label, text):
    inner = Table([
        [Paragraph(f"<b>{label}</b>", sTableCell)],
        [Paragraph(text, sTableCell)],
    ], colWidths=[W-16])
    inner.setStyle(TableStyle([
        ("BACKGROUND",   (0,0), (-1,-1), C_BOX_BG),
        ("BOX",          (0,0), (-1,-1), 1.2, C_BOX_BORDER),
        ("LEFTPADDING",  (0,0), (-1,-1), 8),
        ("RIGHTPADDING", (0,0), (-1,-1), 8),
        ("TOPPADDING",   (0,0), (-1,-1), 5),
        ("BOTTOMPADDING",(0,0), (-1,-1), 5),
    ]))
    return inner

# ════════════════════════════════════════════════════════════════════════════
# CONTENT
# ════════════════════════════════════════════════════════════════════════════
story = []

# ── Cover ────────────────────────────────────────────────────────────────────
story.append(Spacer(1, 3*cm))
story.append(Paragraph("Medical Notes", sTitle))
story.append(Paragraph("Uremic Encephalopathy  |  COPD", sSubtitle))
story.append(Spacer(1, 0.5*cm))
story.append(rule(C_DARK_BLUE, 2))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "Sources: Comprehensive Clinical Nephrology 7th Ed. · Brenner &amp; Rector's The Kidney · "
    "Adams &amp; Victor's Neurology 12th Ed. · Bradley &amp; Daroff's Neurology · "
    "Fishman's Pulmonary Diseases · Robbins &amp; Kumar Basic Pathology · "
    "Katzung's Pharmacology 16th Ed. · Costanzo Physiology 7th Ed.", sSource))
story.append(PageBreak())

# ════════════════════════════════════════════════════════════════════════════
# PART 1 – UREMIC ENCEPHALOPATHY
# ════════════════════════════════════════════════════════════════════════════
story.append(chapter_banner("PART 1 — UREMIC ENCEPHALOPATHY (Metabolic Encephalopathy via Kidney)", C_DARK_BLUE))
story.append(spacer(10))

story.append(body(
    "Uremic encephalopathy (UE) is a syndrome of brain dysfunction resulting from renal failure — "
    "either acute kidney injury (AKI) or end-stage kidney disease (ESKD). It ranges from "
    "imperceptible cognitive changes to coma and death. Importantly, <b>the degree of azotemia "
    "alone correlates poorly</b> with the presence or severity of encephalopathy, and symptoms "
    "characteristically fluctuate hour to hour or day to day."
))
story.append(spacer())

# Pathophysiology
story += h1("1. Pathophysiology")

story += h2("1.1 Uremic Toxin Accumulation")
story.append(body(
    "Among the 75 solutes in the European Uremic Toxin (EUTox) database, ~9% (7 solutes) are "
    "directly associated with neurologic effects. The most important are the <b>guanidino compounds</b>:"
))
story += bullet([
    "Guanidinouscinic acid and methylguanidine are increased <b>100-fold</b> in uremic brain tissue and CSF.",
    "Antagonize <b>GABA receptors</b> (inhibitory) while simultaneously acting as <b>NMDA receptor agonists</b> (excitatory) → enhanced cortical excitability.",
    "Guanidinosuccinic acid, methylguanidine, and homoarginine can directly induce seizures via NMDA receptors and calcium channel modulation.",
    "Gut microbial metabolites (phenylalanine, benzoate, glutamate metabolites) also linked to cognitive impairment in dialysis patients.",
])
story.append(spacer())

story += h2("1.2 Blood-Brain Barrier Disruption")
story += bullet([
    "Kidney injury activates inflammatory cytokines that cross or disrupt the BBB.",
    "Animal models show increased brain inflammation + vascular permeability in uremic encephalopathy (distinct pattern from hepatic encephalopathy).",
    "<b>Asymmetric dimethylarginine (ADMA)</b> — elevated in CKD — inhibits eNOS and correlates with cerebrovascular complications.",
    "Indoxyl sulfate, polyamines, myoinositol, carnitine disrupt solute transport and neuronal membrane permeability.",
])
story.append(spacer())

story += h2("1.3 Secondary Hyperparathyroidism")
story += bullet([
    "Brain calcium content doubles within days of acute renal failure onset.",
    "PTH elevates alkaline phosphatase in brain → promotes tau binding to muscarinic receptors in hippocampus → increased intracellular Ca²⁺ → neuronal cell death.",
    "EEG slowing correlates with N-terminal PTH fragment levels.",
    "1,25-dihydroxyvitamin D treatment improves EEG and reduces PTH.",
    "High FGF-23 (via α-klotho interaction) and low α-klotho both associated with increased dementia risk.",
])
story.append(spacer())

story += h2("1.4 Neurotransmitter Disruption")
story += bullet([
    "Norepinephrine depletion and central <b>dopamine suppression</b> — impairs motor activity.",
    "High tryptophan entry across BBB → excess serotonin synthesis → anorexia.",
    "Neuropeptide Y (NPY) levels dysregulated — promotes endothelial dysfunction.",
])
story.append(spacer())

story += h2("1.5 Drug Accumulation")
story.append(body("Reduced renal clearance → toxic accumulation of:"))
story += bullet([
    "<b>Meperidine metabolites</b> (renal cation secretory transport impairment)",
    "<b>Cimetidine, acyclovir</b> (OAT3 inhibition)",
    "<b>Metoclopramide, phenothiazines, gabapentin, opioids</b> — provoke asterixis and myoclonus in CKD",
])
story.append(spacer(10))

# Clinical Manifestations
story += h1("2. Clinical Manifestations")
story.append(make_table(
    ["Stage", "Mental Features", "Motor Features"],
    [
        ["Early", "Mood swings, irritability, apathy, fatigue\nImpaired concentration, loss of recent memory\nInsomnia, depression", "Fine action tremor\nAsterixis (intermittent loss of antigravity muscle tone)\nMyoclonus (lightning-quick arrhythmic jerks)\nHyperreflexia, dysarthria, altered gait"],
        ["Late / Severe", "Confusion, delirium, psychosis\nHallucinations, delusions\nSeizures (uremic twitch-convulsive syndrome)\nStupor → quiet coma", "Incessant myoclonic twitches (wakefulness and sleep)\nCheyne-Stokes breathing\nKussmaul breathing (metabolic acidosis)"],
    ],
    col_widths=[2.5*cm, 7.5*cm, 7.5*cm]
))
story.append(spacer(4))
story.append(Paragraph(
    "About <b>30%</b> of dialysis patients have mild neuropsychiatric symptoms; ~<b>10%</b> exhibit severe impairment. "
    "Advanced UE with confusion/coma is now predominantly seen in patients where a decision has been made not to start dialysis.",
    sNote))
story.append(spacer(10))

# Investigations
story += h1("3. Investigations")
story.append(make_table(
    ["Test", "Finding"],
    [
        ["EEG", "Generalised slowing with excess theta and delta activity; bilateral spike-wave complexes; severity tracks clinical status; normalises with treatment"],
        ["CSF", "Increased protein (<1 g/L); slight pleocytosis (<25 cells/mL); pressure normal"],
        ["Brain MRI", "Non-specific; white matter lesions (small vessel disease); brain oedema on DWI; decreased brain volume in chronic disease; reduced frontal perfusion on perfusion imaging"],
        ["Serum Ca/Mg", "Must check — hypocalcaemia and hypomagnesaemia can mimic UE"],
        ["Serum BUN/Creatinine", "Elevated but degree does NOT directly correlate with encephalopathy severity"],
    ],
    col_widths=[3.5*cm, 14*cm]
))
story.append(spacer(10))

# Diagnosis
story += h1("4. Diagnosis")
story.append(key_box("Diagnostic Criteria",
    "1. Characteristic symptoms (as above) in a patient with severe renal dysfunction. "
    "2. Exclusion of other causes. "
    "3. Confirmation: symptoms disappear with successful renal replacement therapy."))
story.append(spacer(6))
story.append(body("<b>Key differential:</b> Hypertensive encephalopathy (PRES) — the myoclonic-twitch syndrome "
    "is NOT a feature of hypertensive encephalopathy; its presence points to true uremia. "
    "Volhard introduced 'pseudouremia' for hypertensive cerebral effects. "
    "Also exclude: subdural haematoma (coagulopathy/hypertension in uremia), meningitis, drug toxicity, metabolic acidosis."))
story.append(spacer(10))

# Comparison with Hepatic Encephalopathy
story += h1("5. Uremic vs Hepatic Encephalopathy")
story.append(make_table(
    ["Feature", "Uremic Encephalopathy", "Hepatic Encephalopathy"],
    [
        ["Primary toxins", "Guanidino compounds", "Ammonia"],
        ["Receptor effect", "NMDA agonism + GABA antagonism (excitatory)", "GABAergic enhancement (inhibitory)"],
        ["Dominant motor sign", "Myoclonus; uremic twitch-convulsive syndrome", "Asterixis prominent"],
        ["Brain MRI", "Non-specific; no characteristic signal change", "T1 hyperintensity globus pallidus (Mn deposition)"],
        ["Brain inflammation", "Prominent; increased vascular permeability", "Less prominent"],
        ["Treatment", "Renal replacement therapy / transplant", "Lactulose, rifaximin, liver transplant"],
    ],
    col_widths=[4*cm, 8*cm, 5.5*cm]
))
story.append(spacer(10))

# Treatment
story += h1("6. Treatment")
story += h2("6.1 Renal Replacement Therapy (Primary Treatment)")
story += bullet([
    "<b>Haemodialysis or peritoneal dialysis</b> — symptoms typically regress within days to weeks.",
    "<b>Renal transplantation</b> — most effective; resolution within days; eliminates uremic solutes across a wide molecular-weight range.",
    "Mild symptoms may persist even after adequate dialysis.",
])
story.append(spacer(4))
story += h2("6.2 Supportive Management")
story += bullet([
    "Correct metabolic acidosis",
    "Treat secondary hyperparathyroidism (1,25-dihydroxyvitamin D)",
    "Treat anaemia with erythropoietin",
    "Avoid or dose-adjust renally-cleared neurotoxic drugs (especially meperidine, gabapentin, metoclopramide)",
    "Antiepileptics for seizures — use with caution and dose-adjust for renal failure",
])

story.append(PageBreak())

# ════════════════════════════════════════════════════════════════════════════
# PART 2 – COPD
# ════════════════════════════════════════════════════════════════════════════
story.append(chapter_banner("PART 2 — CHRONIC OBSTRUCTIVE PULMONARY DISEASE (COPD)", C_MID_BLUE))
story.append(spacer(10))

story.append(body(
    "COPD is a common, preventable, and treatable disease characterised by <b>persistent, "
    "not fully reversible airflow limitation</b> that is progressive and associated with an "
    "enhanced chronic inflammatory response to noxious particles or gases — primarily cigarette smoke. "
    "It is the <b>third most common cause of death</b> in the United States and accounts for "
    "&gt;$40 billion/year in direct and indirect healthcare costs."
))
story.append(spacer())

# Definition
story += h1("1. Definition & Subtypes")
story.append(make_table(
    ["Subtype", "Definition", "Key Features"],
    [
        ["Chronic Bronchitis", "Persistent productive cough ≥3 months/year for ≥2 consecutive years", "Mucus hypersecretion from large airway gland hyperplasia; obstruction from small airway inflammation (chronic bronchiolitis)"],
        ["Emphysema", "Enlargement of airspaces distal to terminal bronchioles with alveolar wall destruction", "Loss of elastic recoil; air trapping; increased lung compliance; barrel chest"],
    ],
    col_widths=[3.5*cm, 6*cm, 8*cm]
))
story.append(spacer(6))
story.append(Paragraph(
    "Most patients have a mixture of both subtypes. The two classic phenotypes are the "
    "'<b>Pink Puffer</b>' (emphysema-predominant: thin, non-cyanotic, severe dyspnoea, near-normal PaO₂) "
    "and the '<b>Blue Bloater</b>' (bronchitis-predominant: cyanotic, productive cough, elevated PaCO₂, cor pulmonale).",
    sNote))
story.append(spacer(10))

# Epidemiology & Risk Factors
story += h1("2. Risk Factors")
story += bullet([
    "<b>Cigarette smoking</b> — major risk factor; radiographic evidence of progressive changes even in smokers with normal spirometry.",
    "<b>Alpha-1 antitrypsin (A1AT) deficiency</b> — A1AT inhibits neutrophil elastase; deficiency → unchecked protease activity → panacinar emphysema (lower lobe predominant). Screen all patients with persistent airflow obstruction, especially young patients/non-smokers.",
    "Air pollution, occupational dusts and fumes",
    "Recurrent respiratory infections in childhood",
    "Asthma (risk factor for accelerated FEV₁ decline)",
])
story.append(spacer(10))

# Pathology
story += h1("3. Pathology")
story += h2("3.1 Emphysema Subtypes")
story.append(make_table(
    ["Subtype", "Location", "Cause"],
    [
        ["Centriacinar (centrilobular)", "Central acinus, respiratory bronchioles; upper lobe predominant", "Cigarette smoking (most common type)"],
        ["Panacinar (panlobular)", "Entire acinus uniformly; lower lobe predominant", "Alpha-1 antitrypsin deficiency"],
        ["Paraseptal", "Distal acinus, subpleural", "Associated with spontaneous pneumothorax in young adults"],
    ],
    col_widths=[4.5*cm, 6.5*cm, 6.5*cm]
))
story.append(spacer(6))

story += h2("3.2 Mechanism — Protease-Antiprotease Imbalance")
story += bullet([
    "Cigarette smoke recruits <b>neutrophils and macrophages</b> → release of <b>neutrophil elastase</b> and matrix metalloproteinases (MMPs).",
    "These destroy <b>elastin</b> in alveolar walls.",
    "A1AT normally counterbalances this; when balance is disrupted → emphysema.",
])
story.append(spacer(6))

story += h2("3.3 Chronic Bronchitis Pathology")
story += bullet([
    "Hyperplasia of mucus-secreting glands (Reid index increased — ratio of gland thickness to wall thickness).",
    "Goblet cell metaplasia in small airways.",
    "Chronic bronchiolitis causes obstruction (not the large-airway mucus gland hypertrophy).",
    "MUC5AC concentration increased <b>10-fold</b> and MUC5B <b>3-fold</b> in severe COPD.",
    "Small airway mucus occlusion correlates with degree of airflow obstruction and <b>predicts longevity</b>.",
])
story.append(spacer(10))

# Pathophysiology
story += h1("4. Pathophysiology")
story += h2("4.1 Airflow Obstruction")
story += bullet([
    "Reduced FEV₁ with normal or near-normal FVC → reduced <b>FEV₁/FVC ratio (&lt;0.70 post-bronchodilator)</b> = diagnostic criterion.",
    "Emphysema: loss of elastic recoil → dynamic airway collapse on expiration → air trapping.",
    "Chronic bronchitis: luminal narrowing from inflammation, mucus, and wall remodelling.",
])
story.append(spacer(4))

story += h2("4.2 Hyperinflation")
story += bullet([
    "<b>Static hyperinflation:</b> Increased lung compliance raises equilibrium volume of respiratory system.",
    "<b>Dynamic hyperinflation:</b> During exercise, insufficient expiratory time → air trapping → EELV fails to decline → IRV shrinks → tidal volume augmentation impaired.",
    "Results in: increased work of breathing, <b>diaphragm flattening</b> (mechanical disadvantage), 'neuromechanical uncoupling'.",
    "Diaphragm muscle changes: reduced force/cross-sectional area, reduced myosin heavy chain content, decreased Ca²⁺ sensitivity, slower cross-bridge cycling kinetics.",
    "Classic sign: <b>barrel chest</b> (increased AP diameter).",
])
story.append(spacer(4))

story += h2("4.3 V/Q Mismatch & Gas Exchange")
story += bullet([
    "Primary cause of hypoxemia in COPD — underventilated alveoli with continued perfusion.",
    "Widened <b>A-a gradient</b>; PaO₂ falls below calculated PAO₂.",
    "Exercise-related desaturation more common in emphysema-predominant than bronchitis-predominant disease.",
    "<b>Type 1 RF</b> (hypoxaemia alone): early/moderate COPD; patient hyperventilates → PaCO₂ normal or low.",
    "<b>Type 2 RF</b> (hypoxaemia + hypercapnia): PaCO₂ does not usually rise until FEV₁ falls to <b>20-25% of predicted</b>.",
    "Persistent hypercapnia = poor prognostic sign; survival shorter than normocapnic COPD.",
])
story.append(spacer(4))

story.append(key_box("ABG Example — Moderate COPD with Hyperventilation",
    "pH 7.47 (alkalotic) | PaO₂ 60 mmHg | PaCO₂ 30 mmHg | SaO₂ 90%\n"
    "Interpretation: Hypoxaemia from V/Q mismatch + compensatory respiratory alkalosis "
    "driven by hypoxaemia stimulating peripheral chemoreceptors."))
story.append(spacer(10))

# Spirometry / GOLD
story += h1("5. Spirometry & GOLD Classification")
story.append(body("<b>Diagnosis requires:</b> Post-bronchodilator FEV₁/FVC &lt; 0.70"))
story.append(spacer(4))
story.append(make_table(
    ["GOLD Grade", "Severity", "FEV₁ % Predicted"],
    [
        ["GOLD 1", "Mild", "≥ 80%"],
        ["GOLD 2", "Moderate", "50–79%"],
        ["GOLD 3", "Severe", "30–49%"],
        ["GOLD 4", "Very Severe", "< 30%"],
    ],
    col_widths=[4*cm, 6*cm, 7.5*cm]
))
story.append(spacer(6))
story.append(make_table(
    ["GOLD Group", "Symptoms (mCAT/mMRC)", "Exacerbation History"],
    [
        ["Group A", "Low (mCAT<10 or mMRC<2)", "0–1 exacerbation (no hospitalisation)"],
        ["Group B", "High (mCAT≥10 or mMRC≥2)", "0–1 exacerbation (no hospitalisation)"],
        ["Group E", "Any", "≥2 exacerbations OR ≥1 leading to hospitalisation"],
    ],
    col_widths=[3*cm, 7*cm, 7.5*cm]
))
story.append(spacer(10))

# Clinical Features
story += h1("6. Clinical Features")
story += h2("Symptoms")
story += bullet([
    "Progressive exertional <b>dyspnoea</b> (hallmark)",
    "Chronic productive cough (especially morning sputum in bronchitis)",
    "Wheezing",
    "Exercise intolerance",
])
story += h2("Signs")
story += bullet([
    "Barrel chest, increased AP diameter",
    "Hyperresonance to percussion",
    "Diminished breath sounds",
    "Prolonged expiratory phase, expiratory wheeze",
    "Use of accessory muscles",
    "Cyanosis (bronchitic type)",
    "Asterixis (in hypercapnic encephalopathy)",
    "Signs of cor pulmonale: elevated JVP, peripheral oedema, loud P₂",
])
story.append(spacer(10))

# Complications
story += h1("7. Complications")
story.append(make_table(
    ["Complication", "Mechanism / Notes"],
    [
        ["Cor pulmonale", "Pulmonary hypertension from hypoxic vasoconstriction → RV hypertrophy/failure"],
        ["Polycythaemia", "Compensatory erythrocytosis from chronic hypoxaemia"],
        ["Acute exacerbations (AECOPD)", "Usually viral URTI (rhinovirus) or bacterial (H. influenzae, S. pneumoniae, M. catarrhalis), air pollution, PE"],
        ["Spontaneous pneumothorax", "Emphysema with bullae rupture"],
        ["Respiratory failure (Type 1 or 2)", "Progressive airflow obstruction and muscle fatigue"],
        ["Lung cancer", "Risk independently elevated; smoking common aetiology"],
        ["Cardiovascular disease", "Major comorbidity and leading cause of death in mild-moderate COPD"],
        ["Cachexia / muscle wasting", "Systemic inflammation, hypoxaemia, nutritional depletion"],
    ],
    col_widths=[5*cm, 12.5*cm]
))
story.append(spacer(10))

# Treatment
story += h1("8. Treatment")
story += h2("8.1 Pharmacological — Stable COPD")
story.append(make_table(
    ["Drug Class", "Examples", "Role"],
    [
        ["SABA", "Albuterol (salbutamol)", "Rescue; acute symptom relief"],
        ["SAMA", "Ipratropium bromide", "Rescue; blocks muscarinic receptors; combines with SABA"],
        ["LABA", "Salmeterol, formoterol, indacaterol", "Persistent dyspnoea; combine with LAMA for additive benefit"],
        ["LAMA", "Tiotropium, umeclidinium, glycopyrronium", "Preferred long-acting bronchodilator; reduces exacerbations more than LABA alone"],
        ["LABA + LAMA", "Indacaterol/glycopyrronium etc.", "Superior to monotherapy; first-line for Groups B and E"],
        ["ICS", "Fluticasone, budesonide", "Only in severe obstruction, frequent exacerbations, or asthma overlap. Use blood eosinophils to guide: ≥300/µL = benefit; low = avoid (pneumonia risk)"],
        ["Roflumilast (PDE4 inhibitor)", "Roflumilast", "Severe COPD with chronic bronchitis phenotype; reduces exacerbation frequency"],
        ["Azithromycin (long-term)", "Azithromycin", "Reduces exacerbations in selected patients; monitor for hearing loss, arrhythmia, resistance"],
    ],
    col_widths=[4*cm, 4.5*cm, 9*cm]
))
story.append(spacer(6))

story += h2("8.2 Non-Pharmacological")
story.append(make_table(
    ["Intervention", "Notes"],
    [
        ["Smoking cessation", "Most effective; slows FEV₁ decline rate"],
        ["Long-term O₂ therapy (LTOT)", "PaO₂ ≤55 mmHg (or ≤59 mmHg with cor pulmonale); improves survival"],
        ["Pulmonary rehabilitation", "Improves exercise tolerance, dyspnoea, QoL; reduces hospitalisations"],
        ["Vaccination", "Influenza, pneumococcal, COVID-19, RSV"],
        ["NIV / NIPPV (BiPAP)", "For chronic hypercapnia (nocturnal); reduces persistent CO₂ retention"],
        ["Lung volume reduction surgery", "Selected patients: upper-lobe emphysema + low exercise capacity post-rehabilitation"],
        ["Endobronchial valves", "Bronchoscopic lung volume reduction in suitable emphysema"],
        ["Lung transplantation", "End-stage disease; improves QoL"],
    ],
    col_widths=[5*cm, 12.5*cm]
))
story.append(spacer(6))

story += h2("8.3 Acute Exacerbations (AECOPD)")
story += bullet([
    "<b>Short-acting bronchodilators</b> (SABA ± SAMA) — increase dose and frequency.",
    "<b>Systemic corticosteroids</b> — 5-day oral prednisolone course (equivalent to longer courses).",
    "<b>Antibiotics</b> — routinely given (unlike asthma); β-lactams, macrolides, doxycycline, or fluoroquinolones.",
    "<b>Controlled O₂</b> — target SpO₂ <b>88–92%</b> to avoid suppressing hypoxic drive in chronic CO₂ retainers.",
    "<b>NIV (BiPAP)</b> — for hypercapnic respiratory failure; reduces need for intubation and mortality.",
    "Mortality of AECOPD greater than asthma exacerbations due to older age and cardiovascular comorbidities.",
])
story.append(spacer(10))

# Prognosis
story += h1("9. Prognosis — BODE Index")
story.append(body(
    "The <b>BODE Index</b> is a better predictor of mortality than FEV₁ alone. It incorporates:"
))
story += bullet([
    "<b>B</b>ody mass index (low BMI = worse prognosis)",
    "airflow <b>O</b>bstruction (FEV₁ % predicted)",
    "<b>D</b>yspnoea (mMRC score)",
    "<b>E</b>xercise capacity (6-minute walk distance)",
])
story.append(spacer(4))
story.append(Paragraph(
    "Persistent hypercapnia after an acute exacerbation is an independent poor prognostic indicator. "
    "Survival in hypercapnic COPD is shorter than in normocapnic COPD.",
    sNote))

story.append(spacer(16))
story.append(rule(C_DARK_BLUE, 1.5))
story.append(Paragraph(
    "Sources: Comprehensive Clinical Nephrology 7th Ed. · Brenner &amp; Rector's The Kidney · "
    "Adams &amp; Victor's Principles of Neurology 12th Ed. · Bradley &amp; Daroff's Neurology · "
    "Fishman's Pulmonary Diseases and Disorders · Robbins &amp; Kumar Basic Pathology · "
    "Katzung's Basic &amp; Clinical Pharmacology 16th Ed. · Costanzo Physiology 7th Ed. · "
    "Murray &amp; Nadel's Textbook of Respiratory Medicine · GOLD Guidelines (goldcopd.org)",
    sSource))

# ── Build ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved to {OUTPUT}")
Running Command

cd /tmp/workspace/medical-notes && python generate_notes_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/medical-notes/Medical_Notes_UE_COPD.pdf

Your PDF is ready. It contains both topics in a single, well-formatted A4 document:

Medical Notes UE COPD

PDF Document · PDF

What's inside:
  • Cover page with title, subtitle, and all source citations
  • Part 1 — Uremic Encephalopathy covering pathophysiology (toxins, BBB disruption, PTH, neurotransmitters, drug accumulation), clinical manifestations table (early vs late), investigations, diagnosis, comparison with hepatic encephalopathy, and treatment
  • Part 2 — COPD covering definition/subtypes, risk factors, pathology (emphysema subtypes, protease-antiprotease imbalance, chronic bronchitis histology), pathophysiology (hyperinflation, V/Q mismatch, gas exchange failure with ABG example), GOLD classification tables, clinical features, complications, full pharmacology table (SABA/SAMA/LABA/LAMA/ICS/roflumilast), non-pharmacological interventions, AECOPD management, and BODE index

common ecg pattern

Reading File
This is a visual + broad topic — ECG patterns. Let me search for ECG sections with images in the library.
Searching sources...
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Good - Tintinalli's Emergency Medicine and Braunwald's Heart Disease have rich ECG content. Let me read the key ECG blocks.
Reading File
Reading File
Finding Sources
Let me read the detailed ECG sections from Tintinalli's and get images from Braunwald's.
Reading File
Reading File
Finding Sources
Now let me get the arrhythmia ECG content from Miller's and Tintinalli's atrial flutter/fibrillation sections, plus fetch key images.
Reading File
Reading File
Finding Sources
Excellent content. Now let me fetch the key ECG images and the heart block ECG images from Washington Manual.
Loading Image
Loading Image
Loading Image
Reading File
Excellent - I have rich content and real ECG images. Let me fetch a few more key images: AV block diagram and torsades.
Loading Image
Loading Image
I have excellent real ECG images and comprehensive textbook content. Now I'll compile the full answer.

Common ECG Patterns

Here is a systematic guide to the most important ECG patterns, with real textbook tracings.

ECG Basics: What Each Wave Represents

Wave/IntervalWhat It RepresentsNormal Value
P waveAtrial depolarization (SA node → AV node)<120 ms, upright in II, inverted in aVR
PR intervalAV conduction time (atria → ventricles)120-200 ms
QRS complexVentricular depolarization<120 ms (narrow)
ST segmentEarly ventricular repolarizationIsoelectric (flat)
T waveVentricular repolarizationUpright in most leads
QT intervalTotal ventricular electrical activityCorrected QTc <440 ms (men), <460 ms (women)

1. Normal Sinus Rhythm

  • Rate: 60-100 bpm
  • P wave before every QRS, upright in lead II, inverted in aVR
  • PR interval 120-200 ms
  • QRS narrow (<120 ms)
  • Regular R-R intervals

2. Atrial Arrhythmias

Atrial Flutter

ECG features:
  • "Sawtooth" flutter waves in inferior leads (II, III, aVF) and V1 — the pathognomonic sign
  • Atrial rate typically 300 bpm (range 250-350 bpm)
  • Ventricular rate depends on AV block ratio:
    • 2:1 block → ventricular rate ~150 bpm
    • 3:1 block → ~100 bpm
  • A regular narrow-complex tachycardia at approximately 150 bpm strongly suggests atrial flutter with 2:1 conduction
  • P waves of a single morphology (organised rhythm, unlike AF)
Atrial flutter — sawtooth flutter waves visible in V1 (arrows)
Atrial flutter. Note the sawtooth flutter wave pattern in lead V1 (arrows). - Miller's Anesthesia, 10th Ed.

Atrial Fibrillation (AF)

ECG features (Tintinalli's Emergency Medicine):
  • Absence of discernible P waves — flat or chaotic isoelectric baseline
  • Irregularly irregular ventricular rhythm (no two R-R intervals the same)
  • QRS complexes narrow (unless pre-existing bundle branch block or pre-excitation)
  • Rate typically 110-160 bpm (uncontrolled)
Clinical causes: ischaemic/valvular heart disease, heart failure, alcohol ("holiday heart"), thyrotoxicosis, myocarditis, blunt chest trauma.
Clinical consequences:
  • Loss of atrial contraction (can precipitate HF)
  • Rapid ventricular rate impairs filling
  • Thromboembolic risk: conversion after >12 hrs carries embolic risk; after >48 hrs requires 3-4 weeks anticoagulation before cardioversion
Atrial fibrillation — irregularly irregular rhythm, no distinct P waves
Atrial fibrillation. Irregularly irregular rhythm with no identifiable P waves. - Miller's Anesthesia, 10th Ed.

3. AV Conduction Blocks (Heart Blocks)

AV block ECG examples A-E: first-degree (A), Mobitz I/Wenckebach (B), Mobitz II (C), 2:1 block (D), complete heart block (E)
AV block examples: A=1st degree, B=Mobitz I (Wenckebach), C=Mobitz II, D=2:1 block, E=3rd degree (complete heart block). - Washington Manual of Medical Therapeutics

First-Degree AV Block

  • PR interval >200 ms (one large box) on every beat
  • Every P wave conducts — no dropped beats
  • Usually benign; can be from vagal tone, inferior MI, digoxin, AV nodal disease

Second-Degree AV Block — Mobitz Type I (Wenckebach)

  • Progressive PR prolongation with successive beats until one P wave is not conducted (dropped QRS)
  • RR intervals shorten before the dropped beat
  • "Group beating" pattern
  • Block usually within the AV node - more benign; progression to complete heart block unlikely

Second-Degree AV Block — Mobitz Type II

  • Constant PR interval (not lengthening) followed by sudden dropped QRS without warning
  • Often associated with bundle branch block (wide QRS)
  • Block below the AV node — more serious; high risk of progression to complete heart block
  • Pacemaker usually required

Third-Degree (Complete) Heart Block

  • Complete AV dissociation — atria and ventricles beat independently
  • More P waves than QRS complexes; P waves "march through" QRS complexes with no relationship
  • Ventricular escape rhythm: narrow if junctional (40-60 bpm), wide if ventricular (20-40 bpm)
  • Emergency: requires temporary/permanent pacing

4. Ischaemia and Infarction

STEMI (ST-Elevation MI)

Diagnostic criteria (Tintinalli's):
  • New ST-segment elevation ≥1 mm in at least two contiguous leads
  • Represents acute transmural myocardial injury requiring emergency reperfusion
Territory localisation (culprit artery mapping):
ECG Leads with ST ElevationInfarct TerritoryCulprit Artery
V1-V4 (anterior)Anterior wallLAD (left anterior descending)
II, III, aVF (inferior)Inferior wallRCA or LCx
I, aVL, V5-V6 (lateral)Lateral wallLCx or diagonal branch of LAD
V1-V2 tall R wave (posterior)Posterior wallRCA or LCx
V4R (right-sided lead)Right ventricleProximal RCA
Key ECG clues:
  • aVR elevation > V1 → suggests left main or proximal LAD occlusion
  • ST elevation in III > II + V1 elevation → proximal RCA with RV infarction
  • Inferior MI with lateral ST elevation (V5/V6 or aVL) → suggests LCx over RCA
  • Reciprocal changes (ST depression in leads opposite to elevation) = larger injury zone, higher mortality

NSTEMI / Ischaemia

  • ST depression ≥0.5-1 mm (subendocardial ischaemia)
  • T-wave inversions (Wellens' syndrome in V2-V3 = critical LAD stenosis)
  • May have normal ECG (5-10% of AMI have normal or near-normal ECG at presentation)

Q Waves (Old/Evolving MI)

  • Pathological Q waves: ≥40 ms wide AND ≥25% of QRS amplitude
  • Indicate completed transmural infarction (necrosis)

5. Ventricular Arrhythmias

Ventricular Tachycardia (VT)

ECG features (Miller's Anesthesia):
  • ≥3 consecutive ectopic beats at rate >100 bpm
  • Wide QRS complex (>120 ms)
  • Regular or near-regular rhythm
  • AV dissociation (P waves unrelated to QRS) - pathognomonic when present
  • Fusion beats and capture beats confirm VT
  • Sustained VT: lasts >30 seconds; Nonsustained: terminates spontaneously within 30 seconds
Ventricular tachycardia — wide complex regular tachycardia
Ventricular tachycardia — broad, regular complexes at >100 bpm. - Miller's Anesthesia, 10th Ed.
Monomorphic VT: one morphology — reentry from scar (ischaemic or dilated cardiomyopathy) Polymorphic VT: changing morphology — acquired long QT, electrolyte disturbances

Torsades de Pointes

  • A form of polymorphic VT associated with prolonged QT interval
  • ECG: QRS complexes "twist" around the isoelectric baseline (literally "twisting of the points")
  • Rate 200-250 bpm
  • May terminate spontaneously or degenerate to VF
  • Causes: drugs (antiarrhythmics, antipsychotics, antibiotics), hypokalaemia, hypomagnesaemia, congenital long QT
Torsades de pointes — twisting polymorphic VT preceded by prolonged QT
Torsades de pointes — note the initiating beats with prolonged QT (V, N, N, N labels), then twisting polymorphic VT. - Miller's Anesthesia, 10th Ed.

Ventricular Fibrillation (VF)

  • Chaotic, irregular wide complex activity — no identifiable QRS, ST, or T waves
  • No cardiac output → cardiac arrest
  • Requires immediate defibrillation

6. Bundle Branch Blocks

Right Bundle Branch Block (RBBB)

  • QRS ≥120 ms
  • RSR' ("rabbit ears") pattern in V1-V2 — terminal R wave
  • Wide S wave in I, V5-V6 (slurred terminal S)
  • Can be normal variant or indicate RV strain, PE, ASD

Left Bundle Branch Block (LBBB)

  • QRS ≥120 ms
  • Broad notched R wave in I, aVL, V5-V6 (M-shaped pattern)
  • No septal Q waves in lateral leads
  • Deep QS in V1
  • New LBBB in the context of chest pain is treated as STEMI-equivalent (Sgarbossa criteria can help identify superimposed STEMI)

7. Pulmonary Embolism — S1Q3T3 Pattern

  • S wave in lead I
  • Q wave in lead III
  • T-wave inversion in lead III
  • Also: right axis deviation, incomplete or complete RBBB, sinus tachycardia (most common), right heart strain (T-wave inversions V1-V4)
  • Neither sensitive nor specific alone — diagnosis requires clinical context + CT pulmonary angiography

8. Electrolyte and Metabolic Patterns

ConditionKey ECG Finding
HyperkalaemiaPeaked T waves → widened QRS → sine wave → VF/asystole
HypokalaemiaFlattened/inverted T waves, prominent U waves, prolonged QU
HypercalcaemiaShort QT interval
HypocalcaemiaProlonged QT interval
Digoxin toxicity"Salvador Dali moustache" (scooped ST depression), bradycardia, AV blocks
HypothermiaOsborn (J) waves — positive deflection at J point, bradycardia
PericarditisDiffuse saddle-shaped ST elevation in all leads except aVR; PR depression

9. Pulmonary Hypertension

  • Most common finding: right axis deviation
  • R/S ratio >1 in V1; R/S ratio <1 in V5 and V6
  • qR complex in V1
  • S1Q3T3 pattern
  • Right atrial enlargement (tall P waves in inferior leads - "P pulmonale")
  • Incomplete or complete RBBB
  • Most common dysrhythmias: atrial fibrillation, atrial flutter, AVNRT
Source: Tintinalli's Emergency Medicine

Quick-Reference Summary Table

PatternRateRhythmP WavesQRSKey Clue
Normal sinus60-100RegularUpright in II, every QRSNarrowBaseline
Atrial flutter75-150 (V rate)RegularSawtooth ~300/minNarrow150 bpm tachycardia
Atrial fibrillationVariableIrregularly irregularAbsent/chaoticNarrowNo two R-R equal
1° AV blockNormalRegularNormalNarrowPR >200 ms
Mobitz INormalRegularly irregularGroup beatingNarrowProgressive PR → dropped beat
Mobitz IINormal/slowRegularly irregularFixed PR then droppedWideSudden dropped beat
Complete heart blockSlow escapeRegular (2 independent)Dissociated from QRSWide/narrow escapeP unrelated to QRS
STEMIVariableVariableVariableST elevatedContiguous leads, reciprocal changes
VT>100RegularDissociated (AV dissoc.)Wide (>120 ms)Fusion/capture beats
Torsades200-250IrregularAbsentWide, twistingLong QT precedes it
RBBBNormalRegularNormalWide: RSR' in V1Terminal R in V1
LBBBNormalRegularNormalWide: broad R I/V6No Q in lateral leads

Sources: Tintinalli's Emergency Medicine · Miller's Anesthesia, 10th Ed. · Washington Manual of Medical Therapeutics · Harrison's Principles of Internal Medicine 22E · Braunwald's Heart Disease

explain me with all basic and neccessary details as i am a new student

Finding Sources
Finding Sources
Good sources found. Let me read the foundational ECG content from Guyton & Hall (best physiology textbook for beginners) and Goldman-Cecil, and fetch the key diagrams.
Reading File
Reading File
Reading File
Excellent foundational content. Now let me fetch the key diagrams and get the lead placement / electrical axis content.
Loading Image
Loading Image
Loading Image
Finding Sources
I have excellent diagrams and foundational content. Let me get the lead placement details and the cardiac conduction system description.
Reading File
Finding Sources
Reading File
Loading Image
Now let me fetch the cardiac conduction system diagram and then compile the full beginner guide.
Loading Image
Loading Image
I now have everything needed - excellent diagrams, conduction system image, wave diagrams, lead placement, and grid explanation. Let me write the complete beginner's guide.

ECG for Beginners — Complete Foundation Guide


PART 1: What Is an ECG and Why Do We Do It?

An Electrocardiogram (ECG or EKG) is a completely painless test that records the electrical activity of the heart over time. Every heartbeat is triggered by an electrical signal. By placing electrodes on the skin, we can "listen" to those electrical signals and display them as waves on paper or a screen.
Why it matters: The ECG can detect:
  • Heart attacks (myocardial infarction)
  • Abnormal heart rhythms (arrhythmias)
  • Blocked electrical pathways (heart blocks)
  • Enlarged heart chambers (hypertrophy)
  • Electrolyte imbalances (potassium, calcium problems)
  • Drug toxicity effects

PART 2: The Heart's Electrical System — What Creates the ECG

Before reading an ECG, you must understand why the waves appear. Every wave on the ECG corresponds to a specific electrical event in the heart.
Cardiac conduction system — SA node to Purkinje fibers showing the pathway of electrical activation
The cardiac conduction system — electrical signal travels from SA node → AV node → Bundle of His → Bundle branches → Purkinje fibers. - Costanzo Physiology, 7th Ed.

The Electrical Pathway — Step by Step

1. SA Node (Sinoatrial Node) — "The Pacemaker"
  • Located in the right atrium (upper right part of the heart)
  • Spontaneously generates an electrical impulse 60-100 times per minute
  • This is the "natural pacemaker" — it sets the heart rate
  • The impulse spreads outward through both atria like a ripple in water
2. AV Node (Atrioventricular Node) — "The Gatekeeper"
  • Located between the atria and ventricles
  • Deliberately slows conduction (conduction velocity here is the slowest of any cardiac tissue)
  • This delay (about 0.1 second) is critical — it gives the ventricles time to fill with blood from the atria before they contract
  • Think of it as a traffic light — it pauses the signal before letting it through
3. Bundle of His → Right & Left Bundle Branches
  • After the AV node, the signal enters the Bundle of His (a specialised cable running down the septum)
  • It splits into the right bundle branch (to right ventricle) and left bundle branch (to left ventricle)
4. Purkinje Fibers — "The Express Network"
  • Fine, branching fibres that spread rapidly throughout both ventricles
  • Conduction velocity here is the fastest in the heart (4 m/s)
  • Ensures both ventricles contract almost simultaneously and efficiently
Costanzo Physiology, 7th Ed.; Goldman-Cecil Medicine

PART 3: Depolarization and Repolarization — The Two Key Concepts

These are the two processes that produce all ECG waves.
Depolarization (upstroke) and repolarization (recovery) shown above, with corresponding ECG waves P, QRS, T below
Top: ventricular action potential (depolarization = contraction trigger; repolarization = recovery). Bottom: corresponding ECG waves. - Guyton & Hall Textbook of Medical Physiology
Depolarization = The cell becomes electrically excited. Sodium ions rush into the cell, reversing the charge. This triggers muscle contraction.
Repolarization = The cell returns to its resting state (potassium flows out). The muscle relaxes. This must happen before the next beat.
Simple rule:
  • Depolarization → contraction → appears as an upward wave on ECG (if moving toward the electrode)
  • Repolarization → relaxation → appears as T wave

PART 4: The ECG Paper — How to Read the Grid

Before reading any wave, understand the paper:
ECG grid showing small and large boxes with time (horizontal) and voltage (vertical) measurements, plus all intervals labeled
Standard ECG paper grid with all measurements. Small box = 1 mm = 0.04 sec. Large box = 5 mm = 0.2 sec. - Goldman-Cecil Medicine
AxisWhat It MeasuresSmall Box (1 mm)Large Box (5 mm)
Horizontal (X-axis)Time0.04 seconds (40 ms)0.20 seconds (200 ms)
Vertical (Y-axis)Voltage (amplitude)0.1 mV0.5 mV
Standard recording speed = 25 mm/second
So if you see a wave that spans 5 small boxes wide, it took 5 × 0.04 = 0.20 seconds to occur.

PART 5: The ECG Waves — Each One Explained

Normal ECG showing two complete cardiac cycles with all waves (P, Q, R, S, T) and all intervals (PR, QRS, ST, QT, RR) labeled with normal values
Normal ECG with all waves and intervals labeled. PR interval = 0.16 sec; QRS interval <0.12 sec. - Guyton & Hall Medical Physiology
Labeled ECG diagram showing P wave, PR interval, QRS complex (Q, R, S), ST segment, T wave, QT interval, and J point
ECG from lead II showing all key components. - Costanzo Physiology, 7th Ed.

P Wave

  • What it is: Atrial depolarization — the SA node fires and the electrical wave spreads through both atria
  • What it means physically: The atria are contracting, pushing blood into the ventricles
  • Normal: Small, rounded, upright in lead II; duration <120 ms (3 small boxes)
  • Abnormal: Wide P wave = atrial enlargement or delayed conduction; absent P wave = atrial fibrillation

PR Interval

  • What it is: Time from the start of the P wave to the start of the QRS complex
  • What it measures: Total conduction time through the atria + the AV node
  • The flat "PR segment" (between P wave end and QRS start) = the AV node delay
  • Normal: 120-200 ms (3-5 small boxes)
  • Short PR (<120 ms) = pre-excitation (e.g., Wolff-Parkinson-White syndrome)
  • Long PR (>200 ms) = first-degree heart block (AV node is conducting slowly)

QRS Complex

  • What it is: Ventricular depolarization — the large muscle of both ventricles activates
  • What it means physically: The ventricles contract and pump blood to the lungs (right) and body (left)
  • Made of three waves:
    • Q wave = small downward deflection (first negative wave)
    • R wave = the tall upward spike (most prominent feature)
    • S wave = downward deflection after the R
  • Normal: <120 ms wide (3 small boxes)
  • Wide QRS (≥120 ms) = bundle branch block or ventricular origin beat
  • Pathological Q waves (wide + deep) = old heart attack (scar tissue)
Why is QRS narrow even though ventricles are large? Because the His-Purkinje system conducts extremely fast — it distributes the impulse to all parts of the ventricles almost simultaneously. Costanzo Physiology

ST Segment

  • What it is: The flat line between the end of QRS (J point) and the start of the T wave
  • What it means: The entire ventricle is depolarized (uniformly excited) — no current flows between regions so the line is flat
  • Normal: Flat (isoelectric)
  • ST Elevation = acute transmural injury (heart attack — STEMI, pericarditis)
  • ST Depression = subendocardial ischaemia, digoxin effect

T Wave

  • What it is: Ventricular repolarization — the ventricles are resetting electrically
  • What it means physically: The ventricles are relaxing
  • Normal: Rounded, upright in most leads (inverted in aVR normally)
  • Peaked T waves = hyperkalaemia
  • Inverted T waves = ischaemia, ventricular hypertrophy, bundle branch block

QT Interval

  • What it is: From start of QRS to end of T wave
  • What it measures: The total time for ventricular depolarization + repolarization (the entire electrical cycle of the ventricle)
  • Normal: Corrected QTc <440 ms (men), <460 ms (women)
  • Prolonged QT = risk of dangerous arrhythmia (Torsades de Pointes)
  • Causes: drugs (some antibiotics, antipsychotics), electrolyte imbalances (low K⁺, Mg²⁺, Ca²⁺)

U Wave

  • Small, positive wave after the T wave (not always visible)
  • Represents repolarisation of the Purkinje fibres or papillary muscles
  • Prominent U waves = hypokalaemia, bradycardia

RR Interval

  • Distance between two consecutive R waves
  • Used to calculate heart rate: Heart Rate = 300 ÷ number of large boxes between R waves
    • e.g., 1 large box apart = 300 bpm; 5 large boxes apart = 60 bpm (normal)

PART 6: The 12 Leads — Different Camera Angles of the Heart

A standard ECG has 12 leads. Think of each lead as a camera looking at the heart from a different angle. No electrodes are placed in 12 places — only 10 electrodes are used, but they are combined mathematically to give 12 different views.

The 10 Electrode Positions

4 Limb Electrodes:
  • Right Arm (RA)
  • Left Arm (LA)
  • Right Leg (RL) — this is the ground/reference electrode only
  • Left Leg (LL)
6 Chest (Precordial) Electrodes:
Chest electrode placement showing V1-V6 positions on the chest wall with sternal angle and fourth intercostal space labeled
Precordial electrode placement V1-V6. Start at sternal angle → 4th intercostal space for V1/V2. - Roberts & Hedges' Clinical Procedures in Emergency Medicine
LeadPosition
V1Right sternal border, 4th intercostal space
V2Left sternal border, 4th intercostal space
V3Midway between V2 and V4
V4Left midclavicular line, 5th intercostal space
V5Left anterior axillary line, same horizontal level as V4
V6Left midaxillary line, same horizontal level as V4
Tip to find 4th intercostal space: Feel the sternal angle (the bony ridge on the sternum, ~5 cm from the notch at the top). Just below it is the 2nd rib → count down two more spaces → 4th intercostal space.

The 12 Leads and What Part of the Heart They "See"

Frontal (Limb) Leads — derived from the 4 limb electrodes:
LeadViewPart of Heart Seen
ILeft (0°)Lateral wall
IIInferior-left (60°)Inferior wall — best for P waves
IIIInferior-right (120°)Inferior wall
aVRRight arm (−150°)Cavity/right side — normally negative
aVLLeft arm (−30°)Lateral wall
aVFFeet/inferior (90°)Inferior wall
Horizontal (Precordial) Leads — from chest electrodes:
LeadPart of Heart Seen
V1-V2Right ventricle + anterior septum
V3-V4Anterior wall (left ventricle, LAD territory)
V5-V6Lateral wall (left ventricle)
Memory tip for the territory of the heart by lead groups:
  • Inferior: II, III, aVF
  • Anterior: V1-V4
  • Lateral: I, aVL, V5-V6
  • Right ventricle: V1, V3R, V4R (special right-sided leads)

PART 7: How to Calculate Heart Rate

Method 1 — The 300 Rule (quick, for regular rhythms): Count the number of large boxes between two R waves, then divide 300 by that number.
Large boxes between R wavesHeart Rate
1300 bpm
2150 bpm
3100 bpm
475 bpm
560 bpm
650 bpm
Mnemonic: 300 → 150 → 100 → 75 → 60 → 50
Method 2 — Count QRS complexes: Count all QRS complexes in a 10-second strip, then multiply by 6.
Normal rate: 60-100 bpm
  • <60 = Bradycardia (slow heart rate)
  • 100 = Tachycardia (fast heart rate)

PART 8: Systematic Approach to Reading Any ECG

As a student, always read an ECG in the same order every time. Never skip steps.

The 7-Step Systematic Approach

Step 1 — Rate
  • Count using the 300 rule or QRS counting method
  • Normal: 60-100 bpm; Slow (<60) = bradycardia; Fast (>100) = tachycardia
Step 2 — Rhythm
  • Is it regular? (All R-R intervals equal?)
  • Is it irregular? If so, is it regularly irregular (a pattern) or irregularly irregular (totally random)?
  • Irregularly irregular = almost always atrial fibrillation
Step 3 — P Waves
  • Are P waves present?
  • Is there one P wave before every QRS?
  • Are they upright in lead II?
  • If yes to all → origin is the SA node (sinus rhythm)
Step 4 — PR Interval
  • Measure from start of P to start of QRS
  • Normal: 120-200 ms (3-5 small boxes)
  • Short → WPW; Long → 1st degree block; Missing (P not followed by QRS) → 2nd or 3rd degree block
Step 5 — QRS Complex
  • Is it narrow (<3 small boxes / <120 ms)?
  • Narrow = normal conduction through His-Purkinje
  • Wide (≥120 ms) = bundle branch block, or beat originating from the ventricle itself
Step 6 — ST Segment and T Waves
  • Is the ST segment flat (isoelectric)?
  • Any elevation? (STEMI, pericarditis)
  • Any depression? (Ischaemia, NSTEMI)
  • Are T waves upright, inverted, or peaked?
Step 7 — QT Interval
  • Measure from start of QRS to end of T wave
  • Correct for heart rate (QTc)
  • Prolonged = danger of arrhythmia (Torsades)

PART 9: Quick Summary of Normal Values

ParameterNormal ValueWhat Happens If Abnormal
Heart rate60-100 bpm<60 = bradycardia; >100 = tachycardia
P wave duration<120 msWide = atrial enlargement
P wave axisUpright in II, inverted in aVROtherwise = ectopic origin
PR interval120-200 msLong = AV block; Short = pre-excitation
QRS duration<120 msWide = BBB or ventricular beat
ST segmentIsoelectric (flat)Elevated = injury; Depressed = ischaemia
T waveUpright in most leadsInverted = ischaemia; Peaked = hyperkalaemia
QTc<440 ms (M), <460 ms (F)Prolonged = risk of Torsades

PART 10: One-Line Summary of Each Wave

Think of the ECG as telling a story from top to bottom of the heart:
SA node fires  →  P wave       (atria depolarize → atria contract)
         ↓
AV node delay  →  PR segment   (flat line = waiting at the "gate")
         ↓
Ventricles fire →  QRS complex  (ventricles depolarize → ventricles contract)
         ↓
Ventricles rest →  ST segment   (flat — whole ventricle still depolarized)
         ↓
Ventricles recover → T wave     (ventricles repolarize → ventricles relax)

Sources: Guyton & Hall Textbook of Medical Physiology · Costanzo Physiology, 7th Ed. · Goldman-Cecil Medicine · Roberts & Hedges' Clinical Procedures in Emergency Medicine · Katzung's Basic & Clinical Pharmacology, 16th Ed.

give me also this in a pdf

Running Command

ls /tmp/workspace/medical-notes/ && python3 -c "import requests; print('requests ok')" && python3 -c "from reportlab.platypus import Image; print('reportlab ok')"

Writing File

~/medical-notes/generate_ecg_pdf.py

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

OUTPUT = "/tmp/workspace/medical-notes/ECG_Beginner_Guide.pdf"
IMG_DIR = "/tmp/workspace/medical-notes/ecg_imgs"
os.makedirs(IMG_DIR, exist_ok=True)

# ── Palette ──────────────────────────────────────────────────────────────────
C_NAVY       = colors.HexColor("#1a3a5c")
C_BLUE       = colors.HexColor("#2c6fad")
C_LIGHT_BLUE = colors.HexColor("#d6e8f8")
C_TEAL       = colors.HexColor("#1a7a6e")
C_LIGHT_TEAL = colors.HexColor("#d0efec")
C_ORANGE     = colors.HexColor("#c75b1e")
C_LIGHT_ORG  = colors.HexColor("#fde8da")
C_TBL_HDR    = colors.HexColor("#2c6fad")
C_TBL_ALT    = colors.HexColor("#eef5fb")
C_BOX_BG     = colors.HexColor("#fffbea")
C_BOX_BORDER = colors.HexColor("#e0a800")
C_TIP_BG     = colors.HexColor("#e8f5e9")
C_TIP_BORDER = colors.HexColor("#388e3c")

W = A4[0] - 4*cm

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

def ms(name, parent="Normal", **kw):
    s = ParagraphStyle(name, parent=styles[parent])
    for k, v in kw.items(): setattr(s, k, v)
    return s

sTitle    = ms("sTitle",  fontName="Helvetica-Bold",   fontSize=24, textColor=C_NAVY, alignment=TA_CENTER, spaceAfter=4)
sSub      = ms("sSub",    fontName="Helvetica",        fontSize=12, textColor=C_BLUE, alignment=TA_CENTER, spaceAfter=10)
sBanner   = ms("sBanner", fontName="Helvetica-Bold",   fontSize=16, textColor=colors.white, leading=22, spaceBefore=2, spaceAfter=2)
sH1       = ms("sH1",     fontName="Helvetica-Bold",   fontSize=13, textColor=C_NAVY,  spaceBefore=10, spaceAfter=3, leading=17)
sH2       = ms("sH2",     fontName="Helvetica-Bold",   fontSize=11, textColor=C_BLUE,  spaceBefore=7,  spaceAfter=3, leading=15)
sBody     = ms("sBody",   fontName="Helvetica",        fontSize=9.5, leading=14, spaceAfter=4, alignment=TA_JUSTIFY)
sBullet   = ms("sBullet", fontName="Helvetica",        fontSize=9.5, leading=13, spaceAfter=2, leftIndent=14, firstLineIndent=-10)
sCaption  = ms("sCap",    fontName="Helvetica-Oblique",fontSize=8.5, textColor=colors.HexColor("#444"), leading=12, spaceAfter=6, alignment=TA_CENTER)
sNote     = ms("sNote",   fontName="Helvetica-Oblique",fontSize=9,   textColor=colors.HexColor("#555"), leading=13, spaceAfter=4)
sCode     = ms("sCode",   fontName="Courier",          fontSize=9,   leading=13, spaceAfter=4, leftIndent=10)
sSource   = ms("sSource", fontName="Helvetica-Oblique",fontSize=8,   textColor=colors.HexColor("#555"), leading=12, spaceAfter=2)
sTblHdr   = ms("sTblHdr", fontName="Helvetica-Bold",   fontSize=9,   textColor=colors.white, alignment=TA_CENTER, leading=12)
sTblCell  = ms("sTblCell",fontName="Helvetica",        fontSize=9,   leading=12)
sTblCellC = ms("sTblCC",  fontName="Helvetica",        fontSize=9,   leading=12, alignment=TA_CENTER)

# ── Helpers ───────────────────────────────────────────────────────────────────
def rule(c=C_BLUE, t=1.0): return HRFlowable(width="100%", thickness=t, color=c, spaceAfter=6, spaceBefore=2)
def sp(h=6): return Spacer(1, h)

def banner(text, color=C_NAVY):
    t = Table([[Paragraph(text, sBanner)]], colWidths=[W])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,-1), color),
        ("LEFTPADDING",   (0,0),(-1,-1), 12),
        ("RIGHTPADDING",  (0,0),(-1,-1), 12),
        ("TOPPADDING",    (0,0),(-1,-1), 8),
        ("BOTTOMPADDING", (0,0),(-1,-1), 8),
    ]))
    return t

def h1(txt): return [sp(4), Paragraph(txt, sH1), rule(C_BLUE, 0.8)]
def h2(txt): return [Paragraph(txt, sH2)]
def body(txt): return Paragraph(txt, sBody)

def bullets(items):
    return [Paragraph(f"• {it}", sBullet) for it in items]

def tip_box(label, text, bg=C_BOX_BG, border=C_BOX_BORDER):
    inner = Table([[Paragraph(f"<b>{label}</b>", sTblCell)],
                   [Paragraph(text, sTblCell)]], colWidths=[W-20])
    inner.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,-1), bg),
        ("BOX",           (0,0),(-1,-1), 1.2, border),
        ("LEFTPADDING",   (0,0),(-1,-1), 10),
        ("RIGHTPADDING",  (0,0),(-1,-1), 10),
        ("TOPPADDING",    (0,0),(-1,-1), 6),
        ("BOTTOMPADDING", (0,0),(-1,-1), 6),
    ]))
    return inner

def make_table(headers, rows, col_widths=None, alt=True):
    data = [[Paragraph(h, sTblHdr) for h in headers]]
    for row in rows:
        data.append([Paragraph(str(c), sTblCell) for c in row])
    if not col_widths:
        col_widths = [W/len(headers)]*len(headers)
    t = Table(data, colWidths=col_widths, repeatRows=1)
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0),  C_TBL_HDR),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), ([colors.white, C_TBL_ALT] if alt else [colors.white])),
        ("GRID",          (0,0),(-1,-1), 0.4, colors.HexColor("#bbbbbb")),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
        ("LEFTPADDING",   (0,0),(-1,-1), 6),
        ("RIGHTPADDING",  (0,0),(-1,-1), 6),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
    ]))
    return t

# ── Image downloader ─────────────────────────────────────────────────────────
def dl_img(url, fname):
    path = os.path.join(IMG_DIR, fname)
    if not os.path.exists(path):
        r = requests.get(url, timeout=20)
        with open(path,"wb") as f: f.write(r.content)
    return path

def rl_img(url, fname, width=None, caption=None):
    """Return [Image, caption_para] or [] on failure."""
    try:
        path = dl_img(url, fname)
        w = width or (W - 1*cm)
        img = Image(path, width=w, kind='proportional')
        items = [img]
        if caption:
            items.append(Paragraph(caption, sCaption))
        return items
    except Exception as e:
        print(f"  img failed {fname}: {e}")
        return [Paragraph(f"[Image: {caption or fname}]", sCaption)]

# ── Download all images ───────────────────────────────────────────────────────
IMGS = {
    "conduction.png":  "https://cdn.orris.care/cdss_images/030588aeee4867ca308e5f1a0fcc6940480805730b60fd0ddf1014b5c2254def.png",
    "depol_repol.png": "https://cdn.orris.care/cdss_images/3ff4ade6e91f416f4524029de46348fb5a7f4028e8eeb50fbec86abab89ca495.png",
    "normal_ecg.png":  "https://cdn.orris.care/cdss_images/68a6c0397e45eefcc080b0f11d262dc072c272ed0d5af899d58637b80a828f29.png",
    "ecg_grid.png":    "https://cdn.orris.care/cdss_images/ef815eeb06c673b405e3c7f9112d1e9ff6fbea96a00a2723b233d384156386bd.png",
    "waves_diagram.png":"https://cdn.orris.care/cdss_images/042124084c74430362fb12de1758340e2dd3b129abd476a16698a7fda88e0376.png",
    "leads_placement.png":"https://cdn.orris.care/cdss_images/34b5cf1bc5d662ff1987fcfcf9b03809ef79a5df151f04aef5c6801e52912fa4.png",
    "af.png":          "https://cdn.orris.care/cdss_images/a689a14cc2a98bf071158972c8f1347d8ea29e130b73423f1c5e4b08b55013e3.png",
    "aflutter.png":    "https://cdn.orris.care/cdss_images/f88a5b8505299d45830bb8150a7f9b0883e3b58f7dc8f674472c6cbf759d1bb7.png",
    "vt.png":          "https://cdn.orris.care/cdss_images/c0d1a542a338c6ef89618bdb32851c880180b009a3e5a183ba0a4c6d0ee4a4ae.png",
    "torsades.png":    "https://cdn.orris.care/cdss_images/30c4930e3e293fec6b7deb34cb1b92926ade8033cb34b8e94bda927c4149eb9a.png",
    "av_blocks.png":   "https://cdn.orris.care/cdss_images/a77f39e9879dd484b3b4417e45932db78c25cf99328cac41ff8f2f9c3937b4b3.png",
}
print("Downloading images...")
for fname, url in IMGS.items():
    try:
        dl_img(url, fname)
        print(f"  OK: {fname}")
    except Exception as e:
        print(f"  FAIL: {fname} — {e}")

# ════════════════════════════════════════════════════════════════════════════
# BUILD STORY
# ════════════════════════════════════════════════════════════════════════════
doc = SimpleDocTemplate(OUTPUT, pagesize=A4,
    leftMargin=2*cm, rightMargin=2*cm, topMargin=2.2*cm, bottomMargin=2.2*cm,
    title="ECG for Beginners — Complete Foundation Guide",
    author="Orris Medical Assistant")

story = []

# ── Cover ─────────────────────────────────────────────────────────────────────
story.append(sp(3*cm))
story.append(Paragraph("ECG for Beginners", sTitle))
story.append(Paragraph("Complete Foundation Guide — Waves, Intervals, Leads & Patterns", sSub))
story.append(sp(0.4*cm))
story.append(rule(C_NAVY, 2))
story.append(sp(0.3*cm))
story.append(Paragraph(
    "Sources: Guyton &amp; Hall Medical Physiology · Costanzo Physiology 7th Ed. · "
    "Goldman-Cecil Medicine · Roberts &amp; Hedges' Clinical Procedures · "
    "Katzung's Pharmacology 16th Ed. · Tintinalli's Emergency Medicine · "
    "Miller's Anesthesia 10th Ed. · Washington Manual of Medical Therapeutics",
    sSource))
story.append(PageBreak())

# ════════════════════════════════════════════════════════════════════════════
# PART 1: WHAT IS AN ECG
# ════════════════════════════════════════════════════════════════════════════
story.append(banner("PART 1 — What Is an ECG and Why Do We Do It?", C_NAVY))
story.append(sp(8))
story.append(body(
    "An <b>Electrocardiogram (ECG or EKG)</b> is a completely painless test that records the "
    "<b>electrical activity of the heart</b> over time. Every heartbeat is triggered by an "
    "electrical signal. By placing small sticky electrodes on the skin, we can 'listen' to "
    "those signals and display them as waves on paper or a screen. "
    "No electricity enters the body — the machine only reads signals coming out."
))
story.append(sp(4))
story.append(body("<b>The ECG can detect:</b>"))
story += bullets([
    "Heart attacks (myocardial infarction — ST elevation, Q waves)",
    "Abnormal heart rhythms (arrhythmias — atrial fibrillation, VT, heart block)",
    "Blocked electrical pathways (bundle branch blocks, AV blocks)",
    "Enlarged heart chambers (ventricular hypertrophy)",
    "Electrolyte imbalances (potassium, calcium, magnesium problems)",
    "Drug toxicity effects (digoxin, prolonged QT from medications)",
])
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 2: CONDUCTION SYSTEM
# ════════════════════════════════════════════════════════════════════════════
story.append(banner("PART 2 — The Heart's Electrical System", C_TEAL))
story.append(sp(8))
story.append(body(
    "Before reading an ECG, you must understand <b>why</b> the waves appear. "
    "Every wave corresponds to a specific electrical event in the heart. "
    "The heart has its own built-in electrical wiring — the <b>cardiac conduction system</b>."
))
story.append(sp(6))
story += rl_img("conduction.png", "conduction.png", width=W-2*cm,
    caption="The cardiac conduction system — SA node (pacemaker) → AV node → Bundle of His → Bundle branches → Purkinje fibers.\n(Costanzo Physiology, 7th Ed.)")
story.append(sp(8))

story += h1("The Electrical Pathway — Step by Step")

pathway = [
    ["Step", "Structure", "Function", "Speed"],
    ["1", "SA Node\n(Sinoatrial)", "Natural pacemaker. Fires spontaneously 60–100x/min.\nSpreads impulse through both atria.", "Slowest to start\n~0.05 m/s"],
    ["2", "AV Node\n(Atrioventricular)", "Deliberate DELAY of 0.1 second.\nGives ventricles time to fill with blood.\nThink of it as a traffic light.", "Slowest node\n~0.05 m/s"],
    ["3", "Bundle of His", "Conducts impulse from AV node down\nthe interventricular septum.", "~1 m/s"],
    ["4", "Bundle Branches\n(Left + Right)", "Left branch → left ventricle\nRight branch → right ventricle", "~2 m/s"],
    ["5", "Purkinje Fibers", "Fine network spreading impulse\nthroughout all of both ventricles.\nFastest conduction — ensures simultaneous contraction.", "~4 m/s\n(fastest)"],
]
story.append(make_table(pathway[0], pathway[1:], col_widths=[1.2*cm, 3.5*cm, 8.3*cm, 3.5*cm]))
story.append(sp(6))
story.append(tip_box("Key Concept",
    "The AV node delay is protective — it ensures atria finish contracting and filling the ventricles "
    "BEFORE the ventricles contract. If the AV node conducts too fast, cardiac output drops.",
    C_TIP_BG, C_TIP_BORDER))
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 3: DEPOLARIZATION & REPOLARIZATION
# ════════════════════════════════════════════════════════════════════════════
story.append(banner("PART 3 — Depolarization and Repolarization", C_ORANGE))
story.append(sp(8))
story.append(body(
    "These are the two fundamental processes that produce ALL ECG waves. "
    "Understanding them makes every wave logical, not memorised."
))
story.append(sp(6))
story += rl_img("depol_repol.png", "depol_repol.png", width=W-1*cm,
    caption="Top: ventricular action potential — depolarization (upstroke) triggers contraction; repolarization (return) = relaxation.\n"
            "Bottom: corresponding ECG waves P, QRS (depolarization), T (repolarization). (Guyton & Hall Medical Physiology)")
story.append(sp(6))

story.append(make_table(
    ["Process", "What Happens at Cell Level", "What Triggers", "ECG Appearance"],
    [
        ["Depolarization", "Na⁺ rushes INTO the cell → membrane charge reverses from negative to positive", "Muscle CONTRACTION", "P wave (atria), QRS complex (ventricles)"],
        ["Repolarization", "K⁺ flows OUT → membrane returns to negative resting state", "Muscle RELAXATION", "T wave (ventricles)\n(Atrial repolarization buried inside QRS)"],
    ],
    col_widths=[3.5*cm, 5.5*cm, 4*cm, 4.5*cm]
))
story.append(sp(6))
story.append(tip_box("Simple Rule",
    "Depolarization = contraction → upward deflection on ECG (if wave moves toward the electrode).\n"
    "Repolarization = relaxation → T wave. No current when heart is fully depolarized or fully repolarized → flat line (ST segment).",
    C_BOX_BG, C_BOX_BORDER))
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 4: THE ECG PAPER & GRID
# ════════════════════════════════════════════════════════════════════════════
story.append(banner("PART 4 — The ECG Paper and Grid", C_NAVY))
story.append(sp(8))
story.append(body(
    "Before reading any wave, you must understand the paper. "
    "The ECG grid has two axes: the <b>horizontal axis measures TIME</b> and "
    "the <b>vertical axis measures VOLTAGE (amplitude)</b>."
))
story.append(sp(6))
story += rl_img("ecg_grid.png", "ecg_grid.png", width=W-1*cm,
    caption="Standard ECG paper. Horizontal: 1 small box = 0.04 sec; 1 large box = 0.2 sec.\n"
            "Vertical: 1 small box = 0.1 mV; 1 large box = 0.5 mV. (Goldman-Cecil Medicine)")
story.append(sp(6))

story.append(make_table(
    ["Axis", "What It Measures", "Small Box (1 mm)", "Large Box (5 mm)"],
    [
        ["Horizontal (X-axis)", "TIME", "0.04 seconds (40 ms)", "0.20 seconds (200 ms)"],
        ["Vertical (Y-axis)", "VOLTAGE (Amplitude)", "0.1 mV", "0.5 mV"],
    ],
    col_widths=[4*cm, 4*cm, 5*cm, 4.5*cm]
))
story.append(sp(4))
story.append(Paragraph(
    "<b>Standard recording speed = 25 mm/second</b> — this is the same worldwide so measurements are universal.",
    sNote))
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 5: WAVES AND INTERVALS
# ════════════════════════════════════════════════════════════════════════════
story.append(banner("PART 5 — The ECG Waves and Intervals Explained", C_TEAL))
story.append(sp(8))
story += rl_img("normal_ecg.png", "normal_ecg.png", width=W,
    caption="Normal ECG showing two complete cardiac cycles — P wave, Q, R, S, T, and all intervals labeled.\n"
            "PR interval = 0.16 sec; QRS < 0.12 sec; RR interval shows heart rate. (Guyton & Hall Medical Physiology)")
story.append(sp(6))
story += rl_img("waves_diagram.png", "waves_diagram.png", width=W-2*cm,
    caption="ECG components from lead II: P wave, PR interval, QRS complex, ST segment, T wave, QT interval, J point. (Costanzo Physiology, 7th Ed.)")
story.append(sp(8))

story += h1("Each Wave — What It Is and What It Means")

story += h2("P Wave")
story += bullets([
    "<b>Electrical event:</b> Atrial depolarization (SA node fires → impulse spreads through both atria)",
    "<b>Physical event:</b> Atria contract, pushing blood into ventricles (atrial kick)",
    "<b>Normal appearance:</b> Small, rounded, upright in lead II; duration &lt;120 ms (3 small boxes)",
    "<b>Abnormal:</b> Wide P = atrial enlargement; Absent P = atrial fibrillation or junctional rhythm; Inverted P in II = ectopic atrial origin",
])
story.append(sp(6))

story += h2("PR Interval")
story += bullets([
    "<b>Measured from:</b> Start of P wave → Start of QRS complex",
    "<b>Represents:</b> Total conduction time through atria + AV node + His bundle (the 'AV node delay' is the flat PR segment)",
    "<b>Normal: 120–200 ms (3–5 small boxes)</b>",
    "<b>Short PR (&lt;120 ms):</b> Pre-excitation syndrome (e.g., Wolff-Parkinson-White — a bypass tract bypasses the AV node)",
    "<b>Long PR (&gt;200 ms):</b> First-degree heart block (AV node conducts slowly)",
    "Sympathetic stimulation shortens PR; parasympathetic (vagal) stimulation lengthens it",
])
story.append(sp(6))

story += h2("QRS Complex")
story += bullets([
    "<b>Electrical event:</b> Ventricular depolarization — both ventricles activate via the His-Purkinje system",
    "<b>Physical event:</b> Ventricles contract powerfully, pumping blood to lungs (right) and body (left)",
    "<b>Q wave:</b> First negative (downward) deflection — small initial septal activation",
    "<b>R wave:</b> Tall upward spike — main ventricular activation wave",
    "<b>S wave:</b> Downward deflection after R — terminal forces moving away from the electrode",
    "<b>Normal QRS duration: &lt;120 ms (3 small boxes)</b>",
    "<b>Wide QRS (≥120 ms):</b> Bundle branch block (signal not using the fast Purkinje system) OR ventricular ectopic beat",
    "<b>Pathological Q waves (wide &gt;40 ms AND deep &gt;25% QRS height):</b> Completed heart attack (scar tissue cannot depolarize)",
])
story.append(sp(4))
story.append(tip_box("Why is QRS narrow despite large ventricular mass?",
    "The His-Purkinje system conducts at ~4 m/s — it distributes the impulse to ALL parts of both ventricles "
    "almost simultaneously. Compare this to the AV node (0.05 m/s) — 80x slower! "
    "Fast, simultaneous activation = narrow, efficient QRS. (Costanzo Physiology)"))
story.append(sp(6))

story += h2("ST Segment")
story += bullets([
    "<b>What it is:</b> Flat line between end of QRS (J point) and start of T wave",
    "<b>Why it's flat:</b> The entire ventricle is uniformly depolarized — no current flows between regions → no deflection",
    "<b>Normal: Isoelectric (flat — at the baseline)</b>",
    "<b>ST Elevation:</b> Acute transmural (full-thickness) injury → STEMI (heart attack), pericarditis, Brugada syndrome",
    "<b>ST Depression:</b> Subendocardial ischaemia (inner layer starved of oxygen) → NSTEMI, digoxin effect",
    "The J point is the exact junction of QRS end and ST start",
])
story.append(sp(6))

story += h2("T Wave")
story += bullets([
    "<b>Electrical event:</b> Ventricular repolarization — ventricles reset electrically",
    "<b>Physical event:</b> Ventricles relax (diastole begins)",
    "<b>Normal:</b> Rounded, upright in most leads; inverted in aVR normally",
    "<b>Peaked (tall, narrow) T waves:</b> Hyperkalaemia (high potassium) — first sign",
    "<b>Inverted T waves:</b> Ischaemia, ventricular hypertrophy, bundle branch block, pulmonary embolism",
    "<b>Atrial repolarization:</b> Occurs during this time too but is hidden inside the QRS complex (too small to see)",
])
story.append(sp(6))

story += h2("QT Interval")
story += bullets([
    "<b>Measured from:</b> Start of QRS → End of T wave",
    "<b>Represents:</b> Total ventricular electrical activity (depolarization + repolarization)",
    "<b>Must be corrected for heart rate</b> (faster heart rate = shorter QT naturally) → QTc",
    "<b>Normal QTc: &lt;440 ms (men), &lt;460 ms (women)</b>",
    "<b>Prolonged QTc:</b> Risk of fatal arrhythmia (Torsades de Pointes). Causes: drugs (antiarrhythmics, antipsychotics, some antibiotics), low K⁺/Mg²⁺/Ca²⁺, congenital long QT syndrome",
    "<b>Short QTc:</b> Hypercalcaemia",
])
story.append(sp(6))

story += h2("U Wave")
story += bullets([
    "Small, positive wave after the T wave (not always visible)",
    "Thought to represent repolarization of Purkinje fibers or papillary muscles",
    "<b>Prominent U waves = hypokalaemia</b> (low potassium) or bradycardia",
])
story.append(sp(6))

story += h2("RR Interval")
story += bullets([
    "Distance between two consecutive R wave peaks",
    "Used to calculate heart rate: <b>Heart Rate = 1 / (RR interval in seconds)</b>",
    "Or use the quick 300 Rule (explained in Part 7)",
])
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 6: THE 12 LEADS
# ════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(banner("PART 6 — The 12 Leads: Different Camera Angles of the Heart", C_ORANGE))
story.append(sp(8))
story.append(body(
    "A standard ECG uses <b>12 leads</b>, but only <b>10 physical electrodes</b> are placed. "
    "Each lead looks at the heart from a different angle — like cameras surrounding the heart. "
    "The 12 views are mathematically derived from the 10 electrode signals."
))
story.append(sp(6))

story += h1("Chest (Precordial) Electrode Placement — V1 to V6")
story += rl_img("leads_placement.png", "leads_placement.png", width=W-1*cm,
    caption="Precordial electrode placement V1–V6. Start at the sternal angle to find the 4th intercostal space.\n"
            "(Roberts & Hedges' Clinical Procedures in Emergency Medicine)")
story.append(sp(6))

story.append(make_table(
    ["Lead", "Exact Position"],
    [
        ["V1", "Right sternal border, 4th intercostal space"],
        ["V2", "Left sternal border, 4th intercostal space"],
        ["V3", "Midway between V2 and V4"],
        ["V4", "Left midclavicular line, 5th intercostal space"],
        ["V5", "Left anterior axillary line, same horizontal level as V4"],
        ["V6", "Left midaxillary line, same horizontal level as V4 and V5"],
    ],
    col_widths=[2.5*cm, 15*cm]
))
story.append(sp(4))
story.append(tip_box("How to find the 4th intercostal space",
    "Feel the sternal angle (the bony ridge on the breastbone, about 5 cm below the top notch). "
    "Just lateral to it is the 2nd rib. Count downward: 2nd rib → 2nd space → 3rd rib → 3rd space → 4th rib → 4th space. "
    "V1 and V2 go here. V4–V6 are at the same horizontal level (NOT all in the 5th intercostal space)."))
story.append(sp(8))

story += h1("What Each Lead Group 'Sees'")
story.append(make_table(
    ["Lead Group", "Leads Included", "Wall of Heart Viewed", "Artery at Risk"],
    [
        ["Inferior", "II, III, aVF", "Inferior (bottom) wall of LV", "Right coronary artery (RCA) or LCx"],
        ["Anterior", "V1, V2, V3, V4", "Anterior (front) wall of LV + septum", "Left anterior descending (LAD)"],
        ["Lateral", "I, aVL, V5, V6", "Lateral (side) wall of LV", "Left circumflex (LCx) or diagonal branch of LAD"],
        ["Septal", "V1, V2", "Interventricular septum", "LAD (septal branches)"],
        ["Right Ventricle", "V1, V3R, V4R (special right-sided leads)", "Right ventricular wall", "Proximal RCA"],
    ],
    col_widths=[2.8*cm, 4*cm, 5.2*cm, 5.5*cm]
))
story.append(sp(6))

story += h1("The Limb Leads")
story.append(make_table(
    ["Lead", "View (Angle)", "Normal Appearance"],
    [
        ["I",   "Lateral (0°)",        "Upright P, R, T"],
        ["II",  "Inferior-left (60°)", "Best lead for P waves; upright P, R, T — most used for rhythm monitoring"],
        ["III", "Inferior-right (120°)","Upright P, R, T"],
        ["aVR", "Right arm (–150°)",   "Normally NEGATIVE (looking into the heart from upper right — opposite direction of main current)"],
        ["aVL", "Left arm (–30°)",     "Lateral view; may have small Q wave"],
        ["aVF", "Inferior (90°)",      "Looking from below; inferior wall"],
    ],
    col_widths=[1.8*cm, 4.5*cm, 11.2*cm]
))
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 7: HEART RATE
# ════════════════════════════════════════════════════════════════════════════
story.append(banner("PART 7 — How to Calculate Heart Rate", C_TEAL))
story.append(sp(8))

story += h2("Method 1 — The 300 Rule (for regular rhythms)")
story.append(body(
    "Count the number of <b>large boxes</b> between two consecutive R waves, "
    "then divide 300 by that number."
))
story.append(sp(4))
story.append(make_table(
    ["Large Boxes between R–R", "Heart Rate", "Interpretation"],
    [
        ["1", "300 bpm", "Very fast (rare)"],
        ["2", "150 bpm", "Tachycardia (e.g., atrial flutter 2:1)"],
        ["3", "100 bpm", "Upper limit of normal / mild tachycardia"],
        ["4", "75 bpm",  "Normal"],
        ["5", "60 bpm",  "Normal (lower limit)"],
        ["6", "50 bpm",  "Bradycardia"],
        ["7+", "<43 bpm","Significant bradycardia"],
    ],
    col_widths=[5.5*cm, 4*cm, 8*cm]
))
story.append(sp(4))
story.append(tip_box("Memory mnemonic",
    "300 → 150 → 100 → 75 → 60 → 50  (one R-R large box at a time)"))
story.append(sp(6))

story += h2("Method 2 — Count QRS Complexes")
story += bullets([
    "Find a 10-second strip (usually the bottom rhythm strip on a standard ECG)",
    "Count all QRS complexes in that 10 seconds",
    "Multiply by 6 → heart rate per minute",
    "Use this for irregular rhythms (e.g., atrial fibrillation)",
])
story.append(sp(6))
story.append(make_table(
    ["Heart Rate Category", "Rate (bpm)", "Common Causes"],
    [
        ["Normal Sinus Rhythm", "60–100", "Healthy baseline"],
        ["Sinus Bradycardia", "<60", "Athletes, vagal tone, beta-blockers, hypothyroidism, inferior MI, hypothermia"],
        ["Sinus Tachycardia", ">100", "Pain, fever, anaemia, anxiety, PE, thyrotoxicosis, heart failure"],
    ],
    col_widths=[4.5*cm, 3.5*cm, 9.5*cm]
))
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 8: SYSTEMATIC APPROACH
# ════════════════════════════════════════════════════════════════════════════
story.append(banner("PART 8 — Systematic Approach to Reading Any ECG", C_NAVY))
story.append(sp(8))
story.append(body(
    "Always read an ECG in the <b>same order every single time</b>. This prevents you from "
    "being distracted by one obvious finding and missing something equally important."
))
story.append(sp(6))

story.append(make_table(
    ["Step", "What to Assess", "Normal", "Abnormal = Think..."],
    [
        ["1", "RATE\nCount large boxes between R-R", "60–100 bpm", "<60 = bradycardia\n>100 = tachycardia"],
        ["2", "RHYTHM\nAre all R-R intervals equal?\nIs it regular or irregular?", "Regular; all R-R equal", "Irregular = AF, heart block, ectopics\nRegularly irregular = 2nd degree block"],
        ["3", "P WAVES\nPresent? One before every QRS?\nUpright in lead II?", "Yes, Yes, Yes", "Absent = AF, junctional rhythm\nNo P before QRS = AV block, ectopic ventricular beat"],
        ["4", "PR INTERVAL\nMeasure onset P to onset QRS", "120–200 ms\n(3–5 small boxes)", "Short = WPW; Long = 1st degree block\nMissing/variable = 2nd/3rd degree block"],
        ["5", "QRS COMPLEX\nDuration? Morphology?", "<120 ms (narrow)", "Wide ≥120 ms = BBB or ventricular beat\nDeep Q waves = old MI"],
        ["6", "ST SEGMENT & T WAVES\nFlat baseline? T wave direction?", "ST isoelectric\nT upright in most leads", "ST elevation = STEMI, pericarditis\nST depression = ischaemia, NSTEMI, digoxin\nT inversion = ischaemia, PE, hypertrophy"],
        ["7", "QT INTERVAL\nMeasure QRS start to T wave end", "QTc <440 ms (M)\nQTc <460 ms (F)", "Prolonged = Torsades risk\nShort = hypercalcaemia"],
    ],
    col_widths=[0.8*cm, 4.5*cm, 3.8*cm, 8.4*cm]
))
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 9: COMMON PATTERNS (with images)
# ════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(banner("PART 9 — Common ECG Patterns (With Real Tracings)", C_ORANGE))
story.append(sp(8))

story += h1("9.1 Atrial Flutter")
story += bullets([
    "Sawtooth (saw-blade) flutter waves — most visible in leads II, III, aVF and V1",
    "Atrial rate: ~300 bpm (range 250–350 bpm)",
    "Ventricular rate depends on AV block ratio: 2:1 = 150 bpm, 3:1 = 100 bpm",
    "<b>Key clue: A regular narrow tachycardia at ~150 bpm almost always = atrial flutter with 2:1 block</b>",
])
story.append(sp(4))
story += rl_img("aflutter.png", "aflutter.png", width=W,
    caption="Atrial flutter — sawtooth flutter waves clearly visible in lead V1 (black arrows). (Miller's Anesthesia, 10th Ed.)")
story.append(sp(8))

story += h1("9.2 Atrial Fibrillation (AF)")
story += bullets([
    "<b>Absent P waves</b> — no organised atrial activity; chaotic or flat baseline",
    "<b>Irregularly irregular</b> ventricular rhythm — no two R-R intervals are equal",
    "Narrow QRS (unless bundle branch block or pre-excitation)",
    "Causes: ischaemia, valvular disease, alcohol, thyrotoxicosis, heart failure",
    "Risk: thromboembolism — blood pools in atrium → clot → stroke",
])
story.append(sp(4))
story += rl_img("af.png", "af.png", width=W,
    caption="Atrial fibrillation — irregularly irregular rhythm with no identifiable P waves. (Miller's Anesthesia, 10th Ed.)")
story.append(sp(8))

story += h1("9.3 AV Heart Blocks")
story += rl_img("av_blocks.png", "av_blocks.png", width=W,
    caption="AV block examples: A = 1st degree (long PR), B = Mobitz I/Wenckebach (progressive PR then dropped beat),\n"
            "C = Mobitz II (sudden dropped beat, constant PR), D = 2:1 block, E = 3rd degree/complete heart block.\n(Washington Manual of Medical Therapeutics)")
story.append(sp(6))

story.append(make_table(
    ["Type", "ECG Finding", "Site of Block", "Risk / Action"],
    [
        ["1st Degree", "PR interval >200 ms every beat. No dropped beats.", "AV node (slow conduction)", "Benign. Monitor. No treatment usually needed."],
        ["2nd Degree\nMobitz I\n(Wenckebach)", "Progressive PR prolongation → one dropped QRS → cycle repeats. Group beating pattern.", "Within AV node (proximal)", "Usually benign. Rarely needs pacemaker."],
        ["2nd Degree\nMobitz II", "Constant PR interval → sudden dropped QRS without warning. Often wide QRS.", "Below AV node (distal His-Purkinje)", "Serious. High risk of progressing to complete block. Pacemaker often required."],
        ["3rd Degree\n(Complete)", "Complete AV dissociation. Atria and ventricles beat independently. More P waves than QRS complexes.", "Complete block at any level", "Emergency. Haemodynamic compromise. Temporary then permanent pacemaker needed."],
    ],
    col_widths=[2.8*cm, 5.5*cm, 4*cm, 5.2*cm]
))
story.append(sp(8))

story += h1("9.4 Ventricular Tachycardia (VT)")
story += bullets([
    "≥3 consecutive beats originating from the ventricles at rate >100 bpm",
    "<b>Wide QRS (≥120 ms)</b> — signal not using the fast Purkinje system",
    "AV dissociation (P waves unrelated to QRS) — pathognomonic when visible",
    "Fusion beats and capture beats confirm VT",
    "Can cause haemodynamic compromise; may degenerate to VF (cardiac arrest)",
    "Sustained VT: lasts >30 seconds; Non-sustained: stops within 30 seconds spontaneously",
])
story.append(sp(4))
story += rl_img("vt.png", "vt.png", width=W,
    caption="Ventricular tachycardia — broad, regular complexes at >100 bpm. (Miller's Anesthesia, 10th Ed.)")
story.append(sp(8))

story += h1("9.5 Torsades de Pointes")
story += bullets([
    "A form of polymorphic VT (QRS morphology changes from beat to beat)",
    "QRS complexes appear to 'twist' around the isoelectric baseline",
    "Rate: 200–250 bpm",
    "Preceded by prolonged QT interval — always check QT before initiating certain drugs",
    "Causes: drugs (class Ia/III antiarrhythmics, antipsychotics, some antibiotics), low K⁺/Mg²⁺, congenital long QT",
    "Treatment: IV magnesium sulphate; correct electrolytes; temporary pacing if recurrent",
])
story.append(sp(4))
story += rl_img("torsades.png", "torsades.png", width=W,
    caption="Torsades de Pointes — initiating beats with prolonged QT then twisting polymorphic VT. (Miller's Anesthesia, 10th Ed.)")
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 10: NORMAL VALUES REFERENCE TABLE
# ════════════════════════════════════════════════════════════════════════════
story.append(banner("PART 10 — Normal Values Quick Reference", C_TEAL))
story.append(sp(8))

story.append(make_table(
    ["Parameter", "Normal Value", "What Abnormal Means"],
    [
        ["Heart Rate",       "60–100 bpm",            "<60 = bradycardia; >100 = tachycardia"],
        ["P wave duration",  "<120 ms",               "Wide = atrial enlargement or inter-atrial block"],
        ["P wave axis",      "Upright in II, inverted in aVR", "Inverted in II = ectopic/junctional origin"],
        ["PR interval",      "120–200 ms",            "<120 = pre-excitation (WPW); >200 = 1st degree AV block"],
        ["QRS duration",     "<120 ms",               "≥120 ms = bundle branch block or ventricular beat"],
        ["QRS axis",         "–30° to +90°",          "Left axis = LBBB, LVH, inferior MI; Right axis = RVH, PE, RBBB"],
        ["ST segment",       "Isoelectric (flat)",    "Elevation = STEMI, pericarditis; Depression = ischaemia, digoxin"],
        ["T wave",           "Upright in I, II, V3–V6", "Peaked = hyperkalaemia; Inverted = ischaemia, PE, hypertrophy"],
        ["QTc (men)",        "<440 ms",               "Prolonged = risk of Torsades de Pointes"],
        ["QTc (women)",      "<460 ms",               "Women have slightly longer QT physiologically"],
        ["U wave",           "Small, upright (may be absent)", "Prominent = hypokalaemia; inverted = ischaemia"],
    ],
    col_widths=[4*cm, 4.5*cm, 9*cm]
))
story.append(sp(10))

# ════════════════════════════════════════════════════════════════════════════
# PART 11: THE STORY OF ONE HEARTBEAT
# ════════════════════════════════════════════════════════════════════════════
story.append(banner("PART 11 — The Story of One Heartbeat on ECG", C_NAVY))
story.append(sp(8))
story.append(body(
    "Think of the ECG as telling a sequential story from top to bottom of the heart each time the heart beats:"
))
story.append(sp(6))

story.append(make_table(
    ["Event", "ECG Feature", "What the Heart Is Doing"],
    [
        ["SA node fires",           "No visible deflection",     "Pacemaker triggers a signal — starts the beat"],
        ["Atria depolarize",        "P wave",                    "Atria contract, pushing blood into the ventricles"],
        ["AV node delays signal",   "PR segment (flat line)",    "Traffic light pause — ventricles fill with blood"],
        ["Ventricles depolarize",   "QRS complex",               "Both ventricles contract powerfully, ejecting blood"],
        ["Ventricles fully excited","ST segment (flat)",         "All ventricular cells depolarized — brief plateau"],
        ["Ventricles repolarize",   "T wave",                    "Ventricles relax, refill — ready for next beat"],
        ["Heart at rest",           "TP segment (flat baseline)","Electrical silence between beats (diastole)"],
    ],
    col_widths=[4.5*cm, 4*cm, 9*cm]
))
story.append(sp(8))
story.append(tip_box("The Golden Memory Trick",
    "P = Pump atria    •    QRS = Squeeze ventricles    •    T = Time to recover\n"
    "PR flat = Gate closed at AV node    •    ST flat = Whole ventricle lit up    •    TP flat = Heart resting"))

story.append(sp(16))
story.append(rule(C_NAVY, 1.5))
story.append(Paragraph(
    "Sources: Guyton &amp; Hall Textbook of Medical Physiology · Costanzo Physiology 7th Ed. · "
    "Goldman-Cecil Medicine · Roberts &amp; Hedges' Clinical Procedures · "
    "Katzung's Basic &amp; Clinical Pharmacology 16th Ed. · Tintinalli's Emergency Medicine · "
    "Miller's Anesthesia 10th Ed. · Washington Manual of Medical Therapeutics",
    sSource))

# ── Build ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"\nPDF saved: {OUTPUT}")
Running Command

cd /tmp/workspace/medical-notes && python generate_ecg_pdf.py 2>&1

The error is in the Image helper — kind='proportional' needs both width and height. Let me fix the image helper to set explicit height.
Editing File

~/medical-notes/generate_ecg_pdf.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/medical-notes/generate_ecg_pdf.py'
Running Command

cd /tmp/workspace/medical-notes && python generate_ecg_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/medical-notes/ECG_Beginner_Guide.pdf

Your ECG beginner guide PDF is ready — 6.7 MB with all 11 real textbook images embedded:

ECG Beginner Guide

PDF Document · PDF

What's inside (11 parts):
  1. What Is an ECG — purpose and what it detects
  2. Cardiac Conduction System — SA node → AV node → Bundle of His → Purkinje fibers with the full anatomy diagram
  3. Depolarization & Repolarization — action potential diagram vs ECG waves side by side
  4. The ECG Paper & Grid — how to read time and voltage from the grid
  5. All Waves Explained — P, PR, QRS, ST, T, QT, U, RR with normal values and what abnormalities mean
  6. The 12 Leads — precordial placement photo, limb lead angles, territory table (which leads = which heart wall)
  7. Heart Rate Calculation — 300 rule table + count method
  8. Systematic 7-Step Reading Approach — never miss a finding
  9. Common Patterns with real ECG tracings — Atrial Flutter, AF, AV blocks (all degrees), VT, Torsades
  10. Normal Values Quick Reference Table
  11. The Story of One Heartbeat — a sequential summary table + golden memory trick
This is a shared conversation. Sign in to Orris to start your own chat.