Interpret this table in simplified way
| Ratio | What's Happening | Diagnosis |
|---|---|---|
| < 0.3 | H⁺ rise is much less than expected for the CO₂ rise | Chronic respiratory acidosis + Metabolic alkalosis (the body is over-compensating) |
| = 0.3 | H⁺ rise matches what chronic CO₂ retention would cause | Pure Chronic Respiratory Acidosis |
| 0.3 - 0.8 | H⁺ rise is between chronic and acute expected values | Chronic respiratory acidosis + Acute respiratory acidosis (mixed) - check pH |
| = 0.8 | H⁺ rise matches what acute CO₂ retention would cause | Pure Acute Respiratory Acidosis |
| > 0.8 | H⁺ rise is more than even acute respiratory acidosis explains | Acute or Chronic Respiratory Acidosis + Metabolic Acidosis |
Explain how to calculate ΔH⁺ and ΔPco₂ from lab values
| Parameter | Normal Value |
|---|---|
| pH | 7.40 |
| H⁺ | 40 nmol/L |
| PaCO₂ | 40 mmHg |
H⁺ (nmol/L) ≈ 80 − (last two digits of pH)
| pH | Calculation | H⁺ |
|---|---|---|
| 7.40 | 80 - 40 | = 40 nmol/L |
| 7.30 | 80 - 30 | = 50 nmol/L |
| 7.20 | 80 - 20 | = 60 nmol/L |
| 7.50 | 80 - 50 | = 30 nmol/L |
This formula is accurate between pH 7.20 - 7.55. Outside this range, use the exact formula below.
H⁺ = 10^(9 − pH) nmol/L
1. Read pH and PaCO₂ from ABG
2. H⁺ = 80 − (last 2 digits of pH)
3. ΔH⁺ = H⁺ − 40
4. ΔPco₂ = PaCO₂ − 40
5. Ratio = ΔH⁺ ÷ ΔPco₂ → look up in table
Different sodium bicarbonate preparation and its infusion dose
sodium bicarbonate preparations IV infusion dose concentrations clinical
| Concentration | Strength | Volume | Content | Tonicity |
|---|---|---|---|---|
| 8.4% | 1 mEq/mL | 50 mL | 50 mEq per ampule | Hypertonic (2000 mOsm/L) |
| 7.5% | 0.9 mEq/mL | 50 mL | 44.6 mEq per ampule | Hypertonic |
| 4.2% | 0.5 mEq/mL | 100 mL | 50 mEq per vial | Less hypertonic |
8.4% is the most commonly used in emergencies - each 50 mL ampule = 1 mEq/mL, easy to dose.
| Preparation | Volume | NaHCO₃ content | Carrier fluid |
|---|---|---|---|
| 1.26% | 500 mL | 75 mEq | Isotonic (near-physiologic) |
| 50 mEq in 1L | 1000 mL | 50 mEq | D5W, 0.45% NS, or sterile water |
| 75 mEq in 1L | 1000 mL | 75 mEq | D5W or 0.45% NS |
| 100 mEq in 1L | 1000 mL | 100 mEq | D5W or 0.45% NS |
| 150 mEq in 1L | 1000 mL | 150 mEq | D5W or sterile water |
The 1.26% (isotonic) bag is safest for large-volume infusions - least risk of hypernatremia.
| Form | Strength |
|---|---|
| NaHCO₃ tablets | 325 mg or 650 mg (= 7.7 mEq per 650 mg tablet) |
| KHCO₃ tablets | 25-50 mEq |
| KHCO₃-citric acid | 20-40 mEq |
Dose (mEq) = 0.3 × Weight (kg) × Base Deficit
| Point | Detail |
|---|---|
| Central line preferred for 8.4% | Hypertonic - can cause tissue necrosis if extravasated |
| Peripheral use | Dilute 8.4% → use 1.26% or dilute further |
| Monitor: | ABG, serum Na⁺, K⁺, ionized Ca²⁺, urine pH |
| Caution: | Lowers ionized Ca²⁺ - do not mix with calcium solutions |
| Ventilation | Increase rate during infusion - NaHCO₃ generates CO₂ |
| Overshoot risk | Never fully correct acidosis in one session |
Difference between ABG and VBG
ABG vs VBG difference clinical correlation pH PCO2 PO2 accuracy
| Feature | ABG | VBG |
|---|---|---|
| Blood source | Artery (usually radial) | Vein (peripheral or central) |
| Pain level | More painful | Less painful |
| Difficulty | Technically harder | Easier |
| Needle-stick risk | Higher (arterial pressure) | Lower |
| Complications | Arterial spasm, hematoma, nerve injury, thrombosis | Minimal |
| Allen's test needed? | Yes (before radial puncture) | No |
| Parameter | ABG (Normal) | VBG (Normal) | Difference | Reliable on VBG? |
|---|---|---|---|---|
| pH | 7.35-7.45 | 7.31-7.41 | VBG ~0.03-0.05 lower | ✅ Yes |
| PCO₂ | 35-45 mmHg | 41-51 mmHg | VBG ~4-6 mmHg higher | ✅ Yes (screening) |
| HCO₃ | 22-26 mEq/L | 22-26 mEq/L | Essentially same | ✅ Yes |
| Base Excess | -2 to +2 | Similar | Minimal difference | ✅ Yes |
| PO₂ | 80-100 mmHg | 30-50 mmHg | Very different | ❌ No - use SpO₂ |
| Lactate | <2 mmol/L | Similar | Minimal difference | ✅ Yes |
The key rule: VBG tells you about acid-base status reliably. It tells you nothing about oxygenation - use pulse oximetry (SpO₂) for that instead.
Estimated ABG pH = VBG pH + 0.05
Estimated ABG PCO₂ = VBG PCO₂ − 5 mmHg
VBG = ACID-BASE ✅ + OXYGENATION ❌
ABG = ACID-BASE ✅ + OXYGENATION ✅
If VBG is normal → ABG is almost certainly normal
If VBG is abnormal → may need ABG to confirm and quantify
Give me full note on atrial fibrillation pathophysiology, etiology, diagnosis and management according to latest guideline for emergency physician.
"atrial fibrillation"[MeSH Terms] AND "guideline"[pt]
atrial fibrillation 2023 2024 ACC AHA ESC guidelines emergency management
https://amu.hr/article/current-management-of-atrial-fibrilla…
Pulmonary TB latest WHO update
WHO tuberculosis guidelines 2024 2025 latest update treatment
"tuberculosis"[MeSH Terms] AND "WHO" AND "guideline"[pt]
https://www.who.int/news/item/08-10-2025-who-releases-new-gu…
WHO consolidated guidelines tuberculosis module 4 2025 DS-TB DR-TB treatment update summary
https://pmc.ncbi.nlm.nih.gov/articles/PMC12248249
WHO 2025 Module 4 tuberculosis 4-month regimen isoniazid rifapentine moxifloxacin pyrazinamide DS-TB update
| Category | Examples |
|---|---|
| Immunosuppression | HIV (highest risk - 5-10% per year), TNF-α inhibitors, organ transplant, steroids |
| Malnutrition | BMI < 18.5 - major independent risk factor (new WHO emphasis 2025) |
| Diabetes mellitus | 3x increased risk |
| Silicosis | Occupational exposure |
| CKD / dialysis | Uremia-induced immune suppression |
| Alcohol use disorder | Social + immune factors |
| Recent TB infection | <2 years from exposure |
| Extremes of age | Infants, elderly |
| Tobacco smoking | Independent risk factor |
| Scenario | Features |
|---|---|
| HIV coinfection (CD4 <200) | Lower lobe, no cavity, smear-negative, miliary pattern, normal CXR possible |
| Miliary TB | Hematogenous dissemination, 1-2 mm granulomas in lungs/liver/bone marrow, fundoscopic choroidal tubercles |
| Primary progressive | Middle/lower lobe consolidation, hilar adenopathy |
| Elderly | Atypical symptoms, lower lobe involvement, confused with other diagnoses |
| TB pleuritis | Exudative effusion, pleuritic chest pain, 3-6 months post-infection |
| IRIS (TB-immune reconstitution) | Paradoxical worsening after starting ART in HIV patients |
| Finding | Significance |
|---|---|
| Apical/posterior upper lobe infiltrate | Classic reactivation TB |
| Cavitation | Active, highly infectious |
| Tree-in-bud opacities | Endobronchial spread |
| Miliary pattern (1-2 mm nodules) | Hematogenous dissemination |
| Ghon complex / Ranke complex | Healed primary infection |
| Hilar adenopathy | Primary disease |
| Lower lobe + no cavity | HIV-related or primary |
| Normal CXR | Does NOT exclude TB in HIV patients |
CT chest is more sensitive than plain CXR, especially in HIV or subtle disease.
| Test | Specimen | Sensitivity | Notes |
|---|---|---|---|
| Sputum AFB smear (ZN stain) | 3 sputum samples (early morning) | 45-80% | Rapid, cheap; positive = infectious; negative doesn't exclude |
| Sputum culture (gold standard) | Sputum/BAL | 80-90% | Takes 2-8 weeks (liquid media 2-3 wks; solid 6-8 wks); confirms diagnosis & DST |
| Xpert MTB/RIF (GeneXpert) | Sputum/BAL/tissue | 88% (smear+ve), 68% (smear-ve) | WHO first-line rapid test - 2 hours; also detects rifampicin resistance |
| Xpert MTB/RIF Ultra | Any | Slightly more sensitive than standard | Better for paucibacillary/extrapulmonary |
| TB-LAMP | Sputum | Similar to smear | Point-of-care; less widely available |
| Line probe assay (LPA) | Culture/sputum | - | Detects INH & RIF resistance (Hain GenoType) |
| Whole genome sequencing | Culture | Reference | Comprehensive DST; not yet routine |
| Test | Method | Interpretation |
|---|---|---|
| Tuberculin Skin Test (TST/Mantoux) | 5 TU PPD ID → read induration at 48-72h | ≥5 mm (HIV/immunocompromised); ≥10 mm (high-risk); ≥15 mm (low-risk) |
| IGRA (QuantiFERON-TB Gold Plus / T-SPOT.TB) | Blood test; measures IFN-γ to ESAT-6/CFP-10 | Preferred over TST in BCG-vaccinated individuals |
TST/IGRA = positive means prior exposure / LTBI - DOES NOT diagnose active TB. Active TB requires microbiological confirmation.
Symptoms of TB (cough >2wks, fever, weight loss, night sweats)
↓
Chest X-ray
↓
Xpert MTB/RIF (first-line WHO diagnostic tool)
├─ MTB detected, RIF resistant → MDR-TB workup → LPA/DST
├─ MTB detected, RIF sensitive → DS-TB treatment
└─ MTB not detected → sputum culture + clinical evaluation
├─ Culture positive → TB treatment
└─ Culture negative + clinical improvement on treatment → culture-negative TB
| Phase | Duration | Drugs | Abbreviation |
|---|---|---|---|
| Intensive | 2 months | Isoniazid (H) + Rifampicin (R) + Pyrazinamide (Z) + Ethambutol (E) | 2HRZE |
| Continuation | 4 months | Isoniazid (H) + Rifampicin (R) | 4HR |
| Phase | Duration | Drugs |
|---|---|---|
| Intensive | 2 months | Isoniazid (H) + Rifapentine (P) + Pyrazinamide (Z) + Moxifloxacin (M) |
| Continuation | 2 months | Isoniazid (H) + Rifapentine (P) + Moxifloxacin (M) |
| Drug | 40-55 kg | 56-75 kg | 76-90 kg |
|---|---|---|---|
| Isoniazid | 300 mg | 300 mg | 300 mg |
| Rifapentine | 900 mg | 1200 mg | 1500 mg |
| Moxifloxacin | 400 mg | 400 mg | 400 mg |
| Pyrazinamide (intensive phase only) | 1000 mg | 1500 mg | 2000 mg |
Always give pyridoxine (B6) 25-50 mg/day with isoniazid to prevent peripheral neuropathy.
| Term | Definition |
|---|---|
| MDR-TB | Resistant to isoniazid AND rifampicin |
| RR-TB | Rifampicin-resistant (treated same as MDR-TB) |
| Pre-XDR-TB | MDR/RR-TB + resistant to any fluoroquinolone |
| XDR-TB | MDR/RR-TB + resistant to fluoroquinolone + bedaquiline OR linezolid |
| Drug | Dose |
|---|---|
| B - Bedaquiline | 400 mg OD x 2 weeks → 200 mg 3x/week x 22 weeks |
| Pa - Pretomanid | 200 mg OD |
| L - Linezolid | 600 mg OD (may reduce to 300 mg for toxicity) |
| M - Moxifloxacin | 400 mg OD |
If fluoroquinolone-resistant: use BPaL (without moxifloxacin) - same duration
| Group | Drugs | Role |
|---|---|---|
| Group A (always include if possible) | Levofloxacin OR Moxifloxacin, Bedaquiline, Linezolid | Core agents |
| Group B (add to complete regimen) | Clofazimine, Cycloserine/Terizidone | Add-ons |
| Group C (when Groups A&B insufficient) | Ethambutol, Delamanid, Pyrazinamide, Imipenem-cilastatin, Amikacin, Ethionamide, PAS | Last resort |
| Regimen | Duration | Notes |
|---|---|---|
| 1HP (Isoniazid + Rifapentine weekly) | 1 month (12 doses) | Preferred - shortest, highest completion |
| 3HP (Isoniazid + Rifapentine weekly) | 3 months (12 doses) | WHO preferred option |
| 3HR (Isoniazid + Rifampicin daily) | 3 months | Alternative |
| 6H (Isoniazid daily) | 6 months | Alternative; 9H also acceptable |
| Timepoint | Action |
|---|---|
| Baseline | Sputum AFB x3, culture, LFTs, CBC, creatinine, uric acid, visual acuity (if ethambutol) |
| 2 months (end of intensive phase) | Repeat sputum culture - culture conversion is KEY prognostic marker |
| Monthly | Clinical assessment, symptom review, adherence check |
| End of treatment | Sputum smear + culture; CXR |
| Adverse effects monitoring | LFTs monthly (isoniazid/rifampicin hepatotoxicity); vision (ethambutol); hearing (aminoglycosides); QTc (bedaquiline, fluoroquinolones, clofazimine) |
Stop hepatotoxic anti-TB drugs if: ALT >3x ULN with symptoms OR ALT >5x ULN without symptoms
| Population | Key Considerations |
|---|---|
| HIV + TB | Start TB treatment FIRST → add ART within 2-8 weeks (2 weeks if CD4 <50); use rifabutin instead of rifampicin with PIs; beware IRIS |
| Pregnancy | 2HRZE/4HR standard regimen (rifampicin + pyrazinamide generally safe); avoid aminoglycosides (ototoxicity); pyridoxine essential |
| Children | 4-month regimen for non-severe TB now recommended; weight-based dosing |
| Diabetes | Monitor glycaemia closely; rifampicin reduces OHG levels |
| CKD/Dialysis | Avoid ethambutol (accumulates); adjust pyrazinamide; rifampicin dose unchanged |
| Liver disease | Avoid pyrazinamide if severe; monitor LFTs closely |
Stroke recent update 2026
"ischemic stroke"[MeSH Terms] AND "guideline"[pt]
stroke guidelines 2025 2026 AHA ASA update ischemic stroke treatment thrombolysis thrombectomy
https://www.tctmd.com/news/ahaasa-release-new-comprehensive-…
PMID: 41582814
2026 AHA ASA stroke guideline blood pressure management thrombectomy window extended pediatric dysphagia secondary prevention
https://recapem.com/update-on-management-of-acute-ischemic-s…
Different triage system for emergency physician
emergency department triage systems comparison ESI Manchester ATS CTAS START MCI 2024 2025
START triage SALT triage mass casualty incident MCI system categories 2025
| Level | Category | Color | Criteria | Target Time to Physician |
|---|---|---|---|---|
| 1 | Resuscitation | Red | Requires immediate life-saving intervention (intubation, defibrillation, CPR) | Immediate |
| 2 | Emergent | Orange | High-risk situation; lethargic/disoriented; severe pain/distress; dangerous vital signs | <15 min |
| 3 | Urgent | Yellow | Stable vitals but needs multiple resources (labs + imaging + IV) | <30 min |
| 4 | Less Urgent | Green | Needs one resource only (one lab OR one X-ray) | <60 min |
| 5 | Non-Urgent | Blue | Needs no resources - history + exam only | <120 min |
Step 1: Does the patient need IMMEDIATE life-saving intervention? → Level 1
Step 2: Is this a HIGH-RISK situation / confused / severe distress? → Level 2
Step 3: How many RESOURCES will this patient need?
≥2 resources → Level 3 (also check vital signs - abnormals bump to Level 2)
1 resource → Level 4
0 resources → Level 5
| Level | Category | Color | Target Time |
|---|---|---|---|
| 1 | Immediate | Red | Immediate (0 min) |
| 2 | Very Urgent | Orange | 10 minutes |
| 3 | Urgent | Yellow | 60 minutes |
| 4 | Standard | Green | 120 minutes |
| 5 | Non-Urgent | Blue | 240 minutes |
| Level | Category | Color | Target Time to Physician | Reassessment |
|---|---|---|---|---|
| 1 | Resuscitation | Blue/Red | Immediate | Continuous |
| 2 | Emergent | Red/Orange | 15 minutes | Every 15 min |
| 3 | Urgent | Yellow | 30 minutes | Every 30 min |
| 4 | Less Urgent | Green | 60 minutes | Every 60 min |
| 5 | Non-Urgent | White | 120 minutes | Every 120 min |
| Level | Category | Color | Max Time to Treatment | Duration of Assessment |
|---|---|---|---|---|
| 1 | Immediately Life-Threatening | Red | Immediate | Continuous |
| 2 | Imminently Life-Threatening | Orange | 10 minutes | Every 10 min |
| 3 | Potentially Life-Threatening | Yellow | 30 minutes | Every 30 min |
| 4 | Potentially Serious | Green | 60 minutes | Every 60 min |
| 5 | Less Urgent | Blue | 120 minutes | Every 120 min |
| Level | Category | Color | Action |
|---|---|---|---|
| 1 | Emergency | Red | Immediate |
| 2 | Very Urgent | Orange | Within 10 min |
| 3 | Urgent | Yellow | Within 1 hour |
| 4 | Routine | Green | Within 4 hours |
| 5 | Not Urgent | Blue | Within 8 hours |
| Feature | ESI | MTS | CTAS | ATS | SATS |
|---|---|---|---|---|---|
| Origin | USA | UK | Canada | Australia | South Africa |
| Basis | Acuity + resources | Symptom flowcharts | Complaint + modifiers | Clinical urgency | TEWS + complaint |
| Levels | 5 | 5 | 5 | 5 | 5 |
| Time to complete | 1-2 min | 3-5 min | 5-10 min | 2-3 min | 2-3 min |
| Mandatory reassessment | No | No | Yes | No | No |
| Pediatric version | Yes (ESI-Peds) | Yes (PaedsMTS) | Yes (PaedsCTAS) | Yes | Yes |
| Reliability (κ) | 0.7-0.9 | 0.3-0.6 | 0.7-0.95 | 0.3-0.6 | 0.7 |
| Best for | US EDs, resource prediction | European EDs, symptom-driven | High-reliability, training | Australian setting | Low-resource settings |
| Weakness | Resources subjective | Slow, poor for elderly/atypical | Complex, time-consuming | Moderate reliability | Limited international validation |
No single triage system has proven clearly superior to the others - selection depends on setting, training, and local validation.
| Color | Category | Meaning |
|---|---|---|
| 🔴 Red | Immediate | Life-threatening; needs treatment NOW to survive |
| 🟡 Yellow | Delayed | Serious but stable; can wait |
| 🟢 Green | Minimal/Minor | "Walking wounded"; minor injuries |
| ⚫ Black | Expectant/Dead | Injuries incompatible with survival given resources; or no signs of life |
| ⚫ Gray | Expectant (SALT only) | Expected to die despite maximal intervention |
Can the patient WALK?
YES → GREEN (minimal/walking wounded)
NO ↓
Is patient BREATHING?
NO → Open airway → still not breathing? → BLACK (deceased)
Breathing after opening? → RED (immediate)
YES ↓
Respiratory rate?
>30/min → RED (immediate)
<10/min → RED (immediate)
10-29/min ↓
Perfusion: Radial pulse or capillary refill >2 sec?
No pulse / CRT >2 sec → RED (immediate) + hemorrhage control
Pulse present / CRT ≤2 sec ↓
Mental status: Can follow simple commands?
NO → RED (immediate)
YES → YELLOW (delayed)
"If you can hear me and can walk, move to [safe area]" → GREEN
Assess remaining in priority: Still > Waving > Those who walked but couldn't relocate
| Assessment | Finding | Category |
|---|---|---|
| No signs of life | No breathing, no pulse | BLACK (dead) |
| Signs of life present | → Perform brief lifesaving interventions if possible (control hemorrhage, open airway, give antidote) | ↓ |
| After interventions: Likely to survive? | Cannot follow commands + no peripheral pulse + poor breathing | GRAY (expectant) |
| Obeys commands OR has peripheral pulse OR normal breathing | → | RED (immediate) |
| Significant injury, not immediate | Can wait | YELLOW (delayed) |
| Minor / no injury | Ambulatory | GREEN (minimal) |
Rosen's Emergency Medicine recommends START until more evidence on SALT accumulates.
| Step | START (Adults) | JumpSTART (Children) |
|---|---|---|
| Apneic patient | → BLACK | → Attempt 5 rescue breaths first → if still apneic → BLACK |
| Resp rate normal | 10-29/min | 15-45/min |
| Mental status | Follow commands | AVPU scale (Alert, Voice, Pain, Unresponsive) |
ROUTINE ED TRIAGE (most to least reliable):
CTAS > ESI > MTS > ATS > SATS
MCI/DISASTER TRIAGE:
Adults: START (most validated) or SALT (US national standard)
Children: JumpSTART (pediatric modification of START)
KEY PRINCIPLE DIFFERENCES:
ED triage = save the sickest INDIVIDUAL
MCI triage = save the MOST people with available resources
Different triage system for emergency physician
Generate a pocket guide PDF for ESI vs CTAS decision-making
ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace does not exist"
mkdir -p /home/daytona/workspace/triage-guide && python3 -c "import reportlab; print('reportlab ok')"
~/triage-guide/generate_pocket_guide.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.platypus.flowables import HRFlowable
from reportlab.lib.colors import HexColor
# ── Colour palette ──────────────────────────────────────────────────────────
NAVY = HexColor('#0D1B4B')
TEAL = HexColor('#0077A8')
ORANGE = HexColor('#E05A00')
LIGHT_BG = HexColor('#F0F4FA')
WHITE = colors.white
# Triage level colours
RED = HexColor('#C62828')
ORANGE_T = HexColor('#E65100')
YELLOW_T = HexColor('#F9A825')
GREEN_T = HexColor('#2E7D32')
BLUE_T = HexColor('#1565C0')
L_RED = HexColor('#FFCDD2')
L_ORANGE = HexColor('#FFE0B2')
L_YELLOW = HexColor('#FFF9C4')
L_GREEN = HexColor('#C8E6C9')
L_BLUE = HexColor('#BBDEFB')
# ── Document setup ──────────────────────────────────────────────────────────
OUTPUT = '/home/daytona/workspace/triage-guide/ESI_vs_CTAS_Pocket_Guide.pdf'
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=14*mm, rightMargin=14*mm,
topMargin=14*mm, bottomMargin=14*mm,
title='ESI vs CTAS Pocket Guide',
author='Emergency Medicine Reference'
)
# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
title_style = S('Title2',
fontName='Helvetica-Bold', fontSize=18,
textColor=WHITE, alignment=TA_CENTER, leading=22)
subtitle_style = S('Sub',
fontName='Helvetica', fontSize=9,
textColor=HexColor('#BBDEFB'), alignment=TA_CENTER, leading=12)
section_style = S('Section',
fontName='Helvetica-Bold', fontSize=11,
textColor=WHITE, alignment=TA_CENTER, leading=14)
body_style = S('Body2',
fontName='Helvetica', fontSize=8.5,
textColor=HexColor('#1A1A2E'), leading=12)
small_style = S('Small',
fontName='Helvetica', fontSize=7.5,
textColor=HexColor('#333355'), leading=10)
bold_small = S('BoldSmall',
fontName='Helvetica-Bold', fontSize=8,
textColor=HexColor('#1A1A2E'), leading=11)
note_style = S('Note',
fontName='Helvetica-Oblique', fontSize=7.5,
textColor=HexColor('#444466'), leading=10)
cell_style = S('Cell',
fontName='Helvetica', fontSize=8,
textColor=HexColor('#1A1A2E'), leading=11, alignment=TA_LEFT)
cell_bold = S('CellBold',
fontName='Helvetica-Bold', fontSize=8.5,
textColor=HexColor('#1A1A2E'), leading=11, alignment=TA_LEFT)
hdr_style = S('Hdr',
fontName='Helvetica-Bold', fontSize=9,
textColor=WHITE, alignment=TA_CENTER, leading=12)
# ── Helper to build a coloured header banner ─────────────────────────────────
def banner(text, bg=NAVY, text_style=None):
ts = text_style or section_style
tbl = Table([[Paragraph(text, ts)]], colWidths=[182*mm])
tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), bg),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 8),
('RIGHTPADDING', (0,0), (-1,-1), 8),
('ROUNDEDCORNERS', [4,4,4,4]),
]))
return tbl
# ── Title block ───────────────────────────────────────────────────────────────
title_tbl = Table(
[[Paragraph('ESI vs CTAS', title_style)],
[Paragraph('Emergency Triage Pocket Guide | For Emergency Physicians & Nurses', subtitle_style)]],
colWidths=[182*mm]
)
title_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), NAVY),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
]))
# ── ESI decision algorithm table ──────────────────────────────────────────────
esi_algo = [
[Paragraph('<b>Step</b>', hdr_style),
Paragraph('<b>Question</b>', hdr_style),
Paragraph('<b>Answer</b>', hdr_style),
Paragraph('<b>Level</b>', hdr_style)],
[Paragraph('1', cell_bold),
Paragraph('Immediate life-saving intervention needed?', cell_style),
Paragraph('YES', cell_style),
Paragraph('Level 1 🔴', cell_bold)],
[Paragraph('2', cell_bold),
Paragraph('High-risk / confused / severe distress / dangerous vitals?', cell_style),
Paragraph('YES', cell_style),
Paragraph('Level 2 🟠', cell_bold)],
[Paragraph('3', cell_bold),
Paragraph('How many RESOURCES needed?', cell_style),
Paragraph('≥ 2 resources\n1 resource\n0 resources', cell_style),
Paragraph('Level 3 🟡\nLevel 4 🟢\nLevel 5 🔵', cell_bold)],
[Paragraph('3a', cell_bold),
Paragraph('If Level 3: Are vitals dangerous?', cell_style),
Paragraph('YES → upgrade', cell_style),
Paragraph('Level 2 🟠', cell_bold)],
]
esi_algo_tbl = Table(esi_algo, colWidths=[13*mm, 72*mm, 45*mm, 30*mm])
esi_algo_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), NAVY),
('BACKGROUND', (0,1), (-1,1), L_RED),
('BACKGROUND', (0,2), (-1,2), L_ORANGE),
('BACKGROUND', (0,3), (-1,3), L_YELLOW),
('BACKGROUND', (0,4), (-1,4), L_ORANGE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 8),
('GRID', (0,0), (-1,-1), 0.4, HexColor('#AABBCC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 5),
('RIGHTPADDING', (0,0), (-1,-1), 5),
]))
# ── ESI Vital sign danger zone table ─────────────────────────────────────────
vitals_data = [
[Paragraph('<b>Parameter</b>', hdr_style),
Paragraph('<b>Age <3 mo</b>', hdr_style),
Paragraph('<b>3 mo–3 yr</b>', hdr_style),
Paragraph('<b>3–8 yr</b>', hdr_style),
Paragraph('<b>>8 yr / Adult</b>', hdr_style)],
['HR > (bpm)', '>180', '>160', '>140', '>100'],
['HR < (bpm)', '<50', '<50', '<50', '<50'],
['RR > (bpm)', '>50', '>40', '>30', '>20'],
['SpO₂ <', '<92%', '<92%', '<92%', '<92%'],
['Temp °C >', '>38', '>38.5','—', '>38.5'],
]
vitals_tbl = Table(vitals_data, colWidths=[28*mm, 28*mm, 28*mm, 28*mm, 40*mm])
vitals_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), TEAL),
('BACKGROUND', (0,1), (-1,1), HexColor('#F8F8FF')),
('BACKGROUND', (0,2), (-1,2), HexColor('#F0F0FF')),
('BACKGROUND', (0,3), (-1,3), HexColor('#F8F8FF')),
('BACKGROUND', (0,4), (-1,4), HexColor('#F0F0FF')),
('BACKGROUND', (0,5), (-1,5), HexColor('#F8F8FF')),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTNAME', (0,1), (0,-1), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 7.5),
('ALIGN', (0,0), (-1,-1), 'CENTER'),
('GRID', (0,0), (-1,-1), 0.4, HexColor('#AABBCC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 3),
('BOTTOMPADDING', (0,0), (-1,-1), 3),
]))
# ── CTAS decision table ───────────────────────────────────────────────────────
ctas_data = [
[Paragraph('<b>Level</b>', hdr_style),
Paragraph('<b>Category</b>', hdr_style),
Paragraph('<b>Colour</b>', hdr_style),
Paragraph('<b>Time to MD</b>', hdr_style),
Paragraph('<b>Reassess</b>', hdr_style),
Paragraph('<b>Examples</b>', hdr_style)],
['1', 'Resuscitation', '🔴 Red', 'Immediate', 'Continuous',
'Cardiac arrest, apnoea, RSI needed'],
['2', 'Emergent', '🟠 Orange', '≤15 min', 'q15 min',
'STEMI, stroke, sepsis, major trauma'],
['3', 'Urgent', '🟡 Yellow', '≤30 min', 'q30 min',
'Moderate pain, stable GI bleed, seizure (postictal)'],
['4', 'Less Urgent', '🟢 Green', '≤60 min', 'q60 min',
'Minor injury, sore throat, UTI symptoms'],
['5', 'Non-Urgent', '🔵 Blue', '≤120 min', 'q120 min',
'Prescription refill, rash, well-child concern'],
]
ctas_tbl = Table(ctas_data, colWidths=[10*mm, 28*mm, 18*mm, 22*mm, 20*mm, 64*mm])
ctas_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), NAVY),
('BACKGROUND', (0,1), (-1,1), L_RED),
('BACKGROUND', (0,2), (-1,2), L_ORANGE),
('BACKGROUND', (0,3), (-1,3), L_YELLOW),
('BACKGROUND', (0,4), (-1,4), L_GREEN),
('BACKGROUND', (0,5), (-1,5), L_BLUE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTNAME', (0,1), (0,-1), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 7.5),
('ALIGN', (1,0), (4,-1), 'CENTER'),
('GRID', (0,0), (-1,-1), 0.4, HexColor('#AABBCC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 4),
('RIGHTPADDING', (0,0), (-1,-1), 4),
]))
# ── ESI Level detailed table ──────────────────────────────────────────────────
esi_levels = [
[Paragraph('<b>Level</b>', hdr_style),
Paragraph('<b>Category</b>', hdr_style),
Paragraph('<b>Basis for Decision</b>', hdr_style),
Paragraph('<b>Wait Time</b>', hdr_style),
Paragraph('<b>Clinical Examples</b>', hdr_style)],
['1', 'Resuscitation',
'Immediate life-saving intervention required NOW',
'Immediate',
'Intubation, cardioversion, CPR, massive haemorrhage'],
['2', 'Emergent',
'High-risk; confused/lethargic; severe pain/distress; danger vitals',
'<15 min',
'STEMI, anaphylaxis, active seizure, severe dyspnoea, suicidal'],
['3', 'Urgent',
'≥2 resources needed; vitals normal or mildly abnormal',
'<30 min',
'Abdominal pain (labs + CT), moderate asthma (neb + CXR)'],
['4', 'Less Urgent',
'Only 1 resource needed; no distress',
'<60 min',
'Ankle sprain (X-ray only), simple laceration (repair only)'],
['5', 'Non-Urgent',
'0 resources; history + exam only',
'<120 min',
'Prescription refill, cold symptoms, well-controlled chronic disease'],
]
esi_levels_tbl = Table(esi_levels, colWidths=[10*mm, 25*mm, 55*mm, 20*mm, 60*mm])
esi_levels_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), NAVY),
('BACKGROUND', (0,1), (-1,1), L_RED),
('BACKGROUND', (0,2), (-1,2), L_ORANGE),
('BACKGROUND', (0,3), (-1,3), L_YELLOW),
('BACKGROUND', (0,4), (-1,4), L_GREEN),
('BACKGROUND', (0,5), (-1,5), L_BLUE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTNAME', (0,1), (0,-1), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 7.5),
('ALIGN', (1,0), (3,-1), 'CENTER'),
('GRID', (0,0), (-1,-1), 0.4, HexColor('#AABBCC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 4),
('RIGHTPADDING', (0,0), (-1,-1), 4),
]))
# ── Side-by-side comparison table ────────────────────────────────────────────
compare_data = [
[Paragraph('<b>Feature</b>', hdr_style),
Paragraph('<b>ESI</b>', hdr_style),
Paragraph('<b>CTAS</b>', hdr_style)],
['Origin / Country', 'USA (AHRQ)', 'Canada (CAEP)'],
['Decision Basis', 'Acuity + Expected Resources', 'Chief Complaint + Modifiers + Vitals'],
['Time to Complete', '1–2 minutes', '5–10 minutes'],
['Mandatory Reassessment', '✗ (only when needed)', '✓ At fixed intervals per level'],
['Paediatric Version', 'ESI Paeds (same algorithm)', 'PaedsCTAS (age-adjusted criteria)'],
['Reliability (κ)', '0.70–0.90', '0.70–0.95 (highest of all systems)'],
['Unique Strength', 'Resource prediction; fast', 'Built-in safety net (reassessment)'],
['Main Weakness', 'Resources subjective; variable across countries', 'Complex; requires training; time-intensive'],
['Best Setting', 'High-volume US EDs; resource allocation focus', 'Any ED; especially when structured monitoring needed'],
['Pain Score Used?', '✓ (for Level 2 consideration)', '✓ (first-order modifier)'],
['Vital Sign Threshold', 'Triggers Level 2 upgrade from Level 3', 'Incorporated as modifiers for level adjustment'],
['Non-disabling mild symptoms', 'Level 4 or 5', 'Level 4 or 5'],
]
compare_tbl = Table(compare_data, colWidths=[48*mm, 67*mm, 67*mm])
compare_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), NAVY),
('BACKGROUND', (0,1), (-1,1), LIGHT_BG),
('BACKGROUND', (0,2), (-1,2), WHITE),
('BACKGROUND', (0,3), (-1,3), LIGHT_BG),
('BACKGROUND', (0,4), (-1,4), WHITE),
('BACKGROUND', (0,5), (-1,5), LIGHT_BG),
('BACKGROUND', (0,6), (-1,6), WHITE),
('BACKGROUND', (0,7), (-1,7), LIGHT_BG),
('BACKGROUND', (0,8), (-1,8), WHITE),
('BACKGROUND', (0,9), (-1,9), LIGHT_BG),
('BACKGROUND', (0,10),(-1,10),WHITE),
('BACKGROUND', (0,11),(-1,11),LIGHT_BG),
('BACKGROUND', (0,12),(-1,12),WHITE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTNAME', (0,1), (0,-1), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 8),
('GRID', (0,0), (-1,-1), 0.4, HexColor('#AABBCC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 5),
('RIGHTPADDING', (0,0), (-1,-1), 5),
]))
# ── CTAS Modifiers box ────────────────────────────────────────────────────────
ctas_mod_data = [
[Paragraph('<b>CTAS Modifiers (Adjust Level Up/Down)</b>', hdr_style)],
[Paragraph(
'<b>First-Order (Chief-Complaint Based):</b> Mechanism of injury, acuity of onset, '
'severity of pain/discomfort (NRS ≥8 → consider upgrading by 1 level)<br/><br/>'
'<b>Second-Order (Adding Context):</b> Age extremes (<2 yr or >70 yr), '
'immunocompromised state, mechanism, co-morbidities, patient distress<br/><br/>'
'<b>Key Rule:</b> Reassessment at mandated intervals is REQUIRED. '
'If patient deteriorates → upgrade immediately. Document reassessment time.',
small_style)],
]
ctas_mod_tbl = Table(ctas_mod_data, colWidths=[182*mm])
ctas_mod_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), TEAL),
('BACKGROUND', (0,1), (-1,1), HexColor('#E8F4FD')),
('GRID', (0,0), (-1,-1), 0.4, HexColor('#AABBCC')),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 7),
('RIGHTPADDING', (0,0), (-1,-1), 7),
]))
# ── Clinical tips box ─────────────────────────────────────────────────────────
tips_data = [
[Paragraph('<b>Clinical Decision Tips — ESI</b>', hdr_style),
Paragraph('<b>Clinical Decision Tips — CTAS</b>', hdr_style)],
[Paragraph(
'• <b>Disabling deficit</b> at any NIHSS → Level 2 (do not rely solely on NIHSS)<br/>'
'• Severe pain (NRS ≥8) alone → consider Level 2<br/>'
'• Normal vitals do NOT rule out Level 2 (high-risk history trumps)<br/>'
'• "Resources" = distinct services ordered (one CBC = 1, CBC+BMP = still 1 lab draw)<br/>'
'• CT scan = 1 resource; CT + labs = 2 resources = Level 3 minimum<br/>'
'• Confused/altered → automatically Level 2<br/>'
'• Child with fever: apply paediatric danger vital thresholds',
small_style),
Paragraph(
'• Use <b>first positive discriminator</b> — do not skip down flowchart<br/>'
'• Age <2 or >70 → consider upgrading one level<br/>'
'• Missed reassessment = patient safety risk — document every interval<br/>'
'• Pain ≥8/10 → upgrade by 1 level as first-order modifier<br/>'
'• Immunocompromised patients (HIV, chemo, transplant) → upgrade<br/>'
'• If in doubt between two levels → always assign the <b>higher acuity</b> level<br/>'
'• Sepsis criteria present → Level 2 at minimum',
small_style)],
]
tips_tbl = Table(tips_data, colWidths=[91*mm, 91*mm])
tips_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (0,0), ORANGE),
('BACKGROUND', (1,0), (1,0), TEAL),
('BACKGROUND', (0,1), (0,1), HexColor('#FFF3E0')),
('BACKGROUND', (1,1), (1,1), HexColor('#E0F2FF')),
('GRID', (0,0), (-1,-1), 0.4, HexColor('#AABBCC')),
('VALIGN', (0,0), (-1,-1), 'TOP'),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 6),
('RIGHTPADDING', (0,0), (-1,-1), 6),
]))
# ── Level-to-Level concordance table ─────────────────────────────────────────
concordance_data = [
[Paragraph('<b>ESI Level</b>', hdr_style),
Paragraph('<b>Approximate CTAS Equivalent</b>', hdr_style),
Paragraph('<b>Notes on Differences</b>', hdr_style)],
['Level 1 🔴', 'Level 1 🔴', 'Identical — immediate life threat'],
['Level 2 🟠', 'Level 2 🟠', 'ESI 2 is slightly broader (includes any high-risk without immediate need)'],
['Level 3 🟡', 'Level 2–3 🟠🟡', 'CTAS uses modifiers; ESI 3 with danger vitals → CTAS 2'],
['Level 4 🟢', 'Level 4 🟢', 'Very similar — one resource / less urgent'],
['Level 5 🔵', 'Level 5 🔵', 'Identical — no resources / non-urgent'],
]
concordance_tbl = Table(concordance_data, colWidths=[35*mm, 55*mm, 92*mm])
concordance_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), NAVY),
('BACKGROUND', (0,1), (-1,1), L_RED),
('BACKGROUND', (0,2), (-1,2), L_ORANGE),
('BACKGROUND', (0,3), (-1,3), L_YELLOW),
('BACKGROUND', (0,4), (-1,4), L_GREEN),
('BACKGROUND', (0,5), (-1,5), L_BLUE),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTNAME', (0,1), (0,-1), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,-1), 8),
('GRID', (0,0), (-1,-1), 0.4, HexColor('#AABBCC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 5),
('RIGHTPADDING', (0,0), (-1,-1), 5),
]))
# ── Footer ────────────────────────────────────────────────────────────────────
footer_data = [[
Paragraph(
'ESI: Emergency Severity Index (AHRQ, USA) | CTAS: Canadian Triage and Acuity Scale (CAEP) | '
'Pocket guide for clinical reference only — always apply clinical judgement | '
'Compiled June 2026',
note_style)
]]
footer_tbl = Table(footer_data, colWidths=[182*mm])
footer_tbl.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), LIGHT_BG),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 6),
('RIGHTPADDING', (0,0), (-1,-1), 6),
('BOX', (0,0), (-1,-1), 0.5, HexColor('#AABBCC')),
]))
# ── Assemble story ────────────────────────────────────────────────────────────
story = [
title_tbl,
Spacer(1, 4*mm),
# Page 1: ESI
KeepTogether([
banner('1. ESI — Emergency Severity Index (USA)', ORANGE),
Spacer(1, 2*mm),
banner('1a ESI Decision Algorithm', TEAL),
Spacer(1, 1*mm),
esi_algo_tbl,
Spacer(1, 2*mm),
]),
KeepTogether([
banner('1b ESI — Full Level Details', TEAL),
Spacer(1, 1*mm),
esi_levels_tbl,
Spacer(1, 2*mm),
]),
KeepTogether([
banner('1c ESI — Vital Sign Danger Thresholds (trigger Level 2 upgrade)', TEAL),
Spacer(1, 1*mm),
vitals_tbl,
Spacer(1, 3*mm),
]),
# Page 2: CTAS
KeepTogether([
banner('2. CTAS — Canadian Triage and Acuity Scale', ORANGE),
Spacer(1, 2*mm),
banner('2a CTAS Level Reference', TEAL),
Spacer(1, 1*mm),
ctas_tbl,
Spacer(1, 2*mm),
]),
KeepTogether([
banner('2b CTAS — Modifiers & Reassessment Rules', TEAL),
Spacer(1, 1*mm),
ctas_mod_tbl,
Spacer(1, 3*mm),
]),
# Comparison section
KeepTogether([
banner('3. ESI vs CTAS — Head-to-Head Comparison', NAVY),
Spacer(1, 1*mm),
compare_tbl,
Spacer(1, 3*mm),
]),
KeepTogether([
banner('4. Level Concordance (ESI ↔ CTAS)', NAVY),
Spacer(1, 1*mm),
concordance_tbl,
Spacer(1, 3*mm),
]),
KeepTogether([
banner('5. Clinical Tips at the Triage Desk', NAVY),
Spacer(1, 1*mm),
tips_tbl,
Spacer(1, 3*mm),
]),
footer_tbl,
]
doc.build(story)
print(f"PDF created: {OUTPUT}")
python3 /home/daytona/workspace/triage-guide/generate_pocket_guide.py
ls -lh /home/daytona/workspace/triage-guide/
ESI vs CTAS Pocket Guide
PDF Document · PDF
| Section | Content |
|---|---|
| 1. ESI Decision Algorithm | 3-step flowchart (life threat → high risk → resources) with colour coding |
| 2. ESI Full Level Details | All 5 levels with criteria, wait times, and clinical examples |
| 3. ESI Vital Sign Thresholds | Age-stratified danger vitals that trigger Level 2 upgrade |
| 4. CTAS Level Reference | All 5 levels with time-to-physician, mandatory reassessment intervals, examples |
| 5. CTAS Modifiers | First-order and second-order modifier rules + reassessment documentation note |
| 6. Head-to-Head Comparison | 12-row feature comparison (origin, basis, reliability, strengths, weaknesses) |
| 7. Level Concordance | ESI ↔ CTAS equivalent mapping with notes on key differences |
| 8. Clinical Tips at the Desk | 7 tips each for ESI and CTAS, side by side |