Fever+Wet cough+joint pain+weakness ,give me differentials

Reading File
Finding Sources
Finding Sources
Finding Sources
Searching PubMed

"fever" AND "arthralgia" AND "pneumonia"

Searching PubMed

"fever" AND "cough" AND "arthralgia"

Differential Diagnosis: Fever + Productive (Wet) Cough + Joint Pain + Weakness

This symptom cluster suggests a systemic infectious or post-infectious/inflammatory process affecting both the respiratory tract and joints. Here's an organized differential, grouped by mechanism:

1. Infectious - respiratory with systemic spread

  • Community-acquired pneumonia (bacterial) - fever, productive cough, fatigue/weakness are the classic triad (fatigue ~90%, fever 71-75%, cough 79-91% per Tintinalli's Emergency Medicine); arthralgia can occur as a systemic inflammatory response.
  • Atypical pneumonia (Mycoplasma pneumoniae, Legionella, Chlamydophila) - notorious for extrapulmonary manifestations including arthralgia, myalgia, and marked weakness out of proportion to chest findings.
  • Influenza / other viral respiratory infections (including COVID-19) - fever, cough (can become productive with secondary bacterial infection), diffuse arthralgia/myalgia, and profound weakness are hallmark.
  • Tuberculosis - chronic fever, productive cough, weight loss/weakness; can cause reactive arthritis (Poncet's disease) or direct osteoarticular TB with joint pain.

2. Post-infectious / immune-mediated

  • Acute rheumatic fever - fever plus migratory polyarthritis is the classic adult presentation; wet cough is not typical unless carditis leads to pulmonary congestion/heart failure. Per Harrison's Principles of Internal Medicine, "migratory polyarthritis and fever constitute the usual presentation of acute rheumatic fever in adults."
  • Poststreptococcal reactive arthritis - distinguished from rheumatic fever by non-migratory, more persistent joint involvement following a streptococcal (often respiratory) infection - Tintinalli's Emergency Medicine, p. 116-122.
  • Reactive arthritis following other infections (enteric or respiratory pathogens).

3. Vector-borne / tropical fevers (important if travel or endemic exposure)

  • Chikungunya - fever with severe, often debilitating joint pain and profound fatigue/weakness; respiratory symptoms are less typical but can coexist with concurrent infection. A 2025 systematic review (PMID: 39899618) confirms arthralgia and fatigue persist into the chronic phase in a large proportion of patients.
  • Dengue fever - "break-bone fever" with fever, severe myalgia/arthralgia, and weakness; can have atypical presentations with pulmonary involvement (PMID: 40800585, 2025 case series).
  • Leptospirosis - fever, myalgia, cough, and marked weakness/prostration; consider with water/animal exposure history.

4. Rheumatologic / connective tissue disease

  • Systemic lupus erythematosus (SLE) - fever, arthralgia/arthritis, fatigue/weakness, and pulmonary involvement (pleuritis, lupus pneumonitis) can produce a productive cough.
  • Rheumatoid arthritis with pulmonary manifestations (organizing pneumonia, bronchiectasis) - joint pain plus infective/inflammatory cough.
  • Both listed among classic connective tissue disease causes of fever + arthritis - Roberts and Hedges' Clinical Procedures in Emergency Medicine.

5. Other considerations

  • Infective endocarditis - fever, weakness, arthralgia (immune complex-mediated), and septic pulmonary emboli can cause cough, especially in IV drug users or those with valve disease/right-sided endocarditis.
  • Sarcoidosis - fever and arthralgia can be the presenting feature of an underlying granulomatous disease with pulmonary involvement (PMID: 41552225, 2025 case report).

Key differentiating clues to narrow this down

CluePoints toward
Recent sore throat, migratory polyarthritisRheumatic fever / poststreptococcal reactive arthritis
Travel to tropics, severe joint pain disproportionate to other findingsChikungunya/dengue
Chronic symptoms, weight loss, night sweatsTB
Rash, photosensitivity, oral ulcersSLE
New murmur, IV drug use, dental workEndocarditis
Water exposure (floods, farming)Leptospirosis
Rapid onset, household contacts sickInfluenza/COVID-19
Note: A 2025 systematic review on chikungunya (PMID 39899618) and a 2025 meta-analysis on chikungunya mimicking inflammatory rheumatic disease (PMID 40993769) reinforce that arthralgia/fatigue from vector-borne viral fevers can closely mimic rheumatologic disease - worth considering if there's relevant travel/exposure history, since it can lead to misdiagnosis as RA or spondyloarthritis.
To narrow this further, it would help to know: duration of symptoms, patient age, travel/exposure history, whether the joint pain is migratory vs. fixed, and any rash, sore throat, or recent infection preceding onset. Let me know if you'd like me to go deeper into any one of these (e.g., workup for suspected rheumatic fever vs. atypical pneumonia vs. a vector-borne cause).

Create a diagnostic workup flowchart PDF for these symptoms

Reading File
Running Command

mkdir -p /tmp/workspace/diagnostic-flowchart/output && ls -la /tmp/workspace/

Writing File

~/diagnostic-flowchart/build_flowchart.py

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
from matplotlib.backends.backend_pdf import PdfPages

OUT = "/tmp/workspace/diagnostic-flowchart/output/Diagnostic_Workup_Flowchart.pdf"

COLORS = {
    "title": "#1f3864",
    "assess": "#2e75b6",
    "labs": "#2e75b6",
    "decision": "#bf8f00",
    "branch": "#548235",
    "test": "#7f7f7f",
    "dx": "#c00000",
    "redflag": "#c00000",
}

def box(ax, x, y, w, h, text, color, fontsize=8.5, textcolor="white", weight="bold", style="round,pad=0.02,rounding_size=0.02", lw=1.4, alpha=1.0, fontstyle="normal"):
    b = FancyBboxPatch((x, y), w, h, boxstyle=style, linewidth=lw,
                        edgecolor=color, facecolor=color, alpha=alpha, zorder=2)
    ax.add_patch(b)
    ax.text(x + w/2, y + h/2, text, ha="center", va="center", fontsize=fontsize,
            color=textcolor, weight=weight, fontstyle=fontstyle, zorder=3, linespacing=1.3)
    return b

def outline_box(ax, x, y, w, h, text, edgecolor, fontsize=8, textcolor="black", lw=1.6, facecolor="white"):
    b = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.02,rounding_size=0.02", linewidth=lw,
                        edgecolor=edgecolor, facecolor=facecolor, zorder=2)
    ax.add_patch(b)
    ax.text(x + w/2, y + h/2, text, ha="center", va="center", fontsize=fontsize,
            color=textcolor, zorder=3, linespacing=1.3)
    return b

def diamond(ax, cx, cy, w, h, text, color, fontsize=8.5, textcolor="white"):
    pts = [(cx, cy+h/2), (cx+w/2, cy), (cx, cy-h/2), (cx-w/2, cy)]
    d = mpatches.Polygon(pts, closed=True, facecolor=color, edgecolor=color, zorder=2)
    ax.add_patch(d)
    ax.text(cx, cy, text, ha="center", va="center", fontsize=fontsize, color=textcolor,
            weight="bold", zorder=3, linespacing=1.2)

def arrow(ax, x1, y1, x2, y2, color="black", lw=1.3, connectionstyle="arc3,rad=0.0"):
    a = FancyArrowPatch((x1, y1), (x2, y2), arrowstyle="-|>", mutation_scale=12,
                         color=color, linewidth=lw, connectionstyle=connectionstyle, zorder=1)
    ax.add_patch(a)

def new_page(figsize=(17, 11)):
    fig, ax = plt.subplots(figsize=figsize)
    ax.set_xlim(0, 100)
    ax.set_ylim(0, 65)
    ax.axis("off")
    return fig, ax

pdf = PdfPages(OUT)

# ============================================================
# PAGE 1: Triage -> Initial Workup -> Decision Point
# ============================================================
fig, ax = new_page()

ax.text(50, 63, "Diagnostic Workup Flowchart", ha="center", fontsize=20, weight="bold", color=COLORS["title"])
ax.text(50, 60.3, "Presenting complaint: Fever + Wet (productive) Cough + Joint Pain + Weakness",
        ha="center", fontsize=12.5, color="#333333", style="italic")

# STEP 0: Red flag screen
box(ax, 32, 54.5, 36, 4.6,
    "STEP 0 - IMMEDIATE RED-FLAG SCREEN\nHypotension / SpO2<92% / altered mental status / respiratory distress /\nnew murmur with embolic signs / signs of sepsis",
    COLORS["redflag"], fontsize=9)

arrow(ax, 50, 54.5, 50, 51.3)
outline_box(ax, 38, 48.8, 24, 2.6, "YES -> Any red flag present?", "#c00000", fontsize=8.5, textcolor="#c00000")

# split into urgent path and standard path
arrow(ax, 44, 48.8, 20, 46.5, connectionstyle="arc3,rad=-0.2")
arrow(ax, 56, 48.8, 78, 46.5, connectionstyle="arc3,rad=0.2")

box(ax, 6, 42.8, 28, 4.0, "YES: Admit / escalate to ED-ICU\nO2, IV access, sepsis workup,\nblood cultures x2, lactate,\nempiric broad-spectrum antibiotics",
    COLORS["redflag"], fontsize=8.3)

box(ax, 66, 43.3, 28, 3.4, "NO: Proceed with outpatient / ward\nstructured workup below", COLORS["assess"], fontsize=8.8)

arrow(ax, 80, 43.3, 50, 40.3)

# STEP 1: History + Exam
box(ax, 26, 35.8, 48, 4.6,
    "STEP 1 - FOCUSED HISTORY & EXAMINATION\n"
    "History: onset/duration, travel, water/animal exposure, sick contacts, recent sore throat,\n"
    "rash, IVDU, prior joint disease, medications  |  Exam: vitals, lung auscultation, joint\n"
    "pattern (mono/poly, migratory/fixed), skin/rash, cardiac murmur, lymphadenopathy",
    COLORS["assess"], fontsize=8.6)

arrow(ax, 50, 35.8, 50, 32.6)

# STEP 2: First-line labs/imaging
box(ax, 20, 28.0, 60, 4.6,
    "STEP 2 - FIRST-LINE LABS & IMAGING (all patients)\n"
    "CBC with differential, CRP/ESR, blood cultures x2, chest X-ray, urinalysis,\n"
    "renal/liver panel, flu + COVID-19 PCR/antigen, sputum Gram stain & culture",
    COLORS["labs"], fontsize=8.6)

arrow(ax, 50, 28.0, 50, 24.8)

diamond(ax, 50, 21.5, 34, 6.2, "STEP 3 - Which clinical pattern\ndominates on initial data?", COLORS["decision"], fontsize=9)

# Branches fan out to page 2 categories - draw 6 arrows down to labeled stubs
labels = [
    ("A: Infiltrate on\nCXR (pneumonia)", 8),
    ("B: Joint pain\ndominant, CXR clear", 24),
    ("C: Travel /\nexposure history +", 40),
    ("D: Cardiac findings /\nIVDU", 56),
    ("E: Chronic >2-4wk,\nweight loss", 72),
    ("F: Autoimmune\nfeatures (rash, etc.)", 88),
]
for text, xpos in labels:
    arrow(ax, 50, 18.4, xpos, 12.5, connectionstyle=f"arc3,rad={(xpos-50)/220}")
    outline_box(ax, xpos-8, 8.0, 16, 4.3, text, COLORS["branch"], fontsize=7.6, textcolor=COLORS["branch"])

ax.text(50, 2.8, "See Page 2 for branch-specific workup (A-F) and target diagnoses.  |  Page 1 of 2",
        ha="center", fontsize=9, color="#555555")

pdf.savefig(fig)
plt.close(fig)

# ============================================================
# PAGE 2: Branch-specific workups A-F
# ============================================================
fig, ax = new_page(figsize=(17, 13))
ax.set_ylim(0, 78)

ax.text(50, 76, "Branch-Specific Workup (continued from Page 1)", ha="center", fontsize=18, weight="bold", color=COLORS["title"])

def branch_block(ax, x, y, w, letter_title, tests, dx, h_title=3.0, h_tests=8.0, h_dx=3.2):
    box(ax, x, y, w, h_title, letter_title, COLORS["branch"], fontsize=9.3)
    arrow(ax, x+w/2, y, x+w/2, y-1.0)
    outline_box(ax, x, y-1.0-h_tests, w, h_tests, tests, "#7f7f7f", fontsize=7.6)
    arrow(ax, x+w/2, y-1.0-h_tests, x+w/2, y-1.0-h_tests-1.0)
    box(ax, x, y-2.0-h_tests-h_dx, w, h_dx, dx, COLORS["dx"], fontsize=8.2)

col_w = 28
gap = 4
start_x = 3
top_y = 70

branches = [
    ("BRANCH A\nInfiltrate on CXR\n(pneumonia pattern)",
     "Sputum culture + Gram stain\nAtypical panel: Mycoplasma serology,\nLegionella urinary antigen\nProcalcitonin (if available)\nIf arthralgia disproportionate/persists:\nASO titer, Anti-DNase B, ECG, Echo",
     "-> CAP (typical/atypical) with\nreactive arthralgia\n-> or superimposed rheumatic fever"),
    ("BRANCH B\nJoint pain dominant,\nCXR clear/minimal",
     "Joint pattern migratory?\n  Yes -> ASO/Anti-DNase B, ECG, Echo\n         (Jones criteria)\n  No, fixed/persistent -> RF, anti-CCP,\n         ANA, uric acid, joint aspirate\nRecent GI/GU infection? -> HLA-B27,\n         stool/urine culture",
     "-> Acute rheumatic fever\n-> Reactive arthritis\n-> RA / gout / SLE"),
    ("BRANCH C\nTravel / endemic\nexposure history +",
     "Tropical exposure:\n  Dengue NS1 antigen + IgM/IgG\n  Chikungunya IgM / RT-PCR\n  Malaria smear / RDT\nWater or animal exposure:\n  Leptospira serology (MAT), blood\n  and urine culture",
     "-> Dengue / Chikungunya\n-> Leptospirosis"),
    ("BRANCH D\nCardiac findings,\nIVDU, embolic signs",
     "Blood cultures x3 (before antibiotics)\nTransthoracic echo (TTE); TEE if\n  TTE inconclusive and suspicion high\nApply modified Duke criteria",
     "-> Infective endocarditis"),
    ("BRANCH E\nChronic symptoms\n(>2-4 wk), weight loss,\nnight sweats",
     "Sputum AFB smear/culture,\n  GeneXpert MTB/RIF\nChest CT if CXR equivocal\nJoint imaging if monoarticular\n  (Poncet's disease / skeletal TB)",
     "-> Pulmonary +/- osteoarticular\n     tuberculosis"),
    ("BRANCH F\nAutoimmune features\n(rash, oral ulcers,\nphotosensitivity)",
     "ANA, anti-dsDNA, complement\n  (C3/C4)\nUrinalysis for proteinuria/casts\nAnti-Ro/La, RF, anti-CCP as\n  indicated\nChest imaging for pleuritis/\n  pneumonitis",
     "-> SLE or other connective\n     tissue disease"),
]

for i, (title, tests, dx) in enumerate(branches):
    col = i % 3
    row = i // 3
    x = start_x + col*(col_w+gap)
    y = top_y - row*36
    branch_block(ax, x, y, col_w, title, tests, dx)

ax.text(50, 2.0,
        "Notes: This flowchart is a general educational reference, not a substitute for clinical judgment or local guidelines.\n"
        "Always correlate with full clinical context; multiple pathways may apply simultaneously. Page 2 of 2",
        ha="center", fontsize=8.3, color="#555555", linespacing=1.4)

pdf.savefig(fig)
plt.close(fig)

pdf.close()
print("Saved:", OUT)
Running Command

cd /tmp/workspace/diagnostic-flowchart && python3 build_flowchart.py

Running Command

cd /tmp/workspace/diagnostic-flowchart/output && ls -la && python3 -c " from pypdf import PdfReader r = PdfReader('Diagnostic_Workup_Flowchart.pdf') print('pages:', len(r.pages)) for i,p in enumerate(r.pages): print(i, p.mediabox) "

The PDF is generated successfully - a 2-page flowchart covering the full diagnostic workup.

Diagnostic Workup Flowchart

PDF Document · PDF

Contents:
Page 1 - Triage & Initial Workup
  • Step 0: Red-flag screen (hypotension, hypoxia, altered mental status, sepsis signs) → immediate escalation path vs. standard outpatient/ward path
  • Step 1: Focused history and exam (travel, exposures, joint pattern, rash, cardiac exam)
  • Step 2: First-line labs/imaging for everyone (CBC, CRP/ESR, blood cultures, CXR, urinalysis, flu/COVID PCR, sputum culture)
  • Step 3: Decision point branching into 6 clinical patterns (A-F)
Page 2 - Branch-Specific Workups
  • A - Pneumonia on CXR → sputum culture, atypical panel (Mycoplasma, Legionella), ASO/echo if arthralgia persists → CAP ± reactive arthralgia/rheumatic fever
  • B - Joint pain dominant, clear CXR → migratory vs. fixed pattern workup (ASO/Jones criteria vs. RF/anti-CCP/ANA) → rheumatic fever, reactive arthritis, RA/SLE/gout
  • C - Travel/exposure history → dengue NS1/IgM, chikungunya PCR, malaria smear, leptospira serology
  • D - Cardiac findings/IVDU → blood cultures x3, echo, Duke criteria → infective endocarditis
  • E - Chronic (>2-4 wks), weight loss → AFB smear/GeneXpert, chest CT → TB (± Poncet's disease)
  • F - Autoimmune features → ANA, anti-dsDNA, complement, urinalysis → SLE/connective tissue disease
Each branch ends in a suggested working diagnosis. This is a general educational reference - actual clinical decisions should follow local protocols and full clinical correlation.

Create a quick-reference PDF checklist for clinical exam findings that differentiate these diagnoses

Finding Sources
Finding Sources
Finding Sources
Finding Sources
Writing File

~/diagnostic-flowchart/build_checklist.py

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, FancyBboxPatch
from matplotlib.backends.backend_pdf import PdfPages
import textwrap

OUT = "/tmp/workspace/diagnostic-flowchart/output/Clinical_Exam_Findings_Checklist.pdf"

def wrap_text(text, width=35):
    """Wrap text to specified width."""
    return '\n'.join(textwrap.wrap(text, width=width))

def header_box(ax, x, y, w, h, text, color="#1f3864"):
    """Draw a header box."""
    rect = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.01", 
                          linewidth=1.8, edgecolor=color, facecolor=color, 
                          zorder=2)
    ax.add_patch(rect)
    ax.text(x + w/2, y + h/2, text, ha="center", va="center", 
            fontsize=10, color="white", weight="bold", zorder=3)

def diagnosis_box(ax, x, y, w, h, dx_name, color):
    """Draw a diagnosis name box."""
    rect = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.008", 
                          linewidth=1.6, edgecolor=color, facecolor=color, 
                          zorder=2, alpha=0.85)
    ax.add_patch(rect)
    ax.text(x + w/2, y + h/2, dx_name, ha="center", va="center", 
            fontsize=9.5, color="white", weight="bold", zorder=3, linespacing=1.2)

