Describe in detail the epidemiology, clinical features and diagnosis of dengue.
dengue fever epidemiology clinical features diagnosis
Continue


| Parameter | Finding |
|---|---|
| WBC | Leukopenia (a consistent and early feature) |
| Platelet count | Thrombocytopenia; <100,000/µL is a key marker of critical phase |
| Haematocrit | Rising >20% above baseline = plasma leakage; falling in recovery = dilution |
| Liver enzymes | AST and ALT elevated; AST >ALT is characteristic |
| Coagulation | Prolonged PT/aPTT in severe/DHF cases |
| Phase | Day of illness | Preferred test(s) |
|---|---|---|
| Early febrile / viremic | Days 1-5 (up to day 7-10) | RT-PCR and/or NS1 antigen detection |
| Late / post-febrile | Day 5 onwards | IgM antibody (MAC-ELISA) |
| Combined (single sample, days 1-10) | First 10 days | NS1 Ag + IgM together (identifies ≥90% of cases) |
| Paired sera | Acute (days 1-5) + convalescent (day 15-21) | IgG seroconversion (≥4-fold rise) |
| Sample timing | Method | Time to result |
|---|---|---|
| Acute serum (days 1-5) | RT-PCR / real-time RT-PCR | 1-2 days |
| Acute serum (days 1-5) | NS1 Ag rapid test | Minutes |
| Acute serum (days 1-5) | NS1 Ag ELISA | ~1 day |
| After day 5 | IgM ELISA | 1-2 days |
| After day 5 | IgM rapid test | Minutes |
| Paired sera (days 1-5 and days 15-21) | IgM or IgG seroconversion by ELISA/HIA/NT | 1-2 days (ELISA); ≥7 days (HIA/NT) |
Make pdf
ls -la /tmp/workspace/ 2>/dev/null || mkdir -p /tmp/workspace && ls -la /tmp/workspace/
mkdir -p /tmp/workspace/dengue-pdf && python3 - << 'PYEOF' # Download the two images first import urllib.request import os img_dir = "/tmp/workspace/dengue-pdf/images" os.makedirs(img_dir, exist_ok=True) imgs = { "classification.png": "https://cdn.orris.care/cdss_images/7862964ddaf9374fe035b0bc306c36ed0ccd26adb636d94646bc1025e16a71cd.png", "course.png": "https://cdn.orris.care/cdss_images/c45be6c09edb59e271decc0c66983b522e803c53c55b63a305caa715d9e1507b.png", } for name, url in imgs.items(): path = os.path.join(img_dir, name) urllib.request.urlretrieve(url, path) size = os.path.getsize(path) print(f"Downloaded {name}: {size} bytes") print("Images ready.") PYEOF
~/dengue-pdf/build_pdf.py
"""
Build a detailed PDF report on Dengue: Epidemiology, Clinical Features and Diagnosis
Using ReportLab for full layout control.
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, Image, PageBreak, KeepTogether
)
from reportlab.platypus.tableofcontents import TableOfContents
from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor
import os
OUTPUT = "/tmp/workspace/dengue-pdf/Dengue_Epidemiology_Clinical_Diagnosis.pdf"
IMG_DIR = "/tmp/workspace/dengue-pdf/images"
# ── Colour palette ─────────────────────────────────────────────────────────────
C_TITLE = HexColor("#1a3a5c") # deep navy
C_H1 = HexColor("#1a3a5c") # same navy for H1
C_H2 = HexColor("#c0392b") # deep red for H2
C_H3 = HexColor("#2c7bb6") # steel blue for H3
C_ACCENT = HexColor("#e8f0f7") # light blue tint for shaded rows
C_RULE = HexColor("#c0392b")
C_SOURCE = HexColor("#666666")
C_WHITE = colors.white
C_BLACK = colors.black
W, H = A4
LMARGIN = 2.2*cm
RMARGIN = 2.2*cm
TMARGIN = 2.5*cm
BMARGIN = 2.5*cm
BODY_W = W - LMARGIN - RMARGIN
# ── Styles ─────────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
style_title = S("DocTitle",
fontName="Helvetica-Bold", fontSize=26, leading=32,
textColor=C_WHITE, alignment=TA_LEFT, spaceAfter=4)
style_subtitle = S("DocSubtitle",
fontName="Helvetica", fontSize=13, leading=18,
textColor=HexColor("#d0e4f5"), alignment=TA_LEFT, spaceAfter=2)
style_date = S("DocDate",
fontName="Helvetica", fontSize=10, leading=14,
textColor=HexColor("#b0c8e0"), alignment=TA_LEFT)
style_h1 = S("H1",
fontName="Helvetica-Bold", fontSize=15, leading=20,
textColor=C_H1, spaceBefore=18, spaceAfter=6,
borderPad=4)
style_h2 = S("H2",
fontName="Helvetica-Bold", fontSize=12, leading=16,
textColor=C_H2, spaceBefore=12, spaceAfter=4)
style_h3 = S("H3",
fontName="Helvetica-BoldOblique", fontSize=10.5, leading=14,
textColor=C_H3, spaceBefore=8, spaceAfter=3)
style_body = S("Body",
fontName="Helvetica", fontSize=9.5, leading=14,
textColor=C_BLACK, alignment=TA_JUSTIFY,
spaceAfter=5, spaceBefore=2)
style_bullet = S("Bullet",
fontName="Helvetica", fontSize=9.5, leading=13,
textColor=C_BLACK, leftIndent=14, firstLineIndent=-10,
spaceAfter=2, spaceBefore=1,
bulletIndent=4)
style_sub_bullet = S("SubBullet",
fontName="Helvetica", fontSize=9, leading=12,
textColor=HexColor("#333333"), leftIndent=28, firstLineIndent=-10,
spaceAfter=1)
style_caption = S("Caption",
fontName="Helvetica-Oblique", fontSize=8.5, leading=12,
textColor=C_SOURCE, alignment=TA_CENTER, spaceAfter=6)
style_source = S("Source",
fontName="Helvetica-Oblique", fontSize=7.5, leading=10,
textColor=C_SOURCE)
style_table_hdr = S("TblHdr",
fontName="Helvetica-Bold", fontSize=8.5, leading=11,
textColor=C_WHITE, alignment=TA_CENTER)
style_table_cell = S("TblCell",
fontName="Helvetica", fontSize=8.5, leading=11,
textColor=C_BLACK, alignment=TA_LEFT)
style_table_cell_c = S("TblCellC",
fontName="Helvetica", fontSize=8.5, leading=11,
textColor=C_BLACK, alignment=TA_CENTER)
# ── Helper – bullet item ───────────────────────────────────────────────────────
def bullet(text, sub=False):
st = style_sub_bullet if sub else style_bullet
return Paragraph(f"• {text}", st)
def rule():
return HRFlowable(width="100%", thickness=1.2, color=C_RULE, spaceAfter=6, spaceBefore=2)
def section_rule():
return HRFlowable(width="100%", thickness=0.4, color=HexColor("#cccccc"), spaceAfter=4, spaceBefore=2)
# ── Page templates ─────────────────────────────────────────────────────────────
class DenguePDF(SimpleDocTemplate):
def __init__(self, filename):
super().__init__(
filename,
pagesize=A4,
leftMargin=LMARGIN, rightMargin=RMARGIN,
topMargin=TMARGIN, bottomMargin=BMARGIN,
title="Dengue: Epidemiology, Clinical Features and Diagnosis",
author="Orris Medical AI",
subject="Infectious Disease – Dengue"
)
self.page_num = 0
def handle_pageBegin(self):
self.page_num += 1
super().handle_pageBegin()
def footer_canvas(canvas_obj, doc):
canvas_obj.saveState()
canvas_obj.setFont("Helvetica", 7.5)
canvas_obj.setFillColor(C_SOURCE)
pg = canvas_obj.getPageNumber()
# skip cover page footer
if pg > 1:
canvas_obj.drawString(LMARGIN, 1.4*cm, "Dengue: Epidemiology, Clinical Features and Diagnosis")
canvas_obj.drawRightString(W - RMARGIN, 1.4*cm, f"Page {pg}")
canvas_obj.setStrokeColor(HexColor("#cccccc"))
canvas_obj.setLineWidth(0.4)
canvas_obj.line(LMARGIN, 1.6*cm, W - RMARGIN, 1.6*cm)
canvas_obj.restoreState()
# ── Cover page flowable ────────────────────────────────────────────────────────
class CoverPage:
"""Drawn directly via canvas at build time."""
pass
def cover_drawing(canvas_obj, doc):
"""First-page background + text drawn before any flowables."""
pass # We will build cover as a Table instead for simplicity
# ── Build document ─────────────────────────────────────────────────────────────
story = []
# ── COVER ──────────────────────────────────────────────────────────────────────
cover_data = [[
Paragraph("DENGUE", style_title),
""
],[
Paragraph("Epidemiology · Clinical Features · Diagnosis", style_subtitle),
""
],[
Paragraph("A Comprehensive Medical Review", style_date),
""
],[
Paragraph("Sources: Harrison's · Goldman-Cecil · Red Book 2021 · Rosen's Emergency Medicine · Park's Preventive Medicine · Robbins Pathology", style_date),
""
]]
cover_table = Table(cover_data, colWidths=[BODY_W, 0])
cover_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_TITLE),
("TOPPADDING", (0,0), (-1,0), 30),
("BOTTOMPADDING",(0,-1),(-1,-1), 30),
("LEFTPADDING", (0,0), (-1,-1), 20),
("RIGHTPADDING",(0,0), (-1,-1), 20),
("ROWBACKGROUNDS",(0,0),(-1,-1),[C_TITLE]),
]))
story.append(cover_table)
story.append(Spacer(1, 0.5*cm))
# Thin red rule under cover
story.append(HRFlowable(width="100%", thickness=4, color=C_H2, spaceAfter=20))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 1 – EPIDEMIOLOGY
# ═══════════════════════════════════════════════════════════════════════════════
story.append(Paragraph("1. EPIDEMIOLOGY", style_h1))
story.append(rule())
# 1.1 The Pathogen
story.append(Paragraph("1.1 The Pathogen", style_h2))
story.append(Paragraph(
"Dengue is caused by four antigenically distinct but closely related RNA viruses — DENV-1, DENV-2, DENV-3, "
"and DENV-4 — all members of the genus <i>Flavivirus</i>, family <i>Flaviviridae</i>. The envelope protein "
"varies by as much as 30–40% among serotypes, which is the structural basis for the non-neutralizing "
"cross-reactive antibody reactions that underlie severe disease in secondary infection.",
style_body))
story.append(Paragraph(
"<i>Source: Goldman-Cecil Medicine, p. 1529</i>", style_source))
story.append(Spacer(1, 4))
# 1.2 Global Burden
story.append(Paragraph("1.2 Global Burden", style_h2))
stats = [
["Metric", "Figure"],
["Annual dengue infections (estimated)", "390 million"],
["Clinically apparent infections/year", "96 million"],
["Hospitalizations/year", "~500,000"],
["Deaths/year", "~20,000"],
["People at risk globally", "3.9 billion in 128 countries"],
["Asymptomatic fraction", "~75%"],
["Symptomatic fraction", "~25%"],
]
t = Table(stats, colWidths=[BODY_W*0.65, BODY_W*0.35])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_TITLE),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_ACCENT]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("ALIGN", (1,0), (1,-1), "CENTER"),
]))
story.append(t)
story.append(Paragraph("<i>Sources: Red Book 2021, p. 522; Robbins Pathology, p. 335</i>", style_source))
story.append(Spacer(1, 6))
story.append(Paragraph(
"The disease is endemic and hyperendemic across the tropical and subtropical belt, with the highest burden in "
"Southeast Asia, the Western Pacific, and Central and South America. Within the United States, dengue is "
"endemic in Puerto Rico (3,000–27,000 cases/year), the US Virgin Islands, Guam, American Samoa, and the "
"Northern Mariana Islands. Local transmission outbreaks have occurred in Texas, Hawaii, and Florida. "
"Dengue is the <b>leading cause of febrile illness</b> in travelers returning from the Caribbean, Latin America, "
"and South Asia.",
style_body))
# 1.3 Vector and Transmission
story.append(Paragraph("1.3 Vector and Transmission", style_h2))
story.append(Paragraph(
"The principal vector is <b><i>Aedes aegypti</i></b>, a highly domestic, endophilic, endophagic day-biting mosquito. "
"<i>Aedes albopictus</i> (the tiger mosquito) and <i>Aedes polynesiensis</i> serve as secondary vectors. "
"Humans are the main amplifying host. The transmission cycle is strictly human → mosquito → human — no direct "
"person-to-person spread occurs.",
style_body))
story.append(Paragraph("<b>Incubation periods:</b>", style_h3))
inc_data = [
["Period", "Duration", "Notes"],
["Extrinsic (in mosquito)", "8–12 days", "Mosquito remains infectious for life thereafter"],
["Intrinsic (in human)", "3–14 days (commonly 5–6 days)", "Viremia begins 1–2 days before symptom onset"],
]
t2 = Table(inc_data, colWidths=[BODY_W*0.30, BODY_W*0.38, BODY_W*0.32])
t2.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_H3),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_ACCENT]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
]))
story.append(t2)
story.append(Spacer(1, 6))
story.append(Paragraph("<b>Other (rare) transmission routes:</b>", style_h3))
for item in [
"Vertical (transplacental/perinatal) — rate ~20%, higher when maternal dengue occurs near delivery",
"Breastfeeding, blood transfusion, or organ donation",
"Needlestick or mucocutaneous healthcare-associated exposure",
"Sexual transmission (rare)",
]:
story.append(bullet(item))
story.append(Spacer(1, 4))
# 1.4 Environmental & Social Determinants
story.append(Paragraph("1.4 Environmental and Social Determinants", style_h2))
story.append(Paragraph(
"<i>Ae. aegypti</i> breeds in peridomestic containers of fresh standing water — discarded tires, flower vases, "
"water storage jars, and even millimetre-deep indentations at the base of porcelain toilet bowls. Its population "
"fluctuates with rainfall and water storage practices. It survives best at <b>16–30°C and 60–80% relative "
"humidity</b>. A 2°C rise in ambient temperature shortens the extrinsic incubation period and increases mosquito "
"biting frequency, amplifying transmission.",
style_body))
story.append(Paragraph(
"Key social risk factors include: overcrowding, lack of piped water (driving storage practices), poor sanitation, "
"absence of window screens and air conditioning, and inadequate urban infrastructure. Incidence is highest from "
"<b>July to September</b> in endemic areas.",
style_body))
story.append(Paragraph("<i>Source: Park's Preventive Medicine, p. 290; Harrison's, p. 3901</i>", style_source))
story.append(Spacer(1, 4))
# 1.5 Epidemiology of Severe Disease
story.append(Paragraph("1.5 Epidemiology of Severe Disease and Antibody-Dependent Enhancement", style_h2))
story.append(Paragraph(
'The disease follows an <b>"iceberg" (pyramid) pattern</b>: at the base are asymptomatic infections (~75%), '
"then undifferentiated fever, classical dengue fever (DF), dengue haemorrhagic fever (DHF), and at the apex, "
"dengue shock syndrome (DSS).",
style_body))
story.append(Paragraph(
"Infection with one serotype produces lifelong immunity to that serotype, plus a period of cross-protection "
"against the other three (lasting 1–3 years). After this window, secondary infection with a different serotype "
"markedly increases the risk of severe disease via <b>antibody-dependent enhancement (ADE)</b> — cross-reactive "
"non-neutralizing antibodies from the first infection enhance viral uptake into macrophages via Fc receptors. "
"Only 2–4% of individuals experiencing sequential infections develop severe disease.",
style_body))
story.append(Paragraph(
"Severe dengue is most commonly associated with <b>DENV-2</b> in secondary infections. High-risk groups for "
"severe disease include <b>infants</b> (with passively acquired maternal antibodies), <b>pregnant women</b>, "
"the elderly, and patients with chronic conditions (asthma, diabetes, sickle cell anaemia, liver cirrhosis, "
"G6PD deficiency).",
style_body))
story.append(Paragraph("<i>Source: Red Book 2021, p. 521; Park's, p. 290</i>", style_source))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 2 – CLINICAL FEATURES
# ═══════════════════════════════════════════════════════════════════════════════
story.append(Paragraph("2. CLINICAL FEATURES", style_h1))
story.append(rule())
# Classification figure
story.append(Paragraph("2.1 Classification of Dengue Virus Infection", style_h2))
story.append(Paragraph(
"The <b>WHO 2009 classification</b> (superseding the older DF/DHF/DSS system) divides dengue into three "
"severity tiers, which are more operationally useful for triage:",
style_body))
# WHO 2009 classification table
who_data = [
["Category", "Criteria"],
["Dengue WITHOUT warning signs",
"Fever + ≥2 of: nausea/vomiting, rash, aches and pains, leukopenia, or positive tourniquet test"],
["Dengue WITH warning signs",
"Above + any of: abdominal pain/tenderness, persistent vomiting, clinical fluid accumulation, "
"mucosal bleeding, lethargy/restlessness, liver enlargement >2 cm, rapid platelet decline"],
["SEVERE dengue",
"Any of: severe plasma leakage (shock or respiratory distress); severe bleeding; severe organ "
"involvement (AST/ALT ≥1000 IU/L, impaired consciousness, cardiac/organ failure)"],
]
tw = Table(who_data, colWidths=[BODY_W*0.38, BODY_W*0.62])
tw.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_TITLE),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_ACCENT, HexColor("#fde8e8")]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
("FONTNAME", (0,3), (0,3), "Helvetica-Bold"),
("TEXTCOLOR", (0,3), (0,3), C_H2),
]))
story.append(tw)
story.append(Paragraph("<i>Source: Red Book 2021, p. 520</i>", style_source))
story.append(Spacer(1, 8))
# Classification diagram
img_class = Image(os.path.join(IMG_DIR, "classification.png"), width=BODY_W*0.85, height=8*cm)
img_class.hAlign = "CENTER"
story.append(img_class)
story.append(Paragraph(
"Fig. 1 — Manifestations of dengue virus infection (classification tree). "
"Source: Park's Textbook of Preventive and Social Medicine.",
style_caption))
story.append(Spacer(1, 6))
# 2.2 Three Phases
story.append(Paragraph("2.2 The Three Phases of Dengue Illness", style_h2))
# Course diagram
img_course = Image(os.path.join(IMG_DIR, "course.png"), width=BODY_W*0.72, height=10*cm)
img_course.hAlign = "CENTER"
story.append(img_course)
story.append(Paragraph(
"Fig. 2 — The course of dengue illness: temperature curve, potential clinical issues, laboratory changes "
"(haematocrit and platelets), and serology/virology (viraemia and IgM/IgG) across the febrile, critical, "
"and recovery phases. Source: Park's Textbook of Preventive and Social Medicine.",
style_caption))
story.append(Spacer(1, 8))
# Phase 1
story.append(Paragraph("Phase 1: Febrile Phase (Days 1–7)", style_h3))
story.append(Paragraph(
"Following the incubation period, illness begins <b>abruptly</b> with high fever (39–40°C, occasionally "
"40–41°C) with chills and facial flushing. Classic features include:",
style_body))
for item in [
"<b>Severe headache</b> (often frontal) and <b>retro-orbital pain</b> — particularly on eye movement or pressure; photophobia develops within 24 hours",
"<b>Severe myalgias and arthralgias</b> — the 'breakbone fever' description reflects the intense bone and joint pain",
"<b>Nausea, vomiting, anorexia</b>, altered taste sensation, epigastric discomfort",
"<b>Maculopapular rash</b> (often rubelliform — 'islands of white in a sea of red') — may appear early or late",
"<b>Conjunctival injection</b>, injected oropharynx, lymphadenopathy",
"<b>Petechiae</b> — dorsum of feet, legs, axillae, palate; positive tourniquet test",
"<b>Leukopenia</b> — a consistent and early finding",
"<b>Bifid ('saddleback') fever</b> — initial fever, brief remission of hours to 2 days, then a second peak before defervescence",
]:
story.append(bullet(item))
story.append(Paragraph(
"<b>Tourniquet (Rumpel-Leede) test:</b> Inflate BP cuff to the midpoint between systolic and diastolic pressure "
"for 5 minutes. Positive = ≥10 petechiae per 2.5×2.5 cm. In DHF, typically ≥20 petechiae. "
"<i>(Source: Park's, p. 291)</i>",
style_body))
# Phase 2
story.append(Paragraph("Phase 2: Critical Phase (Days 3–7; duration 24–48 hours)", style_h3))
story.append(Paragraph(
"This phase coincides with <b>defervescence</b> (temperature dropping to ≤37.5–38°C) and is paradoxically the "
"most dangerous period. Increased capillary permeability develops, manifesting as:",
style_body))
for item in [
"<b>Rising haematocrit</b> (≥20% above baseline = significant plasma leakage)",
"<b>Rapid fall in platelet count</b> (often <100,000/µL)",
"<b>Progressive leukopenia</b>",
"<b>Pleural effusion</b> (predominantly right-sided), ascites, pericardial effusion",
"<b>Gallbladder oedema</b> — early ultrasound sign preceding plasma leakage",
]:
story.append(bullet(item))
story.append(Paragraph(
"Patients who <b>do not</b> develop increased capillary permeability improve during this phase. Those who do "
"may progress to:",
style_body))
for item in [
"<b>Hypovolemic shock (DSS)</b> — tachycardia, cool extremities, delayed capillary refill, weak pulse, pulse pressure ≤20 mmHg (e.g., 100/80 mmHg), then frank hypotension",
"<b>Haemorrhagic manifestations</b> — petechiae, ecchymoses, gingival bleeding, epistaxis, haematemesis, melaena, haematuria",
"<b>Organ impairment</b> — hepatitis (AST>ALT), coagulopathy/DIC, encephalopathy, myocarditis, pancreatitis",
]:
story.append(bullet(item))
story.append(Paragraph("<b>Warning signs of progression to severe dengue:</b>", style_h3))
ws_data = [
["Warning Sign", "Significance"],
["Abdominal pain or tenderness", "Hepatomegaly/peritoneal irritation from ascites"],
["Persistent vomiting", "Prevents oral rehydration; suggests severity"],
["Clinical fluid accumulation", "Pleural effusion, ascites — marker of plasma leakage"],
["Mucosal bleeding", "Haemostatic failure"],
["Lethargy or restlessness", "Reduced cerebral perfusion"],
["Liver enlargement >2 cm", "Hepatic involvement"],
["Rapid platelet decline + rising haematocrit", "Most important combined indicator of critical phase"],
]
tw2 = Table(ws_data, colWidths=[BODY_W*0.42, BODY_W*0.58])
tw2.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_H2),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, HexColor("#fff5f5")]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
("FONTNAME", (0,-1), (-1,-1), "Helvetica-Bold"),
]))
story.append(tw2)
story.append(Paragraph("<i>Source: Goldman-Cecil, p. 1543; Red Book 2021, p. 489</i>", style_source))
story.append(Spacer(1, 6))
# Phase 3
story.append(Paragraph("Phase 3: Recovery (Convalescence) Phase (Days 7–10+)", style_h3))
for item in [
"Reabsorption of extravascular fluid — haematocrit falls (dilutional effect), platelets recover",
"Bradycardia is common",
"Risk of <b>fluid overload</b> if excessive IV fluids were given during critical phase",
"Broad-based convalescent rash — confluent petechiae with islands of sparing",
"Fatigue and malaise may persist for weeks",
]:
story.append(bullet(item))
story.append(Spacer(1, 6))
# DHF Grading
story.append(Paragraph("2.3 Classical WHO Grading of DHF / DSS", style_h2))
story.append(Paragraph(
"The older WHO DHF diagnostic criteria require <b>all four</b> of: (1) fever 2–7 days, "
"(2) haemorrhagic tendency, (3) thrombocytopenia (≤100,000/µL), and "
"(4) evidence of increased vascular permeability (haematocrit rise ≥20%, pleural effusion, ascites, or "
"hypoalbuminaemia).",
style_body))
grade_data = [
["Grade", "Features"],
["Grade I", "Fever + positive tourniquet test only (no spontaneous bleeding)"],
["Grade II", "Grade I + spontaneous bleeding (skin or other haemorrhages)"],
["Grade III\n(DSS)", "Signs of circulatory failure: weak/rapid pulse, narrowing pulse pressure, hypotension, cold clammy skin"],
["Grade IV\n(DSS)", "Profound shock — undetectable BP and pulse"],
]
tg = Table(grade_data, colWidths=[BODY_W*0.18, BODY_W*0.82])
tg.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_TITLE),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_ACCENT, HexColor("#fff0e0"), HexColor("#fde8e8")]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (0,0), (0,-1), "CENTER"),
("FONTNAME", (0,3), (0,4), "Helvetica-Bold"),
("TEXTCOLOR", (0,3), (0,4), C_H2),
]))
story.append(tg)
story.append(Paragraph(
"Grades III and IV constitute Dengue Shock Syndrome (DSS). <i>Source: Park's, p. 293</i>", style_source))
story.append(Spacer(1, 6))
# 2.4 Expanded/Less Common Syndromes
story.append(Paragraph("2.4 Expanded Dengue Syndrome (Unusual Manifestations)", style_h2))
story.append(Paragraph(
"Even without classical plasma leakage, dengue can cause isolated organopathy:",
style_body))
for item in [
"<b>Neurological:</b> acute meningoencephalitis, Guillain-Barré syndrome, ADEM, transverse myelitis",
"<b>Cardiac:</b> myocarditis, arrhythmias",
"<b>Hepatic:</b> hepatitis (severe cases: AST>>ALT); rarely fulminant liver failure",
"<b>Renal:</b> acute kidney injury",
"<b>Haemophagocytic lymphohistiocytosis (HLH)</b> — rare but life-threatening",
"<b>Ophthalmic:</b> maculopathy, retinal haemorrhage",
]:
story.append(bullet(item))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 3 – DIAGNOSIS
# ═══════════════════════════════════════════════════════════════════════════════
story.append(Paragraph("3. DIAGNOSIS", style_h1))
story.append(rule())
story.append(Paragraph("3.1 When to Suspect Dengue", style_h2))
story.append(Paragraph(
"Any patient with <b>acute febrile illness (2–7 days)</b> in an endemic area, or a returned traveler from the "
"tropics/subtropics, with two or more of: severe headache, retro-orbital pain, myalgias/arthralgias, rash, "
"leukopenia, and/or thrombocytopenia. Dengue is the <b>leading cause of febrile illness</b> in travelers "
"returning from the Caribbean, Latin America, and South Asia.",
style_body))
story.append(Paragraph("<i>Source: Red Book 2021, p. 503</i>", style_source))
story.append(Spacer(1, 4))
# Differential
story.append(Paragraph("3.2 Differential Diagnosis", style_h2))
diff_data = [
["Condition", "Distinguishing Features"],
["Malaria", "Peripheral blood smear/RDT; cyclical fever; more prominent rigors"],
["Chikungunya", "Prominent polyarthritis (often persists); less thrombocytopenia"],
["Zika virus", "Conjunctivitis; milder illness; teratogenicity; sexual transmission"],
["Leptospirosis", "Weil's disease (jaundice + renal failure); water/soil exposure; conjunctival suffusion"],
["Rickettsial infections", "Eschar; rash centripetal → centrifugal; tick exposure"],
["Viral haemorrhagic fevers", "Ebola/Marburg: nosocomial spread; yellow fever: jaundice; epidemiological context"],
["Typhoid fever", "Relative bradycardia; rose spots; positive blood culture/Widal; splenomegaly"],
["Measles", "Koplik spots; coryza; cough; confluent rash — important in returned traveler"],
]
tdiff = Table(diff_data, colWidths=[BODY_W*0.30, BODY_W*0.70])
tdiff.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_TITLE),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_ACCENT]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(tdiff)
story.append(Paragraph("<i>Source: Rosen's Emergency Medicine, p. 2630</i>", style_source))
story.append(Spacer(1, 8))
# 3.3 Routine Haematology
story.append(Paragraph("3.3 Routine Laboratory Investigations", style_h2))
lab_data = [
["Parameter", "Finding", "Clinical Significance"],
["WBC", "Leukopenia", "Consistent early feature; progressive during febrile phase"],
["Platelet count", "Thrombocytopenia (<100,000/µL)", "Key marker of critical phase onset"],
["Haematocrit", "Rising ≥20% above baseline", "Plasma leakage / haemoconcentration"],
["Haematocrit in recovery", "Falls (dilution)", "Risk of fluid overload"],
["AST / ALT", "Both elevated; AST > ALT characteristic", "Hepatic involvement"],
["PT / aPTT", "Prolonged in DHF/DSS", "DIC and coagulopathy"],
["Albumin", "Hypoalbuminaemia", "Plasma protein loss via leakage"],
]
tlab = Table(lab_data, colWidths=[BODY_W*0.25, BODY_W*0.30, BODY_W*0.45])
tlab.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_H3),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_ACCENT]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(tlab)
story.append(Paragraph("<i>Source: Goldman-Cecil, p. 1548; Rosen's Emergency Medicine, p. 2630</i>", style_source))
story.append(Spacer(1, 8))
# 3.4 Specific Diagnostic Tests
story.append(Paragraph("3.4 Specific Diagnostic Tests", style_h2))
story.append(Paragraph(
"The choice of test depends critically on the <b>day of illness</b> at which the sample is collected. "
"The key principle: <b>virological tests (RT-PCR, NS1)</b> are used in the first 5–7 days; "
"<b>serological tests (IgM)</b> from day 5 onwards.",
style_body))
story.append(Spacer(1, 4))
# Timing matrix
timing_data = [
["Phase", "Day of Illness", "Preferred Test(s)"],
["Early febrile / viremic", "Days 1–5\n(up to day 7–10)", "RT-PCR and/or NS1 antigen detection"],
["Late / post-febrile", "Day 5 onwards", "IgM antibody (MAC-ELISA)"],
["Combined (single sample)", "Days 1–10", "NS1 Ag + IgM together\n(identifies ≥90% of cases)"],
["Paired sera (confirmation)", "Acute days 1–5\n+ Convalescent day 15–21", "IgG seroconversion (≥4-fold rise)"],
]
ttiming = Table(timing_data, colWidths=[BODY_W*0.28, BODY_W*0.25, BODY_W*0.47])
ttiming.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_TITLE),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_ACCENT, C_WHITE, C_ACCENT]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(ttiming)
story.append(Spacer(1, 8))
# Individual tests
story.append(Paragraph("1. Viral Nucleic Acid Detection — RT-PCR", style_h3))
story.append(Paragraph(
"Reverse-transcriptase PCR and real-time RT-PCR detect dengue RNA in serum during the <b>viremic phase "
"(days 1–7)</b>. They offer high sensitivity and specificity, allow serotyping, and have rapid turnaround "
"(1–2 days). This is the gold standard for early diagnosis.",
style_body))
story.append(Paragraph("2. NS1 Antigen Detection", style_h3))
story.append(Paragraph(
"Nonstructural protein 1 (NS1) is a dengue-specific glycoprotein secreted into the bloodstream at high "
"levels during early infection. It is detectable from the <b>onset of fever to day 6–9</b>. Rapid "
"immunochromatographic NS1 assays give results in minutes; NS1 ELISA in ~1 day. NS1 is detectable in both "
"primary and secondary infections and fills the diagnostic gap when IgM is still negative in the first few "
"days. Note: commercial kits do not differentiate serotypes.",
style_body))
story.append(Paragraph("3. Serological Tests — IgM and IgG", style_h3))
sero_data = [
["Test", "Detectable from", "Notes"],
["IgM (MAC-ELISA)", "Day 3–5; 99% positive by day 10", "Peaks at 2 weeks; declines over 2–3 months; cross-reacts with Zika, West Nile, yellow fever, JE"],
["IgG", "Slightly later than IgM in primary; rises rapidly (before IgM) in secondary", "Remains elevated for life; can be falsely positive after other flaviviral infections or vaccination"],
["IgM/IgG ratio", "After day 5", "High ratio = primary infection; low ratio = secondary infection"],
["Paired IgG (≥4-fold rise)", "Acute ≤5 days vs. convalescent >15 days", "Confirms recent infection; useful when acute sample tests negative"],
]
tsero = Table(sero_data, colWidths=[BODY_W*0.22, BODY_W*0.32, BODY_W*0.46])
tsero.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_H3),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_ACCENT, C_WHITE, C_ACCENT]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(tsero)
story.append(Paragraph("<i>Source: Red Book 2021, pp. 507–511</i>", style_source))
story.append(Spacer(1, 6))
story.append(Paragraph("4. Virus Isolation", style_h3))
story.append(Paragraph(
"Virus can be isolated in mosquito cell cultures from serum, plasma, buffy coat, or autopsy tissue (liver, "
"spleen, lymph nodes, thymus) taken within the <b>first 6 days of illness</b>. Turnaround is ≥1 week. "
"Used mainly for research, surveillance, and serotyping.",
style_body))
story.append(Paragraph("5. Haemagglutination Inhibition (HIA), Complement Fixation (CF), and Neutralization Tests", style_h3))
story.append(Paragraph(
"Classic reference-standard serological methods. The <b>plaque reduction neutralization test (PRNT)</b> is "
"the most specific for distinguishing dengue from other flaviviruses. Paired sera required; turnaround ≥7 "
"days. Used in confirmatory and research settings.",
style_body))
story.append(Paragraph("6. Rapid Diagnostic Tests (RDT)", style_h3))
story.append(Paragraph(
"Lateral-flow immunochromatographic assays for IgM/IgG (and combined NS1+IgM/IgG) can give results in "
"15 minutes. Sensitivity varies considerably across commercial kits and proper validation is often lacking. "
"Most useful in resource-limited settings but should not replace RT-PCR or ELISA when available.",
style_body))
story.append(Spacer(1, 8))
# Master diagnostic table (Park's Table 2)
story.append(Paragraph("3.5 Summary: Dengue Diagnostics and Sample Characteristics", style_h2))
diag_summary = [
["Sample", "Diagnostic Goal", "Method", "Time to Result"],
["Acute serum\n(days 1–5)", "Viral detection", "RT-PCR / real-time RT-PCR", "1–2 days"],
["Acute serum\n(days 1–5)", "Antigen detection", "NS1 Ag rapid test", "Minutes"],
["Acute serum\n(days 1–5)", "Antigen detection", "NS1 Ag ELISA", "~1 day"],
["Serum after day 5", "Recent infection (IgM)", "IgM ELISA", "1–2 days"],
["Serum after day 5", "Recent infection (IgM)", "IgM rapid test", "Minutes"],
["Serum after day 5", "Past/secondary (IgG)", "IgG ELISA / HIA", "1–2 days"],
["Paired sera\n(days 1–5 and 15–21)", "IgM/IgG seroconversion", "ELISA / HIA / Neutralization test", "ELISA: 1–2 days\nHIA/NT: ≥7 days"],
["Autopsy tissue / buffy coat\n(within 6 days)", "Virus isolation", "Mosquito cell culture", "≥1 week"],
]
tsum = Table(diag_summary, colWidths=[BODY_W*0.24, BODY_W*0.22, BODY_W*0.30, BODY_W*0.24])
tsum.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_TITLE),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_ACCENT]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#bbbbbb")),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(tsum)
story.append(Paragraph(
"Table adapted from Park's Textbook of Preventive and Social Medicine, Table 2 (p. 293).",
style_source))
story.append(Spacer(1, 6))
# Haematological monitoring
story.append(Paragraph("3.6 Haematological Monitoring Protocol", style_h2))
story.append(Paragraph(
"A full blood count (FBC) should be performed at the <b>first visit</b> to establish the patient's own "
"baseline haematocrit. A <b>rapidly decreasing platelet count in parallel with a rising haematocrit</b> "
"compared to baseline is the most important combined indicator of progression to the critical/plasma leakage "
"phase.",
style_body))
story.append(Paragraph(
"In the absence of baseline, <b>age-specific population haematocrit levels</b> can be used for comparison. "
"Serial monitoring (every 4–6 hours during critical phase) is essential for timely fluid resuscitation.",
style_body))
story.append(Spacer(1, 10))
story.append(HRFlowable(width="100%", thickness=2, color=C_TITLE, spaceAfter=8))
# References
story.append(Paragraph("References", style_h2))
refs = [
"Harrison's Principles of Internal Medicine, 22nd Edition (2025, McGraw Hill Medical), p. 3901",
"Goldman-Cecil Medicine International Edition, 2-Volume Set, pp. 1529–1550",
"Red Book 2021: Report of the Committee on Infectious Diseases (American Academy of Pediatrics), pp. 520–529",
"Rosen's Emergency Medicine: Concepts and Clinical Practice, p. 2630",
"Robbins, Cotran & Kumar Pathologic Basis of Disease, pp. 335–336",
"Park's Textbook of Preventive and Social Medicine, pp. 289–294",
]
for r in refs:
story.append(Paragraph(f"• {r}", style_source))
story.append(Spacer(1, 2))
# ── Build ───────────────────────────────────────────────────────────────────────
doc = DenguePDF(OUTPUT)
doc.build(story, onFirstPage=footer_canvas, onLaterPages=footer_canvas)
print(f"PDF written to: {OUTPUT}")
import os
print(f"File size: {os.path.getsize(OUTPUT):,} bytes")
PYEOF
python3 /tmp/workspace/dengue-pdf/build_pdf.py
python3 -c " from pypdf import PdfReader r = PdfReader('/tmp/workspace/dengue-pdf/Dengue_Epidemiology_Clinical_Diagnosis.pdf') print(f'Pages: {len(r.pages)}') print(f'Title: {r.metadata.title}') print(f'Author: {r.metadata.author}') "
Dengue Epidemiology Clinical Diagnosis
PDF Document · PDF