Pleural effusion detailed topic and management
"pleural effusion"[MeSH Terms] AND management
| Mechanism | Example |
|---|---|
| Increased hydrostatic pressure | Congestive heart failure |
| Increased vascular permeability | Pneumonia, inflammatory states |
| Decreased oncotic pressure | Nephrotic syndrome, hypoalbuminemia |
| Decreased lymphatic drainage | Mediastinal carcinomatosis, malignancy |
| Decreased pleural space pressure | Atelectasis |
| Transdiaphragmatic movement | Hepatic hydrothorax, Meigs syndrome |
| Criterion | Threshold |
|---|---|
| Pleural fluid protein / Serum protein | > 0.5 |
| Pleural fluid LDH / Serum LDH | > 0.6 |
| Pleural fluid LDH | > 2/3 upper limit of normal serum LDH |

| Test | Interpretation |
|---|---|
| pH < 7.2 | Empyema, malignancy, esophageal rupture, RA/lupus/TB pleuritis |
| Glucose < 60 mg/dL | Infection, RA, TB, lupus, esophageal rupture |
| Amylase > 200 μg/dL | Pancreatic disease, esophageal rupture, malignancy, ruptured ectopic pregnancy |
| RBCs > 5,000/μL | Trauma, malignancy, PE |
| Triglycerides > 110 mg/dL | Chylothorax (TB, thoracic duct disruption) |
| ADA > 50 μg/L | Tuberculosis |
| RF, ANA, LE cells | Collagen vascular disease |
| Cytology/biopsy positive | Malignancy |
| Decreased complement | SLE, RA |
| Condition | Key Feature | Management |
|---|---|---|
| Urinothorax | Pleural fluid creatinine / serum creatinine > 1.0 | Relieve urinary obstruction |
| Meigs syndrome | Ovarian tumor + ascites + right PE | Tumor removal resolves effusion |
| Dressler syndrome | 3-30 days post-cardiac surgery/MI; left-sided | NSAIDs/colchicine |
| Asbestos effusion | Small, unilateral, serosanguineous | Rule out mesothelioma; monitor |
| Pseudochylous (cholesterol) effusion | White appearance, no chylomicrons | Treat underlying chronic effusion |
| PMID | Study | Finding |
|---|---|---|
| 39182102 | Surgery vs. fibrinolysis for complicated pleural infection (SR/MA, 2024) | Both effective; surgery may be preferred in selected cases |
| 39708436 | Management in mechanically ventilated patients (SR + guideline, 2025) | Drainage recommended for significant effusions; ultrasound guidance mandatory |
| 40294877 | Intrapleural fibrinolysis for loculated malignant PE (SR/MA, 2025) | Effective for improving drainage; emerging therapeutic option |
Create a clinical decision-making flowchart for diagnosing pleural effusion (transudate vs. exudate)
ls /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or not found"
mkdir -p /home/daytona/workspace/pleural-flowchart && python3 -c "import matplot…
~/pleural-flowchart/flowchart.py
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
fig, ax = plt.subplots(figsize=(22, 34))
ax.set_xlim(0, 22)
ax.set_ylim(0, 34)
ax.axis('off')
# ── colour palette ──────────────────────────────────────────────────────────
C_START = '#1A237E' # deep navy – start/end
C_STEP = '#1565C0' # blue – process step
C_DIAMOND = '#E65100' # deep orange– decision
C_TRANS = '#1B5E20' # dark green – transudate
C_EXUDATE = '#B71C1C' # dark red – exudate
C_CAUSES = '#4A148C' # purple – causes boxes
C_SPEC = '#00695C' # teal – specific tests
C_LIGHT = '#F57F17' # amber – Light's criteria highlight
C_BG = '#FAFAFA' # near-white background
fig.patch.set_facecolor('#F0F4F8')
ax.set_facecolor('#F0F4F8')
# ── helper functions ─────────────────────────────────────────────────────────
def box(ax, x, y, w, h, text, fc, tc='white', fs=10, bold=False,
shape='round,pad=0.1', border='white', lw=1.5, alpha=1.0):
bp = FancyBboxPatch((x - w/2, y - h/2), w, h,
boxstyle=shape, linewidth=lw,
edgecolor=border, facecolor=fc, alpha=alpha, zorder=3)
ax.add_patch(bp)
weight = 'bold' if bold else 'normal'
ax.text(x, y, text, ha='center', va='center', fontsize=fs,
color=tc, fontweight=weight, wrap=True,
multialignment='center', zorder=4,
linespacing=1.35)
def diamond(ax, x, y, w, h, text, fc=C_DIAMOND, tc='white', fs=9.5):
dx, dy = w/2, h/2
pts = [(x, y+dy), (x+dx, y), (x, y-dy), (x-dx, y)]
poly = plt.Polygon(pts, closed=True, facecolor=fc, edgecolor='white',
linewidth=1.5, zorder=3)
ax.add_patch(poly)
ax.text(x, y, text, ha='center', va='center', fontsize=fs,
color=tc, fontweight='bold', multialignment='center', zorder=4,
linespacing=1.3)
def arrow(ax, x1, y1, x2, y2, label='', lc='#37474F', lw=2.0,
label_side='right'):
ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
arrowprops=dict(arrowstyle='->', color=lc,
lw=lw, mutation_scale=18),
zorder=2)
if label:
mx, my = (x1+x2)/2, (y1+y2)/2
offset = 0.22 if label_side == 'right' else -0.22
ax.text(mx + offset, my, label, ha='center', va='center',
fontsize=8.5, color=lc, fontweight='bold', zorder=5,
bbox=dict(boxstyle='round,pad=0.15', fc='#ECEFF1',
ec=lc, lw=0.8, alpha=0.9))
def h_line(ax, x1, x2, y, lc='#37474F', lw=2.0):
ax.plot([x1, x2], [y, y], color=lc, lw=lw, zorder=2)
def v_line(ax, x, y1, y2, lc='#37474F', lw=2.0):
ax.plot([x, x], [y1, y2], color=lc, lw=lw, zorder=2)
# ── TITLE ────────────────────────────────────────────────────────────────────
ax.text(11, 33.3, 'Clinical Decision-Making Flowchart',
ha='center', va='center', fontsize=20, fontweight='bold',
color='#1A237E')
ax.text(11, 32.85, 'Diagnosis of Pleural Effusion: Transudate vs. Exudate',
ha='center', va='center', fontsize=13.5, color='#37474F',
fontstyle='italic')
# thin rule under title
ax.plot([1, 21], [32.55, 32.55], color='#90A4AE', lw=1.2)
# ── NODE POSITIONS (top → down) ──────────────────────────────────────────────
# 1. Patient presents
box(ax, 11, 32.1, 7.5, 0.65,
'Patient presents with suspected Pleural Effusion\n(Dyspnoea · Pleuritic chest pain · Incidental finding)',
C_START, fs=10, bold=True, shape='round,pad=0.15')
arrow(ax, 11, 31.77, 11, 31.3)
# 2. Clinical assessment
box(ax, 11, 31.0, 8.2, 0.52,
'History & Physical Examination\n'
'Percussion dullness · ↓ breath sounds · Absent fremitus · Tracheal shift',
C_STEP, fs=9.5, bold=False)
arrow(ax, 11, 30.74, 11, 30.25)
# 3. Chest X-ray
box(ax, 11, 29.95, 8.0, 0.52,
'Chest X-ray (upright PA + lateral)\n'
'>250 mL visible · Blunt costophrenic angle · Meniscus sign',
C_STEP, fs=9.5)
arrow(ax, 11, 29.69, 11, 29.2)
# 4. Confirm with imaging
box(ax, 11, 28.9, 8.5, 0.55,
'Confirm & Characterise ─ Ultrasound (≥5–10 mL; guides needle) | CT thorax (loculated? parenchymal Δ?)',
C_STEP, fs=9.2)
arrow(ax, 11, 28.62, 11, 28.05)
# ── D1: Obvious cause? ───────────────────────────────────────────────────────
diamond(ax, 11, 27.6, 5.6, 0.88,
'Obvious clinical cause\nof transudate present?\n(CHF / cirrhosis / nephrotic)',
C_DIAMOND, fs=9.2)
# YES → Treat underlying
arrow(ax, 13.8, 27.6, 16.5, 27.6, label='YES →', lc='#2E7D32')
box(ax, 18.5, 27.6, 3.6, 0.72,
'Treat underlying cause\n(diuresis, albumin…)\nMonitor response',
C_TRANS, fs=8.8, bold=False)
# NO ↓
arrow(ax, 11, 27.16, 11, 26.62, label='NO', lc='#C62828')
# ── D2: Thoracentesis ────────────────────────────────────────────────────────
box(ax, 11, 26.3, 7.8, 0.55,
'Thoracentesis (diagnostic + therapeutic)\n'
'Send: Protein · LDH · Glucose · pH · Cell count · Gram stain/Culture · Cytology',
C_STEP, fs=9.2, bold=True)
arrow(ax, 11, 26.02, 11, 25.45)
# ── LIGHT'S CRITERIA PANEL ───────────────────────────────────────────────────
# background panel
lc_panel = FancyBboxPatch((3.5, 24.35), 15, 1.0,
boxstyle='round,pad=0.1', linewidth=2,
edgecolor=C_LIGHT, facecolor='#FFF8E1', zorder=2)
ax.add_patch(lc_panel)
ax.text(11, 25.22, "LIGHT'S CRITERIA (any ONE criterion = Exudate)",
ha='center', va='center', fontsize=10.5, fontweight='bold',
color=C_LIGHT, zorder=4)
criteria = (
'① PF Protein / Serum Protein > 0.5 '
'② PF LDH / Serum LDH > 0.6 '
'③ PF LDH > ²⁄₃ × upper limit of normal serum LDH'
)
ax.text(11, 24.73, criteria, ha='center', va='center', fontsize=9,
color='#4E342E', zorder=4, multialignment='center')
arrow(ax, 11, 24.35, 11, 23.72)
# ── D3: Meets Light's criteria? ─────────────────────────────────────────────
diamond(ax, 11, 23.25, 5.6, 0.88,
'Meets Light\'s Criteria\n(≥1 criterion positive)?',
C_DIAMOND, fs=9.5)
# ── LEFT branch = TRANSUDATE ─────────────────────────────────────────────────
arrow(ax, 8.2, 23.25, 4.8, 23.25, label='← NO', lc='#1B5E20')
box(ax, 3.3, 23.25, 3.8, 0.65,
'TRANSUDATE\n(all 3 criteria negative)',
C_TRANS, fs=10.5, bold=True)
# edge case note
box(ax, 3.3, 22.3, 4.0, 0.72,
'⚠ If on diuretics:\ncheck serum-PF albumin gradient\n>1.2 g/dL → transudate',
'#2E7D32', tc='white', fs=8.3, bold=False, lw=1.2)
arrow(ax, 3.3, 22.93, 3.3, 22.67)
# Transudate causes
box(ax, 3.3, 21.2, 4.2, 1.6,
'CAUSES\n'
'• Heart failure (bilateral; R>L)\n'
'• Hepatic hydrothorax (cirrhosis)\n'
'• Nephrotic syndrome\n'
'• Atelectasis\n'
'• SVC obstruction\n'
'• Myxedema\n'
'• Peritoneal dialysis\n'
'• Urinothorax',
C_CAUSES, tc='white', fs=8.3, lw=1.2)
arrow(ax, 3.3, 21.93, 3.3, 22.02)
# Transudate Mx
box(ax, 3.3, 19.85, 4.0, 1.1,
'MANAGEMENT\n'
'• Treat underlying disease\n'
'• Diuretics (CHF/cirrhosis)\n'
'• Therapeutic thoracentesis\n'
' if symptomatic\n'
'• TIPS (refractory hydrothorax)',
C_TRANS, tc='white', fs=8.3, lw=1.2)
v_line(ax, 3.3, 20.96, 21.45)
ax.annotate('', xy=(3.3, 21.0), xytext=(3.3, 20.96),
arrowprops=dict(arrowstyle='->', color='#37474F', lw=2.0), zorder=2)
# ── RIGHT branch = EXUDATE ───────────────────────────────────────────────────
arrow(ax, 13.8, 23.25, 17.2, 23.25, label='YES →', lc='#C62828')
box(ax, 18.7, 23.25, 3.8, 0.65,
'EXUDATE\n(≥1 criterion positive)',
C_EXUDATE, fs=10.5, bold=True)
arrow(ax, 18.7, 22.93, 18.7, 22.35)
# ── SPECIFIC TESTS on exudate ────────────────────────────────────────────────
box(ax, 18.7, 22.0, 4.0, 0.62,
'Additional Specific Tests',
C_SPEC, fs=9.5, bold=True)
# test-result ladder (right side)
tests = [
('pH < 7.2', 'Empyema / Malignancy /\nOesophageal rupture / RA'),
('Glucose < 60 mg/dL', 'Infection · RA · TB · Lupus\nOesophageal rupture'),
('ADA > 50 U/L', 'TUBERCULOSIS\n(high sensitivity + specificity)'),
('Triglycerides >110 mg/dL', 'Chylothorax\n(thoracic duct disruption)'),
('Amylase > 200 U/dL', 'Pancreatitis /\nOesophageal rupture / Malignancy'),
('RBC > 5000/µL', 'Trauma · Malignancy · PE'),
('Cytology / Biopsy (+)', 'MALIGNANCY\n(cytology 60–90% sensitive)'),
('RF · ANA · LE cells', 'Collagen vascular disease\n(RA, SLE)'),
]
ty = 21.55
for test, result in tests:
ax.text(15.1, ty, f'▶ {test}', ha='left', va='center',
fontsize=7.9, color='#BF360C', fontweight='bold')
ax.text(15.1, ty - 0.25, f' → {result}', ha='left', va='center',
fontsize=7.7, color='#212121')
ty -= 0.7
# Exudate causes heading
ey = ty - 0.1
box(ax, 18.7, ey, 4.2, 0.48,
'MAIN EXUDATE CAUSES',
C_EXUDATE, fs=9, bold=True)
causes_text = (
'• Parapneumonic effusion / Empyema\n'
'• Malignancy (lung, breast, lymphoma,\n'
' mesothelioma, mets)\n'
'• Tuberculosis\n'
'• Pulmonary embolism\n'
'• RA / SLE / vasculitis\n'
'• Pancreatitis / subdiaphragmatic abscess\n'
'• Dressler syndrome\n'
'• Meigs syndrome\n'
'• Drug-induced · Sarcoidosis · Radiation'
)
box(ax, 18.7, ey - 1.15, 4.2, 1.78, causes_text,
C_CAUSES, tc='white', fs=7.9, lw=1.2)
# ── EXUDATE MANAGEMENT ───────────────────────────────────────────────────────
my = ey - 2.35
box(ax, 18.7, my, 4.2, 0.48,
'MANAGEMENT PRINCIPLES',
C_EXUDATE, fs=9, bold=True)
mgmt_text = (
'Parapneumonic/Empyema:\n'
' Simple → Antibiotics alone\n'
' Complicated (pH<7.2) → Chest tube\n'
' Loculated → Intrapleural fibrinolytics\n'
' Non-resolving → VATS / Decortication\n\n'
'Malignant:\n'
' Recurrent → Tunneled pleural catheter\n'
' or Talc pleurodesis\n\n'
'TB → Anti-TB chemotherapy ± steroids\n\n'
'PE → Anticoagulation\n\n'
'Chylothorax:\n'
' Low-fat diet / TPN; duct ligation'
)
box(ax, 18.7, my - 1.5, 4.2, 2.55, mgmt_text,
'#7B1FA2', tc='white', fs=7.8, lw=1.2)
# ── CENTRAL BOTTOM: AFTER CLASSIFICATION ─────────────────────────────────────
arrow(ax, 11, 22.81, 11, 21.6)
diamond(ax, 11, 21.15, 5.6, 0.82,
'Specific diagnosis\nestablished?',
C_DIAMOND, fs=9.5)
arrow(ax, 11, 20.74, 11, 20.15, label='YES', lc='#2E7D32')
box(ax, 11, 19.85, 6.0, 0.52,
'Treat specific underlying cause\n(see Transudate / Exudate management branches)',
'#37474F', fs=9, bold=False)
arrow(ax, 13.8, 21.15, 16.5, 21.15, label='NO →', lc='#C62828')
box(ax, 18.7, 21.15, 3.6, 0.65,
'Further investigation:\nBiopsy (CT/thoracoscopic)\nPET-CT · Bronchoscopy',
'#546E7A', fs=8.3, bold=False)
# ── VOLUME LIMIT REMINDER ─────────────────────────────────────────────────────
box(ax, 11, 19.1, 7.5, 0.52,
'⚠ Drain ≤1.5 L per session to prevent Re-expansion Pulmonary Oedema\n'
' Use ultrasound guidance for all thoracentesis procedures',
'#F57F17', tc='#1A237E', fs=8.5, bold=False,
shape='round,pad=0.1', border='#F57F17', lw=2.0)
# ── LEGEND ────────────────────────────────────────────────────────────────────
legend_items = [
(C_START, 'Start / End'),
(C_STEP, 'Process Step'),
(C_DIAMOND, 'Decision (diamond)'),
(C_TRANS, 'Transudate'),
(C_EXUDATE, 'Exudate'),
(C_CAUSES, 'Causes'),
(C_SPEC, 'Specific Tests'),
(C_LIGHT, "Light's Criteria"),
]
lx, ly = 1.2, 18.4
ax.text(lx, ly + 0.35, 'LEGEND', fontsize=9, fontweight='bold', color='#37474F')
for i, (col, label) in enumerate(legend_items):
rx = lx + (i % 4) * 4.0
ry = ly - (i // 4) * 0.6
rect = FancyBboxPatch((rx, ry - 0.18), 0.48, 0.36,
boxstyle='round,pad=0.04', facecolor=col,
edgecolor='white', linewidth=1, zorder=3)
ax.add_patch(rect)
ax.text(rx + 0.62, ry, label, fontsize=8, va='center', color='#212121')
# ── FOOTER ────────────────────────────────────────────────────────────────────
ax.plot([1, 21], [17.55, 17.55], color='#90A4AE', lw=1)
ax.text(11, 17.3,
'Sources: Goldman-Cecil Medicine (26th ed.) · Murray & Nadel Respiratory Medicine · '
'Light RW criteria (1972) · BTS Guidelines',
ha='center', va='center', fontsize=7.5, color='#607D8B', fontstyle='italic')
ax.text(11, 17.0,
'LDH = lactate dehydrogenase · PF = pleural fluid · ADA = adenosine deaminase · '
'TIPS = transjugular intrahepatic portosystemic shunt · VATS = video-assisted thoracoscopic surgery',
ha='center', va='center', fontsize=7.2, color='#78909C', fontstyle='italic')
plt.tight_layout(pad=0.3)
plt.savefig('/home/daytona/workspace/pleural-flowchart/pleural_effusion_flowchart.png',
dpi=180, bbox_inches='tight', facecolor=fig.get_facecolor())
print("Saved successfully")
cd /home/daytona/workspace/pleural-flowchart && python3 flowchart.py 2>&1
ls -lh /home/daytona/workspace/pleural-flowchart/pleural_effusion_flowchart.png …