def finding_row(ax, x, y, w, h, category, findings, color_cat="#e7e6e6", color_text="black"):
    """Draw a finding row with category and findings."""
    # Category label
    cat_w = w * 0.22
    rect_cat = Rectangle((x, y), cat_w, h, facecolor=color_cat, edgecolor="#999999", 
                         linewidth=1, zorder=1)
    ax.add_patch(rect_cat)
    ax.text(x + cat_w/2, y + h/2, category, ha="center", va="center", 
            fontsize=7.5, color="#333333", weight="bold", zorder=2, linespacing=1.1)
    
    # Findings text
    findings_w = w - cat_w
    rect_findings = Rectangle((x + cat_w, y), findings_w, h, facecolor="white", 
                             edgecolor="#cccccc", linewidth=0.8, zorder=1)
    ax.add_patch(rect_findings)
    ax.text(x + cat_w + 3, y + h/2, findings, ha="left", va="center", 
            fontsize=7.2, color=color_text, zorder=2, linespacing=1.15, family="monospace")

# ============================================================
# PAGE 1: Top 4 diagnoses
# ============================================================
pdf = PdfPages(OUT)
fig = plt.figure(figsize=(17, 22))
ax = fig.add_subplot(111)
ax.set_xlim(0, 100)
ax.set_ylim(0, 140)
ax.axis("off")

