Ecg

Reading File
Asking for Preferences
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Finding Sources
Reading File
Finding Sources
Reading File
Reading File
Reading File
Loading Image
Loading Image
Reading File
Loading Image
Loading Image
Reading File
I now have comprehensive ECG content and images. Let me compile everything into a thorough, well-structured answer.

ECG Basics & Interpretation

Source: Harrison's Principles of Internal Medicine, 22E (2025) - Chapter 247 Electrocardiography (Ary L. Goldberger)

What is an ECG?

An electrocardiogram (ECG or EKG) is a graphical recording of the electrical activity generated by the heart, detected through metallic electrodes attached to the limbs and chest wall. It is noninvasive, inexpensive, and immediately available. Beyond arrhythmia detection, it reveals conduction disturbances, myocardial ischemia/infarction, metabolic disturbances (e.g., hyperkalemia), drug toxicities, and susceptibility to sudden cardiac arrest.

1. Electrophysiologic Basis

The normal heartbeat begins at the sinoatrial (SA) node, which has spontaneous automaticity. The impulse spreads through the atria, then passes through the AV node and His bundle (together = AV junction), bifurcates into the right and left bundle branches, and reaches the ventricular myocardium via Purkinje fibers.
Cardiac conduction system showing SA node, AV node, His bundle, right and left bundle branches, and Purkinje fibers
The cardiac conduction system. The left bundle branch further divides into left anterior and left posterior fascicles.

2. ECG Waveforms & Intervals

ECG waveforms showing P wave, QRS complex, ST segment, T wave, U wave, and PR/QT intervals
The basic ECG waveform. The J point marks the junction between QRS end and ST segment onset.
Waveform/IntervalRepresentsNormal Value
P waveAtrial depolarizationDuration <120 ms; amplitude <2.5 mm
PR intervalAV conduction time (SA node to ventricular muscle)120-200 ms (3-5 small boxes)
QRS complexVentricular depolarization<100 ms (up to 110 ms in some)
ST segmentVentricular plateau phase (isoelectric)Isoelectric (at baseline)
T waveVentricular repolarization (active recovery)Positive in most leads
QT intervalTotal ventricular depolarization + repolarizationCorrected QTc <440 ms (men), <460 ms (women)
U wavePossibly late ventricular repolarization / Purkinje repolarizationSmall, follows T wave
J pointQRS-ST junctionAt isoelectric line

Paper Speed & Calibration

  • Standard sweep speed: 25 mm/s
  • Smallest box (1 mm) = 40 ms (0.04 s)
  • Larger box (5 mm) = 200 ms (0.20 s)
  • Vertical amplitude: 1 mV = 10 mm at standard calibration

Calculating Heart Rate

  • Count the large boxes between two R waves: HR = 300 ÷ (number of large boxes)
  • Or count small boxes: HR = 1500 ÷ (number of small boxes)

3. The 12 Leads

A standard ECG has 12 leads - each providing a different "view" of the heart's electrical activity.

Limb Leads (Frontal Plane)

LeadView
ILeft lateral
IIInferior (most used for rhythm strips)
IIIInferior
aVRRight shoulder (right atrium) - normally negative
aVLLeft lateral
aVFInferior (foot)

Precordial (Chest) Leads (Horizontal Plane)

Precordial lead placement on the chest wall showing V1-V6 positions
Chest lead positions. V1: 4th ICS right sternal border. V2: 4th ICS left sternal border. V3: between V2 & V4. V4: 5th ICS midclavicular line. V5: anterior axillary line. V6: midaxillary line.
LeadView
V1-V2Right ventricle / septal
V3-V4Anterior LV
V5-V6Lateral LV

4. QRS Complex & R-Wave Progression

Ventricular depolarization phases showing septal and free-wall vectors and their effect on V1 vs V6 morphology
Ventricular depolarization occurs in two phases: (1) septal depolarization left-to-right (producing small r in V1, small q in V6), and (2) free-wall depolarization dominated by the larger LV, directed leftward/posteriorly (producing S in V1, tall R in V6).
Normal R-wave progression: R waves increase in amplitude from V1 through V4/V5. The transition zone (where R and S are equal) is usually at V3 or V4.
  • Poor R-wave progression (small R waves persisting through V4) suggests anterior infarction or other pathology.

