Ecg


| Waveform/Interval | Represents | Normal Value |
|---|---|---|
| P wave | Atrial depolarization | Duration <120 ms; amplitude <2.5 mm |
| PR interval | AV conduction time (SA node to ventricular muscle) | 120-200 ms (3-5 small boxes) |
| QRS complex | Ventricular depolarization | <100 ms (up to 110 ms in some) |
| ST segment | Ventricular plateau phase (isoelectric) | Isoelectric (at baseline) |
| T wave | Ventricular repolarization (active recovery) | Positive in most leads |
| QT interval | Total ventricular depolarization + repolarization | Corrected QTc <440 ms (men), <460 ms (women) |
| U wave | Possibly late ventricular repolarization / Purkinje repolarization | Small, follows T wave |
| J point | QRS-ST junction | At isoelectric line |
| Lead | View |
|---|---|
| I | Left lateral |
| II | Inferior (most used for rhythm strips) |
| III | Inferior |
| aVR | Right shoulder (right atrium) - normally negative |
| aVL | Left lateral |
| aVF | Inferior (foot) |

| Lead | View |
|---|---|
| V1-V2 | Right ventricle / septal |
| V3-V4 | Anterior LV |
| V5-V6 | Lateral LV |

| Axis | Degrees | Significance |
|---|---|---|
| Normal | -30° to +100° | Normal |
| Left axis deviation (LAD) | More negative than -30° | LBBB, left anterior fascicular block, inferior MI, LVH |
| Right axis deviation (RAD) | More positive than +90 to +100° | RVH, RBBB, left posterior fascicular block, lateral MI, dextrocardia |
| Cause | Pattern |
|---|---|
| STEMI | Regional (follows coronary territory), convex/tombstone shape |
| Pericarditis | Diffuse, saddle-shaped; PR depression |
| Early repolarization | Benign variant, notch at J point, common in young males |
| Brugada syndrome | Coved ST elevation V1-V3, RBBB-like morphology |
| LVH/LBBB | Discordant ST changes (opposite to main QRS deflection) |
| Hyperkalemia | May cause V1-V3 elevation |
Compare with any previous ECGs - this is invaluable.
| Finding | Meaning |
|---|---|
| Peaked P >2.5 mm in II ("P pulmonale") | Right atrial enlargement |
| Notched/broad P >120 ms in II ("P mitrale") | Left atrial enlargement |
| No P waves | Atrial fibrillation (irregularly irregular), junctional rhythm |
| Retrograde P (after QRS) | Junctional rhythm |
| P waves not related to QRS | Complete (3rd degree) AV block |
| Condition | Key ECG Finding |
|---|---|
| Anterior STEMI | ST elevation V1-V4, Q waves |
| Inferior STEMI | ST elevation II, III, aVF |
| Lateral STEMI | ST elevation I, aVL, V5-V6 |
| Posterior MI | Tall R + ST depression V1-V2 (mirror image) |
| Atrial fibrillation | No P waves, irregularly irregular RR |
| Complete heart block | P-QRS dissociation, slow ventricular rate |
| LBBB | Broad QRS, notched "M" in V5-V6, QS in V1 |
| RBBB | Broad QRS, RSR' ("bunny ears") in V1, wide S in I and V6 |
| Hyperkalemia | Peaked T → wide QRS → sine wave |
| PE (S1Q3T3) | S wave in I, Q wave in III, T inversion in III |
| Pericarditis | Diffuse ST elevation + PR depression |
| Digoxin effect | Sagging ST depression ("reverse tick") |
A patient comes to opd with fever. How to proceed explain with flowchart systematically
PATIENT PRESENTS WITH FEVER (Temp ≥ 38°C / 100.4°F)
│
▼
┌─────────────────────────────────┐
│ STEP 1: IMMEDIATE TRIAGE │
│ Is patient haemodynamically │
│ stable? Any red flags? │
└─────────────────────────────────┘
│
┌────────┴────────┐
▼ ▼
RED FLAGS STABLE
PRESENT → STEP 2
│
▼
EMERGENCY REFERRAL / ADMIT
(Sepsis protocol, IV access,
cultures, empirical antibiotics)
│
▼
┌─────────────────────────────────┐
│ STEP 2: DETAILED HISTORY │
└─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ STEP 3: PHYSICAL EXAMINATION │
└─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ STEP 4: CLASSIFY FEVER TYPE │
└─────────────────────────────────┘
│
┌─────────┼──────────┐
▼ ▼ ▼
SHORT PROLONGED FEVER OF
FEVER (>1 week) UNKNOWN
(<1 wk) ORIGIN (FUO)
│ │ │
▼ ▼ ▼
STEP 5: STEP 6: STEP 7:
FOCUSED EXTENDED SYSTEMATIC
WORKUP WORKUP FUO WORKUP
│
▼
┌─────────────────────────────────┐
│ STEP 8: TREATMENT DECISION │
└─────────────────────────────────┘
| Red Flag | Concern |
|---|---|
| HR >120, SBP <90 mmHg | Septic shock |
| RR >30/min, SpO2 <94% | Sepsis, severe pneumonia |
| Altered consciousness/confusion | Meningitis, encephalitis, septic encephalopathy |
| Petechiae/purpuric rash | Meningococcemia |
| Stiff neck + fever + photophobia | Meningitis (meningeal triad) |
| Fever + jaundice + RUQ pain (Charcot's triad) | Ascending cholangitis |
| Fever in immunocompromised / neutropenic patient | Neutropenic fever (medical emergency) |
| Fever + new cardiac murmur | Infective endocarditis |
| Unresponsive to antipyretics, rapidly rising temp | Consider sepsis / malignant hyperthermia |
If any red flag is present → Stabilize, admit, start sepsis workup immediately. Do NOT send home.
| Pattern | Description | Classic Association |
|---|---|---|
| Continuous / Sustained | Persistent, little variation (<1°C) | Typhoid fever, lobar pneumonia, UTI |
| Remittent | Fluctuates >1°C but never reaches normal | Most bacterial infections |
| Intermittent (Quotidian) | Spikes then returns to normal | Malaria (P. vivax = 48h), pyogenic abscess, miliary TB |
| Tertian | Fever every 3rd day | P. vivax / ovale malaria |
| Quartan | Fever every 4th day | P. malariae |
| Hectic / Septic | Wide swings with drenching sweats | Pyogenic abscesses, infective endocarditis |
| Pel-Ebstein | Weeks of fever alternating weeks of no fever | Hodgkin's lymphoma |
| Relapsing | Recurrent episodes | Brucellosis, Borrelia |
| System | Symptoms to Ask | Suggests |
|---|---|---|
| Respiratory | Cough, sputum, dyspnoea, pleuritic chest pain | Pneumonia, TB, pleural effusion |
| GI | Nausea, vomiting, diarrhoea, pain, jaundice | Gastroenteritis, hepatitis, typhoid, cholangitis |
| Urinary | Dysuria, frequency, loin pain, haematuria | UTI, pyelonephritis |
| CNS | Headache, neck stiffness, photophobia, confusion | Meningitis, encephalitis |
| Skin | Rash, ulcers, swellings | Dengue, typhus, viral exanthem, cellulitis |
| Musculoskeletal | Joint pains, myalgia, bone pain | Rheumatic fever, septic arthritis, osteomyelitis |
| Lymph nodes | Lymphadenopathy | Lymphoma, HIV, EBV, TB, leukemia |
| Cardiac | Chest pain, palpitations, new murmur | Endocarditis, myocarditis |
| Night sweats | Drenching | TB, lymphoma, HIV, brucellosis |
| Weight loss | Unexplained >10% | Malignancy, TB, HIV |
| Region | What to Look For | Significance |
|---|---|---|
| Skin | Rash type, distribution, petechiae, eschar, jaundice | Viral exanthem, meningococcemia, typhus (eschar), rickettsial |
| Eyes | Icterus, conjunctival suffusion, Roth spots | Hepatitis, leptospirosis, endocarditis |
| ENT | Tonsillar exudate, pharyngeal erythema, sinus tenderness | Strep throat, EBV, sinusitis |
| Neck | Meningism (Kernig's, Brudzinski's), lymphadenopathy, thyroid | Meningitis, lymphoma, thyroiditis |
| Chest | Dullness, crepitations, bronchial breathing, friction rub | Pneumonia, pleural effusion, pericarditis |
| Abdomen | Hepatomegaly, splenomegaly, tenderness, rigidity, guarding | Malaria, typhoid, hepatitis, abscess |
| CVS | New murmur, pericardial rub | Endocarditis, pericarditis |
| Joints | Swelling, warmth, tenderness | Septic arthritis, rheumatic fever, reactive arthritis |
| Genitourinary | Costovertebral angle tenderness, urethral discharge | Pyelonephritis, STI |
| Neurological | Focal deficits, consciousness level | CNS infection, encephalitis |
Duration of fever?
│
─────┴─────────────────────────────────────────
│ │ │
< 1 week 1-3 weeks > 3 weeks
"Acute Fever" "Subacute Fever" "Prolonged / FUO"
│ │ │
Common causes: Consider: See FUO criteria
- Viral URTI - Typhoid (Harrison's 22E)
- Malaria - Brucellosis
- Dengue - TB
- UTI - Infective
- Bacterial endocarditis
pneumonia - Malignancy
- Gastroenteritis - Connective tissue
disease
| Test | Rationale |
|---|---|
| CBC with differential | Leukocytosis (bacterial), leukopenia (viral/typhoid), eosinophilia (parasites/allergy), atypical lymphocytes (EBV) |
| ESR / CRP | Nonspecific inflammatory marker; very elevated in bacterial/autoimmune |
| Peripheral blood smear (if travel history) | Malaria |
| Urine routine + culture | Rule out UTI/pyelonephritis |
| Blood culture x2 (pre-antibiotic) | Bacteremia, typhoid, endocarditis |
| Widal test / Typhidot | Enteric fever (in endemic areas) |
| Dengue NS1 antigen / IgM (if endemic, early) | Dengue fever |
| Chest X-ray | Pneumonia, TB, lymphoma, pleural effusion |
| LFT / RFT | Hepatitis, renal involvement in sepsis/leptospirosis |
| Blood glucose | Uncontrolled DM (immunosuppressed host) |
| Serum electrolytes | Dehydration from fever |
| Clinical Suspicion | Additional Tests |
|---|---|
| TB | Mantoux test, sputum AFB, ADA, HRCT chest, GeneXpert |
| Malaria | Thick & thin films, malaria RDT, PCR |
| HIV | HIV ELISA, CD4 count, viral load |
| Typhoid | Blood culture (gold standard), Widal, Typhidot IgM |
| Dengue | NS1 (day 1-5), IgM/IgG (day 5 onwards), CBC for thrombocytopenia |
| Leptospirosis | MAT (microscopic agglutination test), IgM ELISA |
| EBV / CMV | Monospot, EBV IgM, CMV IgM |
| Infective endocarditis | Echocardiography (TTE/TEE), serial blood cultures |
| Urinary source | Urine C&S, renal ultrasound |
| CNS infection | LP (CSF analysis: cell count, protein, glucose, culture, PCR) |
| Autoimmune / Rheumatological | ANA, anti-dsDNA, ANCA, complement levels, RF |
| Malignancy | LDH, uric acid, PET-CT, bone marrow biopsy |
CAUSES OF FEVER
│
─────┼──────────────────────────────────────
│ │ │ │
INFECTIOUS NON-INFECTIOUS MALIGNANCY MISCELLANEOUS
(50-60% INFLAMMATORY (10-20% (Drug fever,
in tropics) DISEASE (NIID) in West) factitious,
│ (20-30% thermoregulatory)
│ in West)
│
Common:
• Bacterial: Typhoid, TB, brucellosis,
endocarditis, pyelonephritis, abscess,
pneumonia, meningitis
• Viral: Dengue, malaria, EBV, CMV,
hepatitis A/B/E, HIV
• Parasitic: Malaria, visceral leishmaniasis
• Fungal: Histoplasma, Candida
(immunocompromised)
NIID:
• SLE, adult Still's disease, vasculitis
• IBD, sarcoidosis
• Rheumatoid arthritis
Malignancy:
• Lymphoma (Hodgkin's / NHL)
• Leukemia, renal cell carcinoma
• Hepatocellular carcinoma
Drug Fever:
• Beta-lactams, sulfonamides,
phenytoin, allopurinol, heparin
(fever disappears 72h after stopping drug)
FUO CONFIRMED
│
▼
Stage 1: Repeat detailed history + examine + basic labs
(Ensure no obvious diagnosis missed)
│
▼
Stage 2: Second-tier investigations
- CT chest/abdomen/pelvis
- PET-CT (most sensitive for occult infection, malignancy)
- Echocardiography (TEE if endocarditis suspected)
- Bone marrow biopsy (pancytopenia, suspected malignancy/TB)
- Temporal artery biopsy (elderly, high ESR → GCA)
- Specific serologies: ANA, ANCA, cryoglobulins, Q fever IFA
│
▼
Stage 3: Invasive procedures if still undiagnosed
- Liver biopsy (granulomatous hepatitis)
- Lymph node biopsy
- Laparoscopic evaluation
│
▼
Stage 4: Watchful waiting (if stable, no diagnosis)
- Avoid empirical antibiotics/steroids unless life-threatening
- Recheck history, examine again, repeat cultures
DIAGNOSIS ESTABLISHED?
│
──────┴──────────────
│ │
YES NO
│ │
SPECIFIC EMPIRICAL
TREATMENT TREATMENT
│ (if unstable/toxic)
▼ │
• Bacterial → appropriate ▼
antibiotics (culture-guided) Antipyretics (paracetamol
• Viral → supportive ± 15 mg/kg or 500-1000 mg)
antivirals if indicated + Hydration
• Malaria → ACT or + Monitor closely
chloroquine (P. vivax) + Watchful waiting if stable
• TB → RHEZ (DOTS)
• Autoimmune → steroids/
DMARDs
• Malignancy → oncology
referral
Fever in OPD
│
├─► RED FLAGS? ──YES──► EMERGENCY MANAGEMENT
│
├─► DETAILED HISTORY (duration, pattern, associated symptoms,
│ travel, exposures, medications, immune status)
│
├─► PHYSICAL EXAM (vitals, skin, ENT, chest, abdomen, CNS, joints)
│
├─► CLASSIFY: Acute (<1wk) / Subacute (1-3wk) / FUO (>3wk)
│
├─► TIER 1 INVESTIGATIONS (CBC, CRP, blood culture, UA, CXR,
│ malaria smear, dengue antigen if endemic)
│
├─► TARGETED TESTS based on clinical clues
│
├─► ESTABLISH DIAGNOSIS
│ │
│ ┌────┴────┐
│ YES NO
│ │ │
▼ ▼ ▼
SPECIFIC RX WATCHFUL WAITING
+ ANTIPYRETICS
+ REVISIT HISTORY
+ ESCALATE WORKUP
Clinical Pearl (Harrison's): The most valuable step in evaluating any fever is a detailed history and physical examination. Most FUOs represent atypical presentations of common diseases, not rare diagnoses. Always compare prior ECGs/labs when available. Avoid empirical antibiotics in stable patients without a clear source - they obscure the diagnostic picture and promote resistance.
Generate a clinical flowchart PDF summarizing this fever workup
mkdir -p /home/daytona/workspace/fever-flowchart && ls /home/daytona/workspace/fever-flowchart/
~/fever-flowchart/generate_fever_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import KeepTogether
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon, Arrow
from reportlab.graphics import renderPDF
from reportlab.platypus import Flowable
import textwrap
# ── colour palette ──────────────────────────────────────────────────────────
RED = colors.HexColor("#C0392B")
ORANGE = colors.HexColor("#E67E22")
TEAL = colors.HexColor("#1A7A6E")
BLUE = colors.HexColor("#2471A3")
PURPLE = colors.HexColor("#7D3C98")
DARK_BLUE = colors.HexColor("#1B2631")
LIGHT_BLUE = colors.HexColor("#D6EAF8")
LIGHT_RED = colors.HexColor("#FADBD8")
LIGHT_TEAL = colors.HexColor("#D0ECE7")
LIGHT_ORANGE = colors.HexColor("#FDEBD0")
LIGHT_PURPLE = colors.HexColor("#E8DAEF")
LIGHT_GREY = colors.HexColor("#F2F3F4")
DARK_GREY = colors.HexColor("#2C3E50")
WHITE = colors.white
GOLD = colors.HexColor("#D4AC0D")
PAGE_W, PAGE_H = A4 # 595 x 842 pts
# ── custom flowable: arrow-connected box ─────────────────────────────────────
class FlowBox(Flowable):
"""A single rounded box with an optional downward arrow below it."""
def __init__(self, text, bg, fg=WHITE, width=None, height=40,
arrow=True, radius=6, font_size=9, bold=False):
Flowable.__init__(self)
self.text = text
self.bg = bg
self.fg = fg
self.bw = width or (PAGE_W - 80)
self.bh = height
self.arrow = arrow
self.radius = radius
self.font_size = font_size
self.bold = bold
self.width = self.bw
self.height = self.bh + (14 if arrow else 0)
def draw(self):
c = self.canv
# box
c.setFillColor(self.bg)
c.setStrokeColor(colors.HexColor("#BDC3C7"))
c.roundRect(0, 14 if self.arrow else 0,
self.bw, self.bh, self.radius, fill=1, stroke=1)
# text
c.setFillColor(self.fg)
font = "Helvetica-Bold" if self.bold else "Helvetica"
c.setFont(font, self.font_size)
lines = self.text.split("\n")
total_h = len(lines) * (self.font_size + 2)
y_start = (14 if self.arrow else 0) + self.bh/2 + total_h/2 - self.font_size
for line in lines:
c.drawCentredString(self.bw/2, y_start, line)
y_start -= (self.font_size + 2)
# arrow
if self.arrow:
c.setStrokeColor(DARK_GREY)
c.setFillColor(DARK_GREY)
c.setLineWidth(1.5)
cx = self.bw / 2
c.line(cx, 13, cx, 2)
# arrowhead
c.setFillColor(DARK_GREY)
p = c.beginPath()
p.moveTo(cx, 0)
p.lineTo(cx-4, 6)
p.lineTo(cx+4, 6)
p.close()
c.drawPath(p, fill=1, stroke=0)
class DiamondBox(Flowable):
"""Decision diamond."""
def __init__(self, text, bg=ORANGE, fg=WHITE, width=None, height=60, arrow=True):
Flowable.__init__(self)
self.text = text
self.bg = bg
self.fg = fg
self.bw = width or (PAGE_W - 80)
self.bh = height
self.arrow = arrow
self.width = self.bw
self.height = self.bh + (14 if arrow else 0)
def draw(self):
c = self.canv
bw, bh = self.bw, self.bh
base_y = 14 if self.arrow else 0
mx = bw / 2
# diamond polygon
c.setFillColor(self.bg)
c.setStrokeColor(colors.HexColor("#BDC3C7"))
c.setLineWidth(1)
p = c.beginPath()
p.moveTo(mx, base_y + bh) # top
p.lineTo(bw, base_y + bh/2) # right
p.lineTo(mx, base_y) # bottom
p.lineTo(0, base_y + bh/2) # left
p.close()
c.drawPath(p, fill=1, stroke=1)
# text
c.setFillColor(self.fg)
c.setFont("Helvetica-Bold", 9)
lines = self.text.split("\n")
y0 = base_y + bh/2 + (len(lines)-1)*6
for line in lines:
c.drawCentredString(mx, y0, line)
y0 -= 13
# arrow
if self.arrow:
c.setStrokeColor(DARK_GREY)
c.setFillColor(DARK_GREY)
c.setLineWidth(1.5)
cx = bw / 2
c.line(cx, 13, cx, 2)
p2 = c.beginPath()
p2.moveTo(cx, 0); p2.lineTo(cx-4, 6); p2.lineTo(cx+4, 6); p2.close()
c.drawPath(p2, fill=1, stroke=0)
class TwoColumnBox(Flowable):
"""Two side-by-side coloured boxes (YES / NO branches)."""
def __init__(self, left_text, right_text,
left_bg=RED, right_bg=TEAL,
left_fg=WHITE, right_fg=WHITE,
width=None, height=50, arrow=True):
Flowable.__init__(self)
self.lt = left_text; self.rt = right_text
self.lb = left_bg; self.rb = right_bg
self.lf = left_fg; self.rf = right_fg
self.bw = width or (PAGE_W - 80)
self.bh = height
self.arrow = arrow
self.width = self.bw
self.height = self.bh + (14 if arrow else 0)
def _draw_half(self, c, x, w, h, base_y, bg, fg, text, radius=6):
c.setFillColor(bg)
c.setStrokeColor(colors.HexColor("#BDC3C7"))
c.roundRect(x, base_y, w, h, radius, fill=1, stroke=1)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", 8)
lines = text.split("\n")
y0 = base_y + h/2 + (len(lines)-1)*5
for line in lines:
c.drawCentredString(x + w/2, y0, line)
y0 -= 11
def draw(self):
c = self.canv
base_y = 14 if self.arrow else 0
half = (self.bw - 6) / 2
self._draw_half(c, 0, half, self.bh, base_y, self.lb, self.lf, self.lt)
self._draw_half(c, half + 6, half, self.bh, base_y, self.rb, self.rf, self.rt)
if self.arrow:
for cx in [half/2, half + 6 + half/2]:
c.setStrokeColor(DARK_GREY); c.setFillColor(DARK_GREY)
c.setLineWidth(1.5)
c.line(cx, 13, cx, 2)
p = c.beginPath()
p.moveTo(cx,0); p.lineTo(cx-4,6); p.lineTo(cx+4,6); p.close()
c.drawPath(p, fill=1, stroke=0)
class SectionHeader(Flowable):
"""Full-width coloured banner for section titles."""
def __init__(self, number, title, bg=DARK_BLUE, fg=WHITE, width=None):
Flowable.__init__(self)
self.number = number
self.title = title
self.bg = bg
self.fg = fg
self.bw = width or (PAGE_W - 80)
self.width = self.bw
self.height = 28
def draw(self):
c = self.canv
c.setFillColor(self.bg)
c.roundRect(0, 0, self.bw, 28, 5, fill=1, stroke=0)
# number badge
c.setFillColor(GOLD)
c.circle(18, 14, 11, fill=1, stroke=0)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 11)
c.drawCentredString(18, 10, str(self.number))
# title
c.setFillColor(self.fg)
c.setFont("Helvetica-Bold", 11)
c.drawString(38, 10, self.title)
def build_pdf(path):
doc = SimpleDocTemplate(
path, pagesize=A4,
leftMargin=30, rightMargin=30,
topMargin=28, bottomMargin=28
)
styles = getSampleStyleSheet()
BODY_W = PAGE_W - 60 # usable width
def style(name="Normal", size=8, color=DARK_GREY, align=TA_LEFT,
bold=False, space_before=2, space_after=2):
return ParagraphStyle(
name, parent=styles["Normal"],
fontSize=size, textColor=color,
alignment=align, leading=size+3,
fontName="Helvetica-Bold" if bold else "Helvetica",
spaceBefore=space_before, spaceAfter=space_after
)
elems = []
# ── TITLE BANNER ─────────────────────────────────────────────────────────
title_tbl = Table(
[[Paragraph(
"<font color='white'><b>CLINICAL APPROACH TO FEVER IN OPD</b></font>",
style(size=16, color=WHITE, align=TA_CENTER, bold=True)
)],
[Paragraph(
"<font color='#D6EAF8'>A Systematic Flowchart | Based on Harrison's Principles of Internal Medicine 22E (2025)</font>",
style(size=8, color=LIGHT_BLUE, align=TA_CENTER)
)]],
colWidths=[BODY_W]
)
title_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
("ROUNDEDCORNERS", [8]),
("TOPPADDING", (0,0), (-1,-1), 12),
("BOTTOMPADDING",(0,0),(-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 12),
]))
elems.append(title_tbl)
elems.append(Spacer(1, 8))
# definition strip
def_tbl = Table(
[[Paragraph(
"Fever = Core body temperature <b>≥ 38.0°C (100.4°F)</b> | "
"Normal oral temp: 36.1–37.2°C | "
"Hyperpyrexia: >41.5°C (emergency)",
style(size=8, color=DARK_GREY, align=TA_CENTER)
)]],
colWidths=[BODY_W]
)
def_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BLUE),
("ROUNDEDCORNERS", [5]),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0),(-1,-1), 6),
]))
elems.append(def_tbl)
elems.append(Spacer(1, 10))
# ── STEP 1: TRIAGE ───────────────────────────────────────────────────────
elems.append(SectionHeader(1, "IMMEDIATE TRIAGE — Is the patient stable?", bg=DARK_BLUE))
elems.append(Spacer(1, 5))
elems.append(DiamondBox("RED FLAGS present?", bg=ORANGE, height=52))
elems.append(Spacer(1, 3))
elems.append(TwoColumnBox(
"YES → EMERGENCY\nAdmit / Refer\nSepsis protocol\nIV access + cultures\nEmpirical antibiotics",
"NO → Stable Patient\nProceed to\ndetailed workup",
left_bg=RED, right_bg=TEAL, height=52
))
# red flags table
elems.append(Spacer(1, 6))
rf_data = [
[Paragraph("<b>Red Flag</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Concern</b>", style(8, WHITE, bold=True))],
["HR >120, SBP <90 mmHg", "Septic shock"],
["RR >30/min, SpO₂ <94%", "Severe pneumonia / Sepsis"],
["Altered consciousness / confusion","Meningitis / Encephalopathy"],
["Petechiae / purpuric rash", "Meningococcemia"],
["Neck stiffness + photophobia", "Bacterial meningitis"],
["Fever + jaundice + RUQ pain", "Ascending cholangitis"],
["Immunocompromised / neutropenic", "Neutropenic fever (emergency)"],
["Fever + new cardiac murmur", "Infective endocarditis"],
]
rf_tbl = Table(rf_data, colWidths=[BODY_W*0.45, BODY_W*0.55])
rf_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), RED),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8),
("BACKGROUND", (0,1), (-1,-1), LIGHT_RED),
("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.HexColor("#FDEDEC"), LIGHT_RED]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#E8DAEF")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
elems.append(rf_tbl)
elems.append(Spacer(1, 10))
# ── STEP 2: HISTORY ──────────────────────────────────────────────────────
elems.append(SectionHeader(2, "DETAILED HISTORY", bg=BLUE))
elems.append(Spacer(1, 5))
hist_data = [
[Paragraph("<b>Domain</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Key Questions</b>", style(8, WHITE, bold=True))],
["Fever pattern", "Onset, duration, degree, diurnal variation, rigors, response to antipyretics"],
["Respiratory", "Cough, sputum colour, dyspnoea, pleuritic chest pain"],
["GI", "Nausea, vomiting, diarrhoea, abdominal pain, jaundice, change in stool colour"],
["Urinary", "Dysuria, frequency, urgency, loin pain, haematuria"],
["CNS", "Headache, neck stiffness, photophobia, confusion, seizures"],
["Skin", "Rash (type, distribution, progression), ulcers, swellings"],
["MSK", "Joint swelling/pain, myalgia, bone pain"],
["Constitutional", "Night sweats, weight loss (>10%), anorexia, fatigue"],
["Travel history", "Malaria zone, typhoid-endemic area, dengue belt, recent international travel"],
["Exposures", "Animal contact, tick/mosquito bites, raw food, sick contacts, sexual history"],
["Medications", "Any new drug in last 4 weeks (drug fever), immunosuppressants, steroids"],
["PMH / Immune", "HIV, diabetes, malignancy, prosthetic valves, prior TB/malaria, transplant"],
["Vaccination", "Typhoid, Hep A/B, meningococcal, influenza status"],
]
hist_tbl = Table(hist_data, colWidths=[BODY_W*0.22, BODY_W*0.78])
hist_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), BLUE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 7.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LIGHT_BLUE, colors.HexColor("#EBF5FB")]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#AED6F1")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), BLUE),
]))
elems.append(hist_tbl)
elems.append(Spacer(1, 10))
# ── STEP 3: FEVER PATTERNS ───────────────────────────────────────────────
elems.append(SectionHeader(3, "FEVER PATTERNS (Temperature Curve)", bg=PURPLE))
elems.append(Spacer(1, 5))
fp_data = [
[Paragraph("<b>Pattern</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Description</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Classic Association</b>", style(8, WHITE, bold=True))],
["Continuous / Sustained", "Persistent; variation <1°C; never normal", "Typhoid, lobar pneumonia, UTI"],
["Remittent", "Fluctuates >1°C; never reaches normal", "Most bacterial infections"],
["Intermittent", "Spikes then returns to normal daily", "Malaria (P. vivax 48h), abscesses"],
["Tertian", "Fever every 3rd day", "P. vivax / P. ovale malaria"],
["Quartan", "Fever every 4th day", "P. malariae malaria"],
["Hectic / Septic", "Wide swings + drenching sweats", "Pyogenic abscesses, endocarditis"],
["Pel–Ebstein", "Weeks of fever alternating with afebrile weeks","Hodgkin's lymphoma"],
["Relapsing", "Recurrent febrile episodes with remission", "Brucellosis, Borrelia, malaria"],
]
fp_tbl = Table(fp_data, colWidths=[BODY_W*0.22, BODY_W*0.40, BODY_W*0.38])
fp_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), PURPLE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 7.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LIGHT_PURPLE, colors.HexColor("#F5EEF8")]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#D7BDE2")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), PURPLE),
]))
elems.append(fp_tbl)
elems.append(Spacer(1, 10))
# ── STEP 4: PHYSICAL EXAMINATION ─────────────────────────────────────────
elems.append(SectionHeader(4, "PHYSICAL EXAMINATION", bg=TEAL))
elems.append(Spacer(1, 5))
pe_data = [
[Paragraph("<b>System</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Key Findings</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Significance</b>", style(8, WHITE, bold=True))],
["Vitals", "Temp, HR, BP, RR, SpO₂; pulse–temp dissociation", "Typhoid if HR low despite high fever"],
["General", "Toxic vs. well appearance, pallor, icterus, cyanosis", "Severity assessment"],
["Skin", "Rash type & distribution, petechiae, eschar, jaundice","Meningococcemia, typhus, viral exanthem"],
["Eyes", "Icterus, conjunctival suffusion, Roth spots", "Hepatitis, leptospirosis, endocarditis"],
["ENT", "Tonsillar exudate, pharyngeal erythema, sinus tender.", "Strep, EBV, sinusitis"],
["Neck", "Kernig's/Brudzinski's, lymphadenopathy, thyroid", "Meningitis, lymphoma, thyroiditis"],
["Chest / CVS", "Crepitations, bronchial breathing, new murmur, rub", "Pneumonia, endocarditis, pericarditis"],
["Abdomen", "Hepatomegaly, splenomegaly, tenderness, rigidity", "Malaria, typhoid, hepatitis, abscess"],
["Joints", "Swelling, warmth, tenderness", "Septic arthritis, rheumatic fever"],
["GU", "CVA tenderness, urethral discharge", "Pyelonephritis, STI"],
["Neuro", "Focal deficits, consciousness (GCS), fundoscopy", "Encephalitis, meningitis"],
]
pe_tbl = Table(pe_data, colWidths=[BODY_W*0.16, BODY_W*0.43, BODY_W*0.41])
pe_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 7.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LIGHT_TEAL, colors.HexColor("#E8F8F5")]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#A9DFBF")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), TEAL),
]))
elems.append(pe_tbl)
elems.append(Spacer(1, 10))
# ── STEP 5: CLASSIFY FEVER ───────────────────────────────────────────────
elems.append(SectionHeader(5, "CLASSIFY THE FEVER BY DURATION", bg=colors.HexColor("#1F618D")))
elems.append(Spacer(1, 5))
dur_data = [
[Paragraph("<b>Category</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Duration</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Common Causes</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Workup Focus</b>", style(8, WHITE, bold=True))],
[Paragraph("<b>Acute Fever</b>", style(8, TEAL, bold=True)),
"< 1 week",
"Viral URTI, malaria, dengue, UTI, bacterial pneumonia, gastroenteritis",
"CBC, malaria smear, dengue NS1, urine R/E, CXR"],
[Paragraph("<b>Subacute Fever</b>", style(8, ORANGE, bold=True)),
"1 – 3 weeks",
"Typhoid, brucellosis, infective endocarditis, TB, malignancy",
"Blood cultures ×2, Widal/Typhidot, Echo, CT, ESR/CRP"],
[Paragraph("<b>FUO</b>", style(8, RED, bold=True)),
"> 3 weeks\n(undiagnosed)",
"Infectious (TB, endocarditis), NIID (SLE, vasculitis), Malignancy (lymphoma), Drug fever",
"PET-CT, bone marrow biopsy, temporal artery biopsy, ANA/ANCA"],
]
dur_tbl = Table(dur_data, colWidths=[BODY_W*0.17, BODY_W*0.13, BODY_W*0.42, BODY_W*0.28])
dur_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#1F618D")),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 7.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LIGHT_TEAL, LIGHT_ORANGE, LIGHT_RED]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#AED6F1")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
elems.append(dur_tbl)
elems.append(Spacer(1, 10))
# ── STEP 6: INVESTIGATIONS ───────────────────────────────────────────────
elems.append(SectionHeader(6, "INVESTIGATIONS", bg=colors.HexColor("#117A65")))
elems.append(Spacer(1, 5))
# Tier 1
elems.append(Paragraph("TIER 1 — First-Line (All Patients)", style(8, TEAL, bold=True)))
elems.append(Spacer(1, 3))
t1_data = [
[Paragraph("<b>Test</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Rationale / Interpretation</b>", style(8, WHITE, bold=True))],
["CBC with differential", "Leukocytosis (bacterial), leukopenia (viral/typhoid), eosinophilia (parasites), atypical lymphocytes (EBV)"],
["ESR / CRP", "Nonspecific inflammation marker; very elevated in bacterial infections & autoimmune disease"],
["Blood culture ×2", "Pre-antibiotic; gold standard for bacteremia, typhoid, endocarditis"],
["Urine R/E + culture", "Rule out UTI / pyelonephritis in all patients with unexplained fever"],
["Peripheral blood smear", "Mandatory if any travel history; identifies malaria species & parasitaemia"],
["Chest X-ray", "Pneumonia, TB (primary/reactivation), lymphoma, pleural effusion, cardiomegaly"],
["LFT / RFT", "Hepatitis, leptospirosis (jaundice), renal involvement in sepsis"],
["Blood glucose", "Assess immune compromise in uncontrolled diabetes"],
["Serum electrolytes", "Dehydration, SIADH in CNS infections"],
["Widal / Typhidot IgM", "(Endemic areas) Enteric fever — note: interpret with clinical context"],
["Dengue NS1 antigen", "(Days 1–5) Dengue fever; add IgM/IgG from day 5 onwards"],
]
t1_tbl = Table(t1_data, colWidths=[BODY_W*0.28, BODY_W*0.72])
t1_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#117A65")),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 7.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LIGHT_TEAL, colors.HexColor("#E8F8F5")]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#A2D9CE")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), colors.HexColor("#117A65")),
]))
elems.append(t1_tbl)
elems.append(Spacer(1, 7))
# Tier 2
elems.append(Paragraph("TIER 2 — Targeted Tests (Based on Clinical Clues)", style(8, ORANGE, bold=True)))
elems.append(Spacer(1, 3))
t2_data = [
[Paragraph("<b>Suspected Diagnosis</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Additional Tests</b>", style(8, WHITE, bold=True))],
["Tuberculosis", "Mantoux test, sputum AFB ×3, ADA, HRCT chest, GeneXpert MTB/RIF"],
["Malaria", "Thick & thin films, malaria RDT, PCR for speciation"],
["HIV", "HIV ELISA, p24 antigen, CD4 count, viral load"],
["Dengue (severe)", "Serial CBC for thrombocytopenia, LFT, dengue IgM/IgG"],
["Leptospirosis", "MAT (microscopic agglutination test), IgM ELISA, urine culture"],
["EBV / CMV", "Monospot test, EBV IgM VCA, CMV IgM, atypical lymphocytes"],
["Infective Endocarditis", "TTE / TEE echocardiography, serial blood cultures ×3"],
["Meningitis", "LP: CSF cell count, protein, glucose, culture, Gram stain, PCR"],
["Autoimmune / NIID", "ANA, anti-dsDNA, ANCA, complement (C3/C4), RF, anti-CCP"],
["Malignancy", "LDH, uric acid, SPEP, CT-PET, bone marrow biopsy"],
["Brucellosis", "Brucella serology (SAT / ELISA), blood culture (Castañeda method)"],
]
t2_tbl = Table(t2_data, colWidths=[BODY_W*0.28, BODY_W*0.72])
t2_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), ORANGE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 7.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LIGHT_ORANGE, colors.HexColor("#FDFEFE")]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#FAD7A0")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), ORANGE),
]))
elems.append(t2_tbl)
elems.append(Spacer(1, 10))
# ── STEP 7: DIFFERENTIAL DIAGNOSIS ───────────────────────────────────────
elems.append(SectionHeader(7, "DIFFERENTIAL DIAGNOSIS — 4 Main Categories", bg=colors.HexColor("#6C3483")))
elems.append(Spacer(1, 5))
dd_data = [
[Paragraph("<b>Infectious (50–60% in tropics)</b>", style(8, WHITE, bold=True)),
Paragraph("<b>NIID (20–30% in West)</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Malignancy (10–20%)</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Miscellaneous</b>", style(8, WHITE, bold=True))],
[Paragraph("Bacterial: Typhoid, TB, brucellosis, endocarditis, pyelonephritis, abscess, pneumonia\n\n"
"Viral: Dengue, EBV, CMV, Hep A/E, HIV\n\n"
"Parasitic: Malaria, visceral leishmaniasis\n\n"
"Fungal: Histoplasma, Candida (immunocomp.)", style(7.5, DARK_GREY)),
Paragraph("SLE\nAdult Still's disease\nVasculitis (GCA, PAN)\nIBD (Crohn's)\nSarcoidosis\nRheumatoid arthritis\nPMR (elderly)\nAutoinflammatory syndromes", style(7.5, DARK_GREY)),
Paragraph("Hodgkin's lymphoma\n(Pel–Ebstein fever)\nNon-Hodgkin's lymphoma\nLeukemia (AML/ALL)\nRenal cell carcinoma\nHepatic malignancy\nPrimary liver tumour", style(7.5, DARK_GREY)),
Paragraph("Drug fever\n(stop suspect drug;\nfever resolves in 72h)\n\nFactitious fever\n\nHeat stroke\n\nThyroid storm\n\nAdrenal insufficiency", style(7.5, DARK_GREY))],
]
dd_tbl = Table(dd_data, colWidths=[BODY_W*0.30, BODY_W*0.22, BODY_W*0.23, BODY_W*0.25])
dd_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), RED),
("BACKGROUND", (1,0), (1,0), BLUE),
("BACKGROUND", (2,0), (2,0), PURPLE),
("BACKGROUND", (3,0), (3,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 7.5),
("BACKGROUND", (0,1), (0,1), LIGHT_RED),
("BACKGROUND", (1,1), (1,1), LIGHT_BLUE),
("BACKGROUND", (2,1), (2,1), LIGHT_PURPLE),
("BACKGROUND", (3,1), (3,1), LIGHT_TEAL),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#D5D8DC")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
elems.append(dd_tbl)
elems.append(Spacer(1, 10))
# ── STEP 8: FUO WORKUP ───────────────────────────────────────────────────
elems.append(SectionHeader(8, "FUO WORKUP (Fever > 3 weeks, undiagnosed)", bg=RED))
elems.append(Spacer(1, 5))
fuo_data = [
[Paragraph("<b>Stage</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Action</b>", style(8, WHITE, bold=True))],
[Paragraph("<b>Stage 1</b>\nRepeat basics", style(8, RED, bold=True)),
"Repeat detailed history + thorough physical exam; ensure no obvious diagnosis missed; CBC, CRP, LFT, RFT, UA, blood cultures"],
[Paragraph("<b>Stage 2</b>\nAdvanced imaging", style(8, RED, bold=True)),
"CT chest/abdomen/pelvis; PET-CT (most sensitive for occult infection & malignancy); Echocardiography (TEE); specific serologies: ANA, ANCA, cryoglobulins, Q fever IFA"],
[Paragraph("<b>Stage 3</b>\nInvasive procedures", style(8, RED, bold=True)),
"Bone marrow biopsy (pancytopenia, haematological malignancy, TB, leishmaniasis); temporal artery biopsy (elderly, high ESR → GCA); liver biopsy (granulomatous hepatitis); lymph node biopsy"],
[Paragraph("<b>Stage 4</b>\nWatchful waiting", style(8, RED, bold=True)),
"If patient is stable and no diagnosis established: avoid empirical antibiotics/steroids; monitor closely; reassess after 2–4 weeks; reconsider entire differential"],
]
fuo_tbl = Table(fuo_data, colWidths=[BODY_W*0.20, BODY_W*0.80])
fuo_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), RED),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 7.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.HexColor("#FDEDEC"), LIGHT_RED]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#F1948A")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
elems.append(fuo_tbl)
elems.append(Spacer(1, 10))
# ── STEP 9: TREATMENT DECISION ───────────────────────────────────────────
elems.append(SectionHeader(9, "TREATMENT DECISION", bg=colors.HexColor("#1E8449")))
elems.append(Spacer(1, 5))
tx_data = [
[Paragraph("<b>Condition</b>", style(8, WHITE, bold=True)),
Paragraph("<b>Treatment</b>", style(8, WHITE, bold=True))],
["Sepsis / Bacteremia", "IV broad-spectrum antibiotics within 1 hour; blood cultures first; source control"],
["Typhoid fever", "Ceftriaxone 2g IV OD (7–14 days) OR azithromycin 1g OD (5 days); ciprofloxacin if sensitive"],
["Malaria (P. falciparum)", "ACT (artemether–lumefantrine or artesunate); severe → IV artesunate"],
["Malaria (P. vivax)", "Chloroquine + primaquine (after G6PD test)"],
["Pneumonia (CAP)", "Amoxicillin-clavulanate ± azithromycin; severe → IV ceftriaxone + azithromycin"],
["TB", "RHEZ for 2 months → RH for 4 months (DOTS regimen); DOTS compliance mandatory"],
["Dengue", "Supportive: IV fluids, paracetamol (NO NSAIDs/aspirin); monitor platelets"],
["Viral URTI", "Supportive; paracetamol, hydration, rest; antibiotics NOT indicated"],
["Autoimmune (SLE, etc.)", "NSAIDs for mild; hydroxychloroquine + steroids; DMARDs for refractory disease"],
["Malignancy", "Refer oncology; treat any concurrent infection; symptom palliation"],
["Drug fever", "Stop offending drug; fever typically resolves within 48–72 hours"],
]
tx_tbl = Table(tx_data, colWidths=[BODY_W*0.27, BODY_W*0.73])
tx_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#1E8449")),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 7.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [LIGHT_TEAL, colors.HexColor("#F9FBE7")]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#82E0AA")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), colors.HexColor("#1E8449")),
]))
elems.append(tx_tbl)
elems.append(Spacer(1, 8))
# antipyretics strip
ap_tbl = Table(
[[Paragraph(
" <b>ANTIPYRETICS:</b> Paracetamol 500–1000 mg PO q6h (adults) | 15 mg/kg q6h (children) | "
"Ibuprofen (avoid in dengue, dehydration, renal impairment) | "
"<b>Avoid aspirin in children</b> (Reye's syndrome risk) | "
"Always ensure adequate oral / IV hydration",
style(7.5, DARK_GREY, align=TA_LEFT)
)]],
colWidths=[BODY_W]
)
ap_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#FEF9E7")),
("LEFTBORDER", (0,0), (0,-1), 4, GOLD),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("BOX", (0,0), (-1,-1), 0.5, GOLD),
]))
elems.append(ap_tbl)
elems.append(Spacer(1, 8))
# ── WHEN TO ADMIT ─────────────────────────────────────────────────────────
elems.append(SectionHeader(10, "WHEN TO ADMIT / REFER URGENTLY", bg=RED))
elems.append(Spacer(1, 5))
admit_items = [
"Fever >40°C unresponsive to antipyretics",
"Any haemodynamic instability (HR >120, SBP <90 mmHg)",
"Fever + meningism OR altered consciousness",
"Fever + purpuric / petechial rash",
"Immunocompromised host (HIV, transplant, chemotherapy, neutropenia)",
"Unable to maintain oral intake / severe dehydration",
"Fever of Unknown Origin requiring further inpatient workup",
"Suspected endocarditis, severe malaria, complicated typhoid",
]
admit_data = [[Paragraph(f"✦ {item}", style(8, DARK_GREY))] for item in admit_items]
admit_tbl = Table(admit_data, colWidths=[BODY_W])
admit_tbl.setStyle(TableStyle([
("ROWBACKGROUNDS", (0,0), (-1,-1), [LIGHT_RED, colors.HexColor("#FDFEFE")]),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#F1948A")),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 8),
]))
elems.append(admit_tbl)
elems.append(Spacer(1, 10))
# ── CLINICAL PEARL ────────────────────────────────────────────────────────
pearl_tbl = Table(
[[Paragraph(
" ★ <b>CLINICAL PEARL (Harrison's 22E):</b> The single most valuable step in any fever workup is a "
"<b>detailed history and physical examination</b>. Most FUOs represent atypical presentations of "
"common diseases, not rare diagnoses. Infections account for >50% of FUO in the tropics (TB predominates); "
"Non-Infectious Inflammatory Diseases predominate in the West. "
"<b>Avoid empirical antibiotics in stable, undiagnosed patients</b> — they obscure the diagnostic picture and promote resistance.",
style(7.5, DARK_GREY, align=TA_JUSTIFY)
)]],
colWidths=[BODY_W]
)
pearl_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#FEF5E7")),
("BOX", (0,0), (-1,-1), 1.5, GOLD),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
elems.append(pearl_tbl)
elems.append(Spacer(1, 6))
# ── FOOTER ────────────────────────────────────────────────────────────────
footer_tbl = Table(
[[Paragraph(
"Source: Harrison's Principles of Internal Medicine 22E (2025, McGraw-Hill) — "
"Ch. 21 Fever & Rash | Ch. 22 Fever of Unknown Origin | Ch. 79 Infections in Cancer | "
"Generated by Orris Clinical AI | For educational use only",
style(6.5, colors.HexColor("#808B96"), align=TA_CENTER)
)]],
colWidths=[BODY_W]
)
footer_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
]))
elems.append(footer_tbl)
doc.build(elems)
print(f"PDF saved: {path}")
if __name__ == "__main__":
out = "/home/daytona/workspace/fever-flowchart/Fever_Workup_Flowchart.pdf"
build_pdf(out)
cd /home/daytona/workspace/fever-flowchart && python generate_fever_pdf.py 2>&1
~/fever-flowchart/generate_fever_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/fever-flowchart/generate_fever_pdf.py'
cd /home/daytona/workspace/fever-flowchart && python generate_fever_pdf.py 2>&1
~/fever-flowchart/generate_fever_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/fever-flowchart/generate_fever_pdf.py'
grep -n "style(" /home/daytona/workspace/fever-flowchart/generate_fever_pdf.py | head -60
cd /home/daytona/workspace/fever-flowchart && sed -i 's/style(size=/style(fsize=/g' generate_fever_pdf.py && python generate_fever_pdf.py 2>&1
cd /home/daytona/workspace/fever-flowchart && python -c " content = open('generate_fever_pdf.py').read() content = content.replace('style(size=', 'style(fsize=') open('generate_fever_pdf.py', 'w').write(content) print('done') " && python generate_fever_pdf.py 2>&1
ls -lh /home/daytona/workspace/fever-flowchart/Fever_Workup_Flowchart.pdf && python -c " from pypdf import PdfReader r = PdfReader('/home/daytona/workspace/fever-flowchart/Fever_Workup_Flowchart.pdf') print(f'Pages: {len(r.pages)}') print(f'Title: {r.metadata.title}') "
Fever Workup Flowchart
PDF Document · PDF
| Step | Content |
|---|---|
| 1 | Immediate Triage - Red flags table (sepsis, meningitis, purpura, etc.) with YES/NO decision branches |
| 2 | Detailed History - 13-row table covering fever characteristics, systems, travel, exposures, medications |
| 3 | Fever Patterns - 8 patterns (continuous, remittent, intermittent, Pel-Ebstein, etc.) with classic associations |
| 4 | Physical Examination - 11-system head-to-toe table with findings and significance |
| 5 | Classify by Duration - Acute / Subacute / FUO with causes and workup focus per category |
| 6 | Investigations - Tier 1 (all patients) + Tier 2 (targeted, condition-specific) |
| 7 | Differential Diagnosis - 4-column table: Infectious / NIID / Malignancy / Miscellaneous |
| 8 | FUO Workup - 4-stage stepwise approach (repeat basics → imaging → invasive → watchful waiting) |
| 9 | Treatment - Condition-specific treatments + antipyretic dosing strip |
| 10 | When to Admit / Refer + Harrison's Clinical Pearl |