# Title
ax.text(50, 137, "Clinical Exam Findings Quick-Reference Checklist", 
        ha="center", fontsize=18, weight="bold", color="#1f3864")
ax.text(50, 134, "Fever + Cough + Joint Pain + Weakness: Differential Diagnosis", 
        ha="center", fontsize=11, style="italic", color="#555555")

# Column layout
col_w = 23
gap = 0.5
col_positions = [1, 25.5, 50, 74.5]

diagnoses_page1 = [
    {
        "name": "COMMUNITY-\nACQUIRED\nPNEUMONIA",
        "color": "#2e75b6",
        "findings": [
            ("Vital signs", "Tachypnea (RR>20), tachycardia,\nfever, hypoxia common"),
            ("Chest exam", "Crackles/rales, bronchial breath\nsounds, dullness to percussion,\nsplinting (pain with breath)"),
            ("Constitutional", "Malaise, fatigue, myalgia\ndisproportionate to joint pain"),
            ("Joints", "Arthralgias possible but NOT\nmigratory or severely inflamed"),
            ("Heart", "Normal S1/S2, no murmur (unless\nsecondary complication)"),
            ("Skin/rash", "None, or unrelated to pneumonia"),
            ("Red flags", "Hypoxia, altered mental status,\nhypotension, sepsis signs"),
        ]
    },
    {
        "name": "ACUTE\nRHEUMATIC\nFEVER",
        "color": "#c00000",
        "findings": [
            ("Vital signs", "Fever ~38-39°C, may be variable"),
            ("Joint exam", "MIGRATORY polyarthritis\n(moves between joints daily),\nno permanent damage"),
            ("Heart findings", "NEW murmur (aortic/mitral),\ncardiomegaly (CXR), pericardial\nfriction rub, signs of heart failure"),
            ("Skin", "Erythema marginatum (pale center,\nred border, non-pruritic) or\nsubcutaneous nodules"),
            ("Neuro", "Chorea (involuntary movements) if\npresent -> pathognomonic"),
            ("Chest exam", "Normal or signs of\ncardiomegaly/pulmonary edema"),
            ("ESR/CRP", "Both elevated (acute phase)"),
        ]
    },
    {
        "name": "INFECTIVE\nENDOCARDITIS",
        "color": "#bf8f00",
        "findings": [
            ("Vital signs", "Fever ~38-39°C, tachycardia"),
            ("Heart findings", "NEW or CHANGING murmur\n(regurgitant, high-pitched),\ncardiomegaly, signs of\ndecompensation"),
            ("Embolic phenomena", "Osler nodes (tender fingertip\nnodules), Janeway lesions\n(painless palmar macules),\nsplinter hemorrhages"),
            ("Petechiae", "Petechiae on conjunctiva, palate,\nextremities; retinal hemorrhages\n(Roth spots)"),
            ("Splenomegaly", "Palpable spleen"),
            ("Joint pain", "Arthralgias but NOT migratory or\ninflammatory; not a major finding"),
            ("Risk factors", "IVDU, prosthetic valve, recent\ndental/GI procedure"),
        ]
    },
    {
        "name": "SYSTEMIC\nLUPUS\nERYTHEMATOSUS",
        "color": "#70ad47",
        "findings": [
            ("Vital signs", "Fever, may be low-grade"),
            ("Skin findings", "MALAR rash (butterfly, spares\nnaso-labial folds), photosensitivity,\noral ulcers (painless), Raynaud's"),
            ("Joint exam", "Non-erosive polyarthritis\n(PIP/MCP/wrist), but NOT\nmigratory; may resemble RA"),
            ("Chest/lungs", "Pleuritis (pleuritic pain),\npleural effusion, pneumonitis,\ncan cause productive cough"),
            ("Other findings", "Lymphadenopathy, pericarditis,\nRenal involvement (proteinuria,\ncasts in UA)"),
            ("Hair/nails", "Alopecia, nail changes"),
            ("Constitutional", "Profound fatigue out of proportion\nto exam findings"),
        ]
    },
]