5. QRS Axis

The mean QRS axis describes the overall direction of ventricular depolarization in the frontal plane:
AxisDegreesSignificance
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
Quick rule: If QRS is positive in lead I and positive in lead II → normal axis. Positive I, negative II → LAD. Negative I, positive II → RAD.

6. ST Segment & T Wave Abnormalities

ST Elevation - Key Causes

CausePattern
STEMIRegional (follows coronary territory), convex/tombstone shape
PericarditisDiffuse, saddle-shaped; PR depression
Early repolarizationBenign variant, notch at J point, common in young males
Brugada syndromeCoved ST elevation V1-V3, RBBB-like morphology
LVH/LBBBDiscordant ST changes (opposite to main QRS deflection)
HyperkalemiaMay cause V1-V3 elevation

ST Depression - Key Causes

  • Subendocardial ischemia (horizontal or downsloping)
  • Digoxin effect (reverse tick / "sagging")
  • Reciprocal changes in STEMI
  • LVH strain pattern

T Wave Changes

  • Inversion: Ischemia, ventricular hypertrophy, bundle branch block, pulmonary embolism (right heart strain), pericarditis
  • Peaked/tall T waves: Hyperkalemia (early), posterior MI (prominent T in V1-V2)
  • Flat T waves: Hypokalemia, hypothyroidism

QT Prolongation

Prolonged QTc (>500 ms) increases risk of Torsades de Pointes:
  • Drugs: antiarrhythmics (amiodarone, sotalol), antipsychotics, fluoroquinolones, azithromycin
  • Electrolytes: hypokalemia, hypomagnesemia, hypocalcemia
  • Congenital long QT syndrome