y_start = 131

for idx, dx in enumerate(diagnoses_page1):
    x = col_positions[idx % 4]
    y = y_start - (idx // 4) * 68
    
    # Diagnosis header
    diagnosis_box(ax, x, y - 2.5, col_w, 2.8, dx["name"], dx["color"])
    
    # Findings
    row_h = 8.0
    for i, (category, findings) in enumerate(dx["findings"]):
        finding_row(ax, x, y - 5.2 - i*row_h, col_w, row_h, category, findings)

ax.text(50, 1.5, "Page 1 of 2: Most Common & Acutely Differentiated Diagnoses",
        ha="center", fontsize=9, color="#555555", weight="bold")

pdf.savefig(fig, bbox_inches="tight", pad_inches=0.3)
plt.close(fig)

# ============================================================
# PAGE 2: Secondary & chronic diagnoses
# ============================================================
fig = plt.figure(figsize=(17, 22))
ax = fig.add_subplot(111)
ax.set_xlim(0, 100)
ax.set_ylim(0, 140)
ax.axis("off")

ax.text(50, 137, "Clinical Exam Findings Quick-Reference Checklist (continued)", 
        ha="center", fontsize=18, weight="bold", color="#1f3864")
ax.text(50, 134, "Additional Diagnoses to Consider", 
        ha="center", fontsize=11, style="italic", color="#555555")

diagnoses_page2 = [
    {
        "name": "DENGUE\nFEVER",
        "color": "#548235",
        "findings": [
            ("Vital signs", "HIGH fever (40-40.5°C),\nrelative bradycardia (characteristic)"),
            ("Joint/muscle pain", "SEVERE arthralgias & myalgias\n('breakbone fever'), weakness\nout of proportion"),
            ("Rash", "Rash appears on 3rd-4th day\n(face, trunk, extremities),\nspares palms/soles initially"),
            ("Bleeding signs", "Petechiae, mucosal bleeding\n(severe cases)"),
            ("Chest exam", "Minimal findings; cough not typical\nunless secondary pneumonia"),
            ("Lymph nodes", "Lymphadenopathy (cervical,\noccipital)"),
            ("Conjunctivitis", "Non-purulent conjunctival\ninjection without exudate"),
        ]
    },
    {
        "name": "CHIKUNGUNYA\nFEVER",
        "color": "#8b4789",
        "findings": [
            ("Vital signs", "Fever (often ~39-40°C),\ntachycardia"),
            ("Joint pain", "SEVERE, DEBILITATING\npolyarthritis (hands, feet, knees),\nmay persist weeks-months,\ntruly disabling"),
            ("Weakness/fatigue", "Profound fatigue & weakness,\noften bedbound early"),
            ("Rash", "Maculopapular, generalized,\noften pruritic, NO hemorrhagic\nfeatures usually"),
            ("Chest exam", "No specific findings; cough\nuncommon unless concurrent\ninfection"),
            ("Lymph nodes", "Mild or absent"),
            ("Travel hx", "CRITICAL: recent travel to\nendemic areas (Africa, Asia,\nCaribbean)"),
        ]
    },
    {
        "name": "TUBERCULOSIS\n(pulmonary +\njoint involvement)",
        "color": "#d99694",
        "findings": [
            ("Vital signs", "LOW-GRADE fever (afternoon spike),\nnight sweats, weight loss"),
            ("Chest exam", "Crackles apical (upper lobes),\ndull percussion if effusion,\nmay have minimal findings early"),
            ("Constitutional", "Profound weakness, fatigue,\nweight loss, malaise over weeks-months"),
            ("Joint exam", "Monoarticular or oligoarticular\n(hip, knee, ankle), warm, swollen,\nPoncet disease if rheumatic"),
            ("Lymph nodes", "Hilar or mediastinal (CXR),\nperipheral nodes possible"),
            ("Sputum", "Productive cough, may be\nblood-tinged (hemoptysis)"),
            ("Timeline", "CHRONIC onset (weeks-months),\nnot acute"),
        ]
    },
    {
        "name": "LEPTOSPIROSIS",
        "color": "#4472c4",
        "findings": [
            ("Vital signs", "Biphasic fever: high in 1st week,\nlull, then recurrence"),
            ("Chest exam", "Cough, possible pneumonia-like\nconsolidation (10-15% of cases)"),
            ("Joint/muscle pain", "Severe myalgias (especially\ncalves, shins), arthralgias,\nmarkedly painful"),
            ("Constitutional", "Headache, malaise, extreme weakness"),
            ("Renal signs", "If severe: jaundice, renal\ndysfunction (Weil disease),\nbleeding"),
            ("Eyes", "Conjunctival suffusion WITHOUT\nexudate (characteristic)"),
            ("Exposure hx", "CRITICAL: water exposure\n(floods, occupational), animal\ncontact (rodents, livestock)"),
        ]
    },
    {
        "name": "REACTIVE\nARTHRITIS\n(post-strep or\nother infection)",
        "color": "#ed7d31",
        "findings": [
            ("Vital signs", "Fever may be mild or absent"),
            ("Joint exam", "NON-MIGRATORY polyarthritis\n(asymmetric), usually lower\nlimbs (knees, ankles, feet)"),
            ("Onset", "Follows GI or GU infection by\n1-3 weeks (dysentery, chlamydia,\netc.) or respiratory infection"),
            ("Chest exam", "May have resolved respiratory\nsymptoms or lingering cough"),
            ("Conjunctivitis", "Possible (if Reiter variant)"),
            ("Urethritis", "May have dysuria history"),
            ("Rash", "Usually none; can have keratoderma\nblennorrhagicum"),
        ]
    },
    {
        "name": "ATYPICAL\nPNEUMONIA\n(Mycoplasma,\nLegionella)",
        "color": "#a9d08e",
        "findings": [
            ("Vital signs", "Fever, may be modest,\nmild tachypnea"),
            ("Chest exam", "Crackles/wheezing possible,\nbut often MINIMAL findings\ndespite significant infiltrate"),
            ("Constitutional", "Prominent headache, malaise,\nmyalgias, fatigue"),
            ("Joint pain", "Arthralgias/myalgias common,\nbut NOT primary complaint"),
            ("GI symptoms", "Nausea, diarrhea (esp. Legionella)"),
            ("Cough character", "Initially dry, becomes productive\nlater, may be prolonged"),
            ("CXR-exam mismatch", "CLASSIC: CXR shows consolidation\nbut minimal exam findings"),
        ]
    },
]

y_start = 131

for idx, dx in enumerate(diagnoses_page2):
    x = col_positions[idx % 4]
    y = y_start - (idx // 4) * 68
    
    # Diagnosis header
    diagnosis_box(ax, x, y - 2.5, col_w, 2.8, dx["name"], dx["color"])
    
    # Findings
    row_h = 8.0
    for i, (category, findings) in enumerate(dx["findings"]):
        finding_row(ax, x, y - 5.2 - i*row_h, col_w, row_h, category, findings)

# Footer: Key discriminators
footer_text = """
KEY DISCRIMINATORS:
• MIGRATORY joints + NEW cardiac murmur = ARF  |  • EMBOLIC signs (Osler/Janeway) + new murmur = IE  |  • MALAR rash + photosensitivity = SLE
• SEVERE disabling arthralgia + fatigue + travel to tropics = Chikungunya/Dengue  |  • CHRONIC (weeks-months) + weight loss = TB
• Normal exam with CXR infiltrate = Atypical pneumonia (Mycoplasma/Legionella)  |  • Post-infection +2-3wk lag = Reactive arthritis
"""
ax.text(50, 2.0, footer_text, ha="center", fontsize=8, color="#333333", 
        linespacing=1.4, bbox=dict(boxstyle="round,pad=0.8", facecolor="#fffacd", 
        edgecolor="#bf8f00", linewidth=1.5, alpha=0.9))

ax.text(50, 0.3, "Page 2 of 2: Less Common & Chronic Diagnoses  |  Use in conjunction with lab/imaging findings for definitive diagnosis",
        ha="center", fontsize=8.5, color="#555555", weight="bold", style="italic")

pdf.savefig(fig, bbox_inches="tight", pad_inches=0.3)
plt.close(fig)

pdf.close()
print("Saved:", OUT)
Running Command

cd /tmp/workspace/diagnostic-flowchart && python3 build_checklist.py && ls -la output/

The PDF checklist is built and verified. Here's the summary:

Clinical Exam Findings Checklist

PDF Document · PDF

2-page quick-reference checklist covering 10 differentials:
Page 1 - Most common/acute diagnoses:
  • Community-acquired pneumonia - crackles/bronchial breathing, tachypnea, no migratory joint findings
  • Acute rheumatic fever - migratory polyarthritis, new murmur, erythema marginatum, chorea (pathognomonic if present)
  • Infective endocarditis - Osler nodes, Janeway lesions, splinter hemorrhages, new/changing murmur, splenomegaly
  • SLE - malar rash, photosensitivity, non-erosive polyarthritis, pleuritis, renal findings
Page 2 - Additional/chronic diagnoses:
  • Dengue - high fever with relative bradycardia, severe "breakbone" arthralgia, rash on day 3-4
  • Chikungunya - severely debilitating polyarthritis, travel history critical
  • Tuberculosis - low-grade afternoon fever, weight loss, chronic monoarticular joint involvement
  • Leptospirosis - conjunctival suffusion without exudate, biphasic fever, calf myalgia, water exposure
  • Reactive arthritis - non-migratory asymmetric arthritis 1-3 weeks after GI/GU/respiratory infection
  • Atypical pneumonia (Mycoplasma/Legionella) - classic mismatch between CXR infiltrate and minimal exam findings
Each entry is organized by exam category (vitals, chest, joints, skin, heart, etc.) for fast bedside scanning, and page 2 ends with a "key discriminators" box summarizing the single most distinguishing sign for each condition (e.g., migratory joints + new murmur = rheumatic fever; embolic skin signs + murmur = endocarditis).
Findings are drawn from Harrison's Principles of Internal Medicine, Goldman-Cecil Medicine, Fuster and Hurst's The Heart, Fitzpatrick's Dermatology, and Tintinalli's Emergency Medicine.
This is an educational reference only - final diagnosis still requires correlating exam findings with the labs/imaging from the workup flowchart.
This is a shared conversation. Sign in to Orris to start your own chat.