7. Systematic 14-Step Interpretation (Harrison's Approach)

A systematic approach is mandatory to avoid errors of omission. Analyze every ECG for:
  1. Standardization & calibration (1 mV = 10 mm, paper speed)
  2. Lead placement & artifacts
  3. Rhythm (sinus vs. ectopic)
  4. Heart rate
  5. PR interval / AV conduction
  6. QRS interval
  7. QT/QTc intervals
  8. Mean QRS electrical axis
  9. P waves (morphology, axis)
  10. QRS voltages (hypertrophy criteria)
  11. Precordial R-wave progression
  12. Abnormal Q waves
  13. ST segments
  14. T waves & U waves
Compare with any previous ECGs - this is invaluable.

8. P Wave Abnormalities

FindingMeaning
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 wavesAtrial fibrillation (irregularly irregular), junctional rhythm
Retrograde P (after QRS)Junctional rhythm
P waves not related to QRSComplete (3rd degree) AV block

9. Ventricular Hypertrophy

LVH Voltage Criteria (Sokolow-Lyon)

  • S in V1 + R in V5 or V6 >35 mm (age >35 years)
  • R in aVL >11-13 mm
  • Often accompanied by "strain pattern" (ST depression + T wave inversion in lateral leads I, aVL, V5-V6)

RVH

  • Dominant R wave in V1 (R > S)
  • Right axis deviation
  • ST depression + T wave inversion in V1-V3 (strain)

10. Clinical Correlations at a Glance

ConditionKey ECG Finding
Anterior STEMIST elevation V1-V4, Q waves
Inferior STEMIST elevation II, III, aVF
Lateral STEMIST elevation I, aVL, V5-V6
Posterior MITall R + ST depression V1-V2 (mirror image)
Atrial fibrillationNo P waves, irregularly irregular RR
Complete heart blockP-QRS dissociation, slow ventricular rate
LBBBBroad QRS, notched "M" in V5-V6, QS in V1
RBBBBroad QRS, RSR' ("bunny ears") in V1, wide S in I and V6
HyperkalemiaPeaked T → wide QRS → sine wave
PE (S1Q3T3)S wave in I, Q wave in III, T inversion in III
PericarditisDiffuse ST elevation + PR depression
Digoxin effectSagging ST depression ("reverse tick")

Source: Harrison's Principles of Internal Medicine, 22E (2025), Chapter 247 - Electrocardiography (pp. 1911-1918), by Ary L. Goldberger. Also based on Goldberger's Clinical Electrocardiography: A Simplified Approach, 10th ed. (Elsevier, 2024).

Want me to go deeper on any specific area - arrhythmias, bundle branch blocks, STEMI patterns, or axis calculation?

A patient comes to opd with fever. How to proceed explain with flowchart systematically

Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
I now have comprehensive content from Harrison's. I have enough to build a thorough, structured flowchart-based answer. Let me now compose it.

Approach to a Patient with Fever in OPD

Source: Harrison's Principles of Internal Medicine, 22E (2025)

MASTER FLOWCHART

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   │
└─────────────────────────────────┘

STEP 1: IMMEDIATE TRIAGE - Red Flags

Before anything else, look for danger signs requiring emergency management:
Red FlagConcern
HR >120, SBP <90 mmHgSeptic shock
RR >30/min, SpO2 <94%Sepsis, severe pneumonia
Altered consciousness/confusionMeningitis, encephalitis, septic encephalopathy
Petechiae/purpuric rashMeningococcemia
Stiff neck + fever + photophobiaMeningitis (meningeal triad)
Fever + jaundice + RUQ pain (Charcot's triad)Ascending cholangitis
Fever in immunocompromised / neutropenic patientNeutropenic fever (medical emergency)
Fever + new cardiac murmurInfective endocarditis
Unresponsive to antipyretics, rapidly rising tempConsider sepsis / malignant hyperthermia
If any red flag is present → Stabilize, admit, start sepsis workup immediately. Do NOT send home.

STEP 2: DETAILED HISTORY

A thorough history is the most valuable component of the fever workup.

A. Fever Characteristics

  • Onset: Sudden vs. gradual
  • Duration: Days, weeks, months?
  • Pattern (temperature curve):
PatternDescriptionClassic Association
Continuous / SustainedPersistent, little variation (<1°C)Typhoid fever, lobar pneumonia, UTI
RemittentFluctuates >1°C but never reaches normalMost bacterial infections
Intermittent (Quotidian)Spikes then returns to normalMalaria (P. vivax = 48h), pyogenic abscess, miliary TB
TertianFever every 3rd dayP. vivax / ovale malaria
QuartanFever every 4th dayP. malariae
Hectic / SepticWide swings with drenching sweatsPyogenic abscesses, infective endocarditis
Pel-EbsteinWeeks of fever alternating weeks of no feverHodgkin's lymphoma
RelapsingRecurrent episodesBrucellosis, Borrelia
  • Degree of fever: Low-grade (37.5-38.5°C), moderate (38.5-39.5°C), high (>39.5°C)
  • Associated rigors / chills: Suggest bacteremia, malaria, pyelonephritis
  • Response to antipyretics: Does the fever respond to paracetamol/NSAIDs?
  • Diurnal variation: Higher in evenings (TB)

B. Associated Symptoms - System-by-System

SystemSymptoms to AskSuggests
RespiratoryCough, sputum, dyspnoea, pleuritic chest painPneumonia, TB, pleural effusion
GINausea, vomiting, diarrhoea, pain, jaundiceGastroenteritis, hepatitis, typhoid, cholangitis
UrinaryDysuria, frequency, loin pain, haematuriaUTI, pyelonephritis
CNSHeadache, neck stiffness, photophobia, confusionMeningitis, encephalitis
SkinRash, ulcers, swellingsDengue, typhus, viral exanthem, cellulitis
MusculoskeletalJoint pains, myalgia, bone painRheumatic fever, septic arthritis, osteomyelitis
Lymph nodesLymphadenopathyLymphoma, HIV, EBV, TB, leukemia
CardiacChest pain, palpitations, new murmurEndocarditis, myocarditis
Night sweatsDrenchingTB, lymphoma, HIV, brucellosis
Weight lossUnexplained >10%Malignancy, TB, HIV

C. Epidemiological & Exposure History

  • Travel: Malaria zone? Typhoid endemic area? Dengue belt?
  • Animal contact / bites: Leptospirosis, brucellosis, rabies, Q fever, rickettsia
  • Tick / mosquito bites: Malaria, dengue, rickettsia, Lyme disease
  • Sexual history: HIV, gonorrhoea, syphilis
  • Food history: Raw meat/fish, unpasteurised dairy (brucellosis), shellfish (hepatitis A/E)
  • Sick contacts: Family, school, workplace
  • Occupation: Farmer, abattoir worker, healthcare worker
  • Water source: Leptospirosis, typhoid

D. Past Medical History

  • Immunosuppression (HIV, steroids, chemotherapy, diabetes)
  • Prior similar episodes
  • Recent surgery / procedures / hospitalisation (nosocomial infection)
  • Prosthetic valves / implants (endocarditis risk)
  • Previous TB / malaria
  • Medications (drug fever is a diagnosis of exclusion)

E. Immunisation Status

  • Typhoid, hepatitis A/B, meningococcal vaccine status

STEP 3: PHYSICAL EXAMINATION

Perform a systematic head-to-toe examination:

Vital Signs

  • Temperature (confirm and grade), HR, BP, RR, SpO2
  • Check for relative bradycardia (pulse-temperature dissociation - seen in typhoid, drug fever, Legionella)

General Appearance

  • Toxic/ill-looking vs. well-appearing
  • Nutritional status, pallor, icterus, cyanosis, clubbing, lymphadenopathy, oedema

System-Specific Findings

RegionWhat to Look ForSignificance
SkinRash type, distribution, petechiae, eschar, jaundiceViral exanthem, meningococcemia, typhus (eschar), rickettsial
EyesIcterus, conjunctival suffusion, Roth spotsHepatitis, leptospirosis, endocarditis
ENTTonsillar exudate, pharyngeal erythema, sinus tendernessStrep throat, EBV, sinusitis
NeckMeningism (Kernig's, Brudzinski's), lymphadenopathy, thyroidMeningitis, lymphoma, thyroiditis
ChestDullness, crepitations, bronchial breathing, friction rubPneumonia, pleural effusion, pericarditis
AbdomenHepatomegaly, splenomegaly, tenderness, rigidity, guardingMalaria, typhoid, hepatitis, abscess
CVSNew murmur, pericardial rubEndocarditis, pericarditis
JointsSwelling, warmth, tendernessSeptic arthritis, rheumatic fever, reactive arthritis
GenitourinaryCostovertebral angle tenderness, urethral dischargePyelonephritis, STI
NeurologicalFocal deficits, consciousness levelCNS infection, encephalitis

STEP 4: CLASSIFY THE FEVER

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
Fever of Unknown Origin (FUO) Definition (Harrison's 22E):
  • Temperature ≥38°C on multiple occasions
  • Duration >3 weeks
  • No diagnosis after thorough initial evaluation (3 outpatient visits OR 3 days in hospital)

STEP 5: INITIAL INVESTIGATIONS (ALL FEVER CASES)

Tier 1 - First-line (OPD, all patients):

TestRationale
CBC with differentialLeukocytosis (bacterial), leukopenia (viral/typhoid), eosinophilia (parasites/allergy), atypical lymphocytes (EBV)
ESR / CRPNonspecific inflammatory marker; very elevated in bacterial/autoimmune
Peripheral blood smear (if travel history)Malaria
Urine routine + cultureRule out UTI/pyelonephritis
Blood culture x2 (pre-antibiotic)Bacteremia, typhoid, endocarditis
Widal test / TyphidotEnteric fever (in endemic areas)
Dengue NS1 antigen / IgM (if endemic, early)Dengue fever
Chest X-rayPneumonia, TB, lymphoma, pleural effusion
LFT / RFTHepatitis, renal involvement in sepsis/leptospirosis
Blood glucoseUncontrolled DM (immunosuppressed host)
Serum electrolytesDehydration from fever

Tier 2 - Targeted (based on history/examination):

Clinical SuspicionAdditional Tests
TBMantoux test, sputum AFB, ADA, HRCT chest, GeneXpert
MalariaThick & thin films, malaria RDT, PCR
HIVHIV ELISA, CD4 count, viral load
TyphoidBlood culture (gold standard), Widal, Typhidot IgM
DengueNS1 (day 1-5), IgM/IgG (day 5 onwards), CBC for thrombocytopenia
LeptospirosisMAT (microscopic agglutination test), IgM ELISA
EBV / CMVMonospot, EBV IgM, CMV IgM
Infective endocarditisEchocardiography (TTE/TEE), serial blood cultures
Urinary sourceUrine C&S, renal ultrasound
CNS infectionLP (CSF analysis: cell count, protein, glucose, culture, PCR)
Autoimmune / RheumatologicalANA, anti-dsDNA, ANCA, complement levels, RF
MalignancyLDH, uric acid, PET-CT, bone marrow biopsy

STEP 6: DIFFERENTIAL DIAGNOSIS FRAMEWORK (4 Big Categories)

From Harrison's 22E (Table 22-2 approach):
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)

STEP 7: FUO WORKUP (if fever >3 weeks, undiagnosed)

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
Geographic note (Harrison's 22E): In Southern Asia & Far East, infectious causes (especially TB) account for up to 50% of FUO. In Western nations, Non-Infectious Inflammatory Diseases (NIIDs - autoimmune, vasculitis, granulomatous) are the most common cause (up to 30%).

STEP 8: TREATMENT DECISION

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

Antipyretics

  • Paracetamol: Drug of choice - 500-1000 mg PO q6h (adults); 15 mg/kg q6h (children)
  • Ibuprofen: Effective but avoid in dehydrated patients, renal impairment
  • Avoid aspirin in children (Reye's syndrome) and dengue (bleeding risk)

When to Refer / Admit

  • Fever >40°C unresponsive to antipyretics
  • Any haemodynamic instability
  • Fever + meningism, altered consciousness
  • Fever in immunocompromised host
  • Fever + purpuric rash
  • FUO requiring further workup
  • Unable to maintain oral intake (severe dehydration)

SUMMARY FLOWCHART (Condensed)

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

Sources: Harrison's Principles of Internal Medicine, 22E (2025) - Chapter 22 (FUO), Chapter 21 (Fever & Rash); Swanson's Family Medicine Review, 9E; Goldman-Cecil Medicine
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

Reading File
Running Command

mkdir -p /home/daytona/workspace/fever-flowchart && ls /home/daytona/workspace/fever-flowchart/

Writing File

~/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)
Running Command

cd /home/daytona/workspace/fever-flowchart && python generate_fever_pdf.py 2>&1

Editing File

~/fever-flowchart/generate_fever_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/fever-flowchart/generate_fever_pdf.py'
Running Command

cd /home/daytona/workspace/fever-flowchart && python generate_fever_pdf.py 2>&1

Editing File

~/fever-flowchart/generate_fever_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/fever-flowchart/generate_fever_pdf.py'
Running Command

grep -n "style(" /home/daytona/workspace/fever-flowchart/generate_fever_pdf.py | head -60

Running Command

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

Running Command

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

Running Command

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}') "

Your clinical flowchart PDF is ready:

Fever Workup Flowchart

PDF Document · PDF


What's Inside (4 pages)

The PDF is fully colour-coded and covers all 10 steps:
StepContent
1Immediate Triage - Red flags table (sepsis, meningitis, purpura, etc.) with YES/NO decision branches
2Detailed History - 13-row table covering fever characteristics, systems, travel, exposures, medications
3Fever Patterns - 8 patterns (continuous, remittent, intermittent, Pel-Ebstein, etc.) with classic associations
4Physical Examination - 11-system head-to-toe table with findings and significance
5Classify by Duration - Acute / Subacute / FUO with causes and workup focus per category
6Investigations - Tier 1 (all patients) + Tier 2 (targeted, condition-specific)
7Differential Diagnosis - 4-column table: Infectious / NIID / Malignancy / Miscellaneous
8FUO Workup - 4-stage stepwise approach (repeat basics → imaging → invasive → watchful waiting)
9Treatment - Condition-specific treatments + antipyretic dosing strip
10When to Admit / Refer + Harrison's Clinical Pearl
Each section uses a distinct colour scheme for quick visual navigation during OPD use.
This is a shared conversation. Sign in to Orris to start your own chat.