Malaria symptoms, diagnosis, treatment flow chart diagram
malaria symptoms diagnosis treatment flowchart WHO guidelines 2024
A clean, professional medical flowchart diagram titled "Malaria: Symptoms, Diagnosis & Treatment" with the following flow structure: START BOX at top: "Patient presents with Fever + Travel/Residence in endemic area" Arrow down to SYMPTOMS BOX (light orange background): Title: "SYMPTOMS" • Fever (irregular early, then periodic every 2-3 days) • Chills and rigors • Headache • Myalgia / arthralgia • Nausea, vomiting, diarrhea • Sweating episodes • Fatigue / malaise • Splenomegaly (classic triad: fever + splenomegaly + thrombocytopenia) Arrow down to CLINICAL ASSESSMENT BOX (light yellow background): Title: "INITIAL ASSESSMENT" • Travel history to malaria-endemic region? • Fever >38.5°C of unclear origin? • Chemoprophylaxis taken? • Altered mental status? (suspect cerebral malaria) • Assess for severe vs. uncomplicated malaria Arrow splits into two paths: LEFT = "SEVERE MALARIA signs present" RIGHT = "No severe signs" SEVERE MALARIA indicators (red border box, left side): • Altered consciousness / cerebral malaria • Respiratory distress • Severe anemia (Hb <7 g/dL) • Renal failure / hemoglobinuria • Shock / circulatory collapse • Spontaneous bleeding • Hyperparasitemia (>5% RBCs) UNCOMPLICATED MALARIA (green border box, right side): • Fever + parasitemia • No organ dysfunction • Can tolerate oral medications Arrow down from both boxes to DIAGNOSIS BOX (light blue background): Title: "DIAGNOSIS" • Blood smear (thick & thin) - Gold standard • Rapid Diagnostic Test (RDT) - antigen detection • PCR - for low parasitemia / species confirmation • CBC: thrombocytopenia, anemia • LFTs, renal function, blood glucose • Species identification: P. falciparum, P. vivax, P. ovale, P. malariae, P. knowlesi Arrow down to TREATMENT BOX splitting into two branches: LEFT BRANCH - SEVERE MALARIA (red header): "HOSPITALIZE - IV Treatment" • IV Artesunate (first-line) - preferred over quinine • If artesunate unavailable: IV Quinine + doxycycline/clindamycin • Supportive care: fluids, antipyretics, manage complications • Monitor blood glucose (risk of hypoglycemia) • Blood transfusion if severe anemia RIGHT BRANCH - UNCOMPLICATED MALARIA (green header): "Outpatient Oral Treatment" • P. falciparum / mixed: Artemisinin-based Combination Therapy (ACT) (Artemether-lumefantrine OR Artesunate-amodiaquine) • Chloroquine-sensitive species (P. vivax, P. ovale, P. malariae): Oral Chloroquine 3-day course • P. vivax / P. ovale: add Primaquine (after G6PD testing) to prevent relapse • Treat fever with paracetamol Arrow down to FOLLOW-UP BOX (light purple background): Title: "FOLLOW-UP & MONITORING" • Repeat blood smears at 48-72 hrs, Day 7, Day 14, Day 28 • Monitor for treatment failure / drug resistance • Assess for complications • Primaquine for radical cure (P. vivax/P. ovale) • Educate on prevention: bed nets, repellents, chemoprophylaxis for future travel Use a clean white background, medical blue color scheme, clear directional arrows, bold section headers, and professional typography suitable for medical education.

Create a detailed reference PDF of this flowchart for clinical use
mkdir -p /home/daytona/workspace/malaria-pdf && ls /home/daytona/workspace/malar…
~/malaria-pdf/generate_malaria_pdf.py
#!/usr/bin/env python3
"""
Malaria Clinical Reference PDF Generator
Detailed flowchart-style reference for clinical use
"""
import urllib.request
import io
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether, PageBreak
)
from reportlab.platypus import Image as RLImage
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon
from reportlab.graphics.charts.flowchart import (
FlowChart
)
from reportlab.graphics import renderPDF
from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor
OUTPUT_PATH = "/home/daytona/workspace/malaria-pdf/Malaria_Clinical_Reference.pdf"
# --- Color Palette ---
C_BLUE_DARK = HexColor("#1A3C5E")
C_BLUE_MED = HexColor("#2C6FAC")
C_BLUE_LIGHT = HexColor("#D6E8FA")
C_ORANGE = HexColor("#E8790C")
C_ORANGE_LIGHT= HexColor("#FEF0DC")
C_GREEN = HexColor("#1F7A3E")
C_GREEN_LIGHT = HexColor("#D4EDDA")
C_RED = HexColor("#B22222")
C_RED_LIGHT = HexColor("#FDECEA")
C_YELLOW_LIGHT= HexColor("#FFFDE7")
C_PURPLE = HexColor("#5B2C8D")
C_PURPLE_LIGHT= HexColor("#EDE7F6")
C_GREY_LIGHT = HexColor("#F5F5F5")
C_GREY = HexColor("#CCCCCC")
C_BLACK = colors.black
C_WHITE = colors.white
# --- Page Setup ---
W, H = A4 # 595 x 842 pts
def header_footer(canvas_obj, doc):
"""Draw header and footer on every page."""
canvas_obj.saveState()
# Top header bar
canvas_obj.setFillColor(C_BLUE_DARK)
canvas_obj.rect(0, H - 28*mm, W, 28*mm, fill=1, stroke=0)
canvas_obj.setFillColor(C_WHITE)
canvas_obj.setFont("Helvetica-Bold", 14)
canvas_obj.drawString(15*mm, H - 14*mm, "MALARIA – Clinical Reference Guide")
canvas_obj.setFont("Helvetica", 9)
canvas_obj.drawRightString(W - 15*mm, H - 10*mm, "Symptoms · Diagnosis · Treatment")
canvas_obj.drawRightString(W - 15*mm, H - 18*mm, "Based on WHO Guidelines (2024) | Tintinalli's EM | Rosen's EM")
# Orange accent line under header
canvas_obj.setFillColor(C_ORANGE)
canvas_obj.rect(0, H - 30*mm, W, 2*mm, fill=1, stroke=0)
# Footer
canvas_obj.setFillColor(C_GREY_LIGHT)
canvas_obj.rect(0, 0, W, 12*mm, fill=1, stroke=0)
canvas_obj.setFillColor(C_BLUE_DARK)
canvas_obj.setFont("Helvetica", 8)
canvas_obj.drawString(15*mm, 4*mm,
"Sources: WHO Guidelines for Malaria (Nov 2024) | Tintinalli's Emergency Medicine | Rosen's Emergency Medicine | Harrison's Principles of Internal Medicine 22E")
canvas_obj.drawRightString(W - 15*mm, 4*mm, f"Page {doc.page}")
canvas_obj.restoreState()
def build_section_title(text, bg_color=C_BLUE_DARK, fg_color=C_WHITE, size=12):
style = ParagraphStyle(
"sectiontitle",
fontName="Helvetica-Bold",
fontSize=size,
textColor=fg_color,
backColor=bg_color,
spaceAfter=2,
spaceBefore=6,
leftIndent=6,
rightIndent=6,
leading=size + 6,
borderPad=4,
)
return Paragraph(f" {text}", style)
def build_body(text, bold=False, size=9, color=C_BLACK, indent=0):
style = ParagraphStyle(
"body",
fontName="Helvetica-Bold" if bold else "Helvetica",
fontSize=size,
textColor=color,
leftIndent=indent,
leading=size + 4,
spaceAfter=1,
)
return Paragraph(text, style)
def bullet(text, color=C_BLUE_MED, size=9):
style = ParagraphStyle(
"bullet",
fontName="Helvetica",
fontSize=size,
textColor=C_BLACK,
leftIndent=12,
bulletIndent=2,
leading=size + 4,
spaceAfter=1,
)
return Paragraph(f"<bullet>•</bullet> {text}", style)
def colored_table(data, col_widths, header_bg=C_BLUE_DARK, row_bg_alt=C_BLUE_LIGHT, font_size=8):
"""Build a styled table."""
style = TableStyle([
("BACKGROUND", (0, 0), (-1, 0), header_bg),
("TEXTCOLOR", (0, 0), (-1, 0), C_WHITE),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), font_size),
("FONTNAME", (0, 1), (-1, -1), "Helvetica"),
("FONTSIZE", (0, 1), (-1, -1), font_size - 1),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [C_WHITE, row_bg_alt]),
("GRID", (0, 0), (-1, -1), 0.5, C_GREY),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("LEFTPADDING", (0, 0), (-1, -1), 5),
("RIGHTPADDING", (0, 0), (-1, -1), 5),
("TOPPADDING", (0, 0), (-1, -1), 4),
("BOTTOMPADDING", (0, 0), (-1, -1), 4),
("WORDWRAP", (0, 0), (-1, -1), True),
])
t = Table(data, colWidths=col_widths)
t.setStyle(style)
return t
def flowchart_box(canvas_obj, x, y, w, h, title, lines,
bg=C_BLUE_LIGHT, border=C_BLUE_MED, title_bg=C_BLUE_MED,
title_fg=C_WHITE, font_size=8, title_size=9):
"""Draw a styled flowchart box directly on canvas."""
canvas_obj.setFillColor(bg)
canvas_obj.setStrokeColor(border)
canvas_obj.setLineWidth(1.2)
canvas_obj.roundRect(x, y, w, h, 5, fill=1, stroke=1)
# Title bar
canvas_obj.setFillColor(title_bg)
canvas_obj.roundRect(x, y + h - 18, w, 18, 4, fill=1, stroke=0)
canvas_obj.setFillColor(title_fg)
canvas_obj.setFont("Helvetica-Bold", title_size)
canvas_obj.drawCentredString(x + w / 2, y + h - 13, title)
# Content lines
canvas_obj.setFillColor(C_BLACK)
canvas_obj.setFont("Helvetica", font_size)
line_h = font_size + 3
cy = y + h - 24
for line in lines:
if cy < y + 4:
break
canvas_obj.drawString(x + 7, cy, line)
cy -= line_h
def draw_arrow(canvas_obj, x1, y1, x2, y2, color=C_BLUE_MED):
"""Draw an arrow from (x1,y1) to (x2,y2)."""
canvas_obj.setStrokeColor(color)
canvas_obj.setFillColor(color)
canvas_obj.setLineWidth(1.5)
canvas_obj.line(x1, y1, x2, y2)
# arrowhead
canvas_obj.setFillColor(color)
p = canvas_obj.beginPath()
p.moveTo(x2, y2)
p.lineTo(x2 - 5, y2 + 8)
p.lineTo(x2 + 5, y2 + 8)
p.close()
canvas_obj.drawPath(p, fill=1, stroke=0)
def draw_diamond(canvas_obj, cx, cy, w, h, text, bg=C_YELLOW_LIGHT, border=C_ORANGE, font_size=8):
"""Draw a diamond decision shape."""
pts = [cx, cy + h/2, cx + w/2, cy, cx, cy - h/2, cx - w/2, cy]
canvas_obj.setFillColor(bg)
canvas_obj.setStrokeColor(border)
canvas_obj.setLineWidth(1.5)
p = canvas_obj.beginPath()
p.moveTo(pts[0], pts[1])
for i in range(2, len(pts), 2):
p.lineTo(pts[i], pts[i+1])
p.close()
canvas_obj.drawPath(p, fill=1, stroke=1)
canvas_obj.setFillColor(C_BLACK)
canvas_obj.setFont("Helvetica-Bold", font_size)
canvas_obj.drawCentredString(cx, cy - 3, text)
# ============================================================
# PAGE 1 – FLOWCHART (drawn with canvas)
# ============================================================
class FlowChartPage:
"""Custom canvas-based page 1 flowchart."""
def draw(self, canvas_obj):
cw = W
ch = H
# --- Title already handled by header/footer ---
# ---- START box ----
start_x = cw/2 - 80; start_y = ch - 80*mm
start_w = 160; start_h = 22
canvas_obj.setFillColor(C_BLUE_DARK)
canvas_obj.roundRect(start_x, start_y, start_w, start_h, 8, fill=1, stroke=0)
canvas_obj.setFillColor(C_WHITE)
canvas_obj.setFont("Helvetica-Bold", 9)
canvas_obj.drawCentredString(cw/2, start_y + 7, "PATIENT PRESENTS WITH FEVER + TRAVEL / RESIDENCE IN ENDEMIC AREA")
# Arrow down
draw_arrow(canvas_obj, cw/2, start_y, cw/2, start_y - 10)
# ---- SYMPTOMS box ----
sym_y = start_y - 10 - 90
sym_x = cw/2 - 120; sym_w = 240; sym_h = 90
flowchart_box(canvas_obj, sym_x, sym_y, sym_w, sym_h,
"SYMPTOMS",
["• Fever (irregular early → periodic every 2-3 days)",
"• Chills and rigors | • Profuse sweating",
"• Headache | • Myalgia / arthralgia",
"• Nausea, vomiting, diarrhea",
"• Fatigue / malaise | • Splenomegaly",
"Classic triad: Fever + Splenomegaly + Thrombocytopenia"],
bg=C_ORANGE_LIGHT, border=C_ORANGE, title_bg=C_ORANGE,
title_fg=C_WHITE, font_size=7.5)
draw_arrow(canvas_obj, cw/2, sym_y, cw/2, sym_y - 10)
# ---- ASSESSMENT diamond ----
assess_cy = sym_y - 10 - 28
draw_diamond(canvas_obj, cw/2, assess_cy, 220, 52,
"Severe malaria signs?", bg=C_YELLOW_LIGHT, border=C_ORANGE, font_size=8.5)
# YES / NO labels
canvas_obj.setFont("Helvetica-Bold", 8)
canvas_obj.setFillColor(C_RED)
canvas_obj.drawString(cw/2 - 105 - 22, assess_cy - 3, "YES")
canvas_obj.setFillColor(C_GREEN)
canvas_obj.drawString(cw/2 + 105 + 5, assess_cy - 3, "NO")
# ---- SEVERE branch (left) ----
sev_x = 15*mm; sev_w = 130; sev_h = 105
sev_y = assess_cy - 28 - sev_h
# Arrow from diamond left
draw_arrow(canvas_obj, cw/2 - 110, assess_cy, sev_x + sev_w/2, sev_y + sev_h + 10)
draw_arrow(canvas_obj, sev_x + sev_w/2, sev_y + sev_h + 10, sev_x + sev_w/2, sev_y + sev_h)
flowchart_box(canvas_obj, sev_x, sev_y, sev_w, sev_h,
"SEVERE MALARIA",
["• Altered consciousness",
"• Cerebral malaria / seizures",
"• Respiratory distress / ARDS",
"• Severe anemia (Hb <7 g/dL)",
"• Acute renal failure",
"• Circulatory shock",
"• Haemoglobinuria",
"• Hyperparasitaemia (>5% RBCs)",
"• Spontaneous bleeding",
"• Repeated vomiting"],
bg=C_RED_LIGHT, border=C_RED, title_bg=C_RED,
title_fg=C_WHITE, font_size=7.5)
# ---- UNCOMPLICATED branch (right) ----
unc_x = W - 15*mm - 130; unc_w = 130; unc_h = 105
unc_y = sev_y
# Arrow from diamond right
draw_arrow(canvas_obj, cw/2 + 110, assess_cy, unc_x + unc_w/2, unc_y + unc_h + 10)
draw_arrow(canvas_obj, unc_x + unc_w/2, unc_y + unc_h + 10, unc_x + unc_w/2, unc_y + unc_h)
flowchart_box(canvas_obj, unc_x, unc_y, unc_w, unc_h,
"UNCOMPLICATED MALARIA",
["• Fever + parasitaemia confirmed",
"• No organ dysfunction",
"• Able to tolerate oral meds",
"• Outpatient management",
"",
"Species: P. falciparum,",
"P. vivax, P. ovale,",
"P. malariae, P. knowlesi"],
bg=C_GREEN_LIGHT, border=C_GREEN, title_bg=C_GREEN,
title_fg=C_WHITE, font_size=7.5)
# ---- DIAGNOSIS box (centre, below both branches) ----
diag_y = sev_y - 15 - 95
diag_x = cw/2 - 130; diag_w = 260; diag_h = 95
# Arrows from both branches down to diagnosis
draw_arrow(canvas_obj, sev_x + sev_w/2, sev_y, sev_x + sev_w/2, diag_y + diag_h + 8)
draw_arrow(canvas_obj, sev_x + sev_w/2, diag_y + diag_h + 8, cw/2, diag_y + diag_h + 8)
draw_arrow(canvas_obj, unc_x + unc_w/2, unc_y, unc_x + unc_w/2, diag_y + diag_h + 8)
draw_arrow(canvas_obj, unc_x + unc_w/2, diag_y + diag_h + 8, cw/2, diag_y + diag_h + 8)
draw_arrow(canvas_obj, cw/2, diag_y + diag_h + 8, cw/2, diag_y + diag_h)
flowchart_box(canvas_obj, diag_x, diag_y, diag_w, diag_h,
"DIAGNOSIS",
["• Thick & thin blood smear [GOLD STANDARD] – species ID + parasite density",
"• Rapid Diagnostic Test (RDT) – antigen detection (HRP2, pLDH)",
"• PCR – species confirmation, low parasitaemia, mixed infections",
"• CBC: thrombocytopenia, anaemia, leukopenia",
"• LFTs, renal function, blood glucose, lactate",
"• Repeat smears if initial negative + high suspicion"],
bg=C_BLUE_LIGHT, border=C_BLUE_MED, title_bg=C_BLUE_MED,
title_fg=C_WHITE, font_size=7.5)
draw_arrow(canvas_obj, cw/2, diag_y, cw/2, diag_y - 10)
# ---- TREATMENT split ----
treat_y = diag_y - 10 - 110
# Severe treatment (left)
st_x = 15*mm; st_w = 145; st_h = 110
draw_arrow(canvas_obj, cw/2, diag_y - 10, cw/2 - st_w/2 - 15, diag_y - 10)
draw_arrow(canvas_obj, st_x + st_w/2, diag_y - 10, st_x + st_w/2, treat_y + st_h)
flowchart_box(canvas_obj, st_x, treat_y, st_w, st_h,
"SEVERE MALARIA TREATMENT",
["HOSPITALISE – IV Treatment",
"• IV Artesunate (1st line, WHO preferred)",
" 2.4 mg/kg at 0, 12, 24h then daily",
"• Alt: IV Quinine + Doxycycline/Clindamycin",
"• Supportive: IV fluids, antipyretics",
"• Blood glucose monitoring (hypoglycaemia risk)",
"• Transfusion if Hb <7 g/dL",
"• Manage seizures, respiratory support",
"• ICU if cerebral malaria"],
bg=C_RED_LIGHT, border=C_RED, title_bg=C_RED,
title_fg=C_WHITE, font_size=7.2)
canvas_obj.setFont("Helvetica-Bold", 8); canvas_obj.setFillColor(C_RED)
canvas_obj.drawCentredString(st_x + st_w/2, treat_y - 8, "HOSPITALISE")
# Uncomplicated treatment (right)
ut_x = W - 15*mm - 150; ut_w = 150; ut_h = 110
draw_arrow(canvas_obj, cw/2, diag_y - 10, cw/2 + ut_w/2 + 15, diag_y - 10)
draw_arrow(canvas_obj, ut_x + ut_w/2, diag_y - 10, ut_x + ut_w/2, treat_y + ut_h)
flowchart_box(canvas_obj, ut_x, treat_y, ut_w, ut_h,
"UNCOMPLICATED TREATMENT",
["Oral Treatment – Outpatient",
"P. falciparum / mixed (ACT):",
"• Artemether-lumefantrine (1st line)",
"• Artesunate-amodiaquine",
"• Artesunate-mefloquine",
"P. vivax / P. ovale (chloroquine-sensitive):",
"• Chloroquine 3-day course",
"+ Primaquine (after G6PD test) for radical cure",
"Antipyretic: Paracetamol"],
bg=C_GREEN_LIGHT, border=C_GREEN, title_bg=C_GREEN,
title_fg=C_WHITE, font_size=7.2)
canvas_obj.setFont("Helvetica-Bold", 8); canvas_obj.setFillColor(C_GREEN)
canvas_obj.drawCentredString(ut_x + ut_w/2, treat_y - 8, "OUTPATIENT")
# ---- FOLLOW-UP box ----
fu_y = treat_y - 18 - 60
fu_x = cw/2 - 130; fu_w = 260; fu_h = 60
draw_arrow(canvas_obj, st_x + st_w/2, treat_y, st_x + st_w/2, fu_y + fu_h + 10)
draw_arrow(canvas_obj, st_x + st_w/2, fu_y + fu_h + 10, cw/2, fu_y + fu_h + 10)
draw_arrow(canvas_obj, ut_x + ut_w/2, treat_y, ut_x + ut_w/2, fu_y + fu_h + 10)
draw_arrow(canvas_obj, ut_x + ut_w/2, fu_y + fu_h + 10, cw/2, fu_y + fu_h + 10)
draw_arrow(canvas_obj, cw/2, fu_y + fu_h + 10, cw/2, fu_y + fu_h)
flowchart_box(canvas_obj, fu_x, fu_y, fu_w, fu_h,
"FOLLOW-UP & MONITORING",
["• Repeat blood smears at 48-72h, Day 7, 14, 28",
"• Monitor for treatment failure / drug resistance",
"• Primaquine for P. vivax/P. ovale radical cure (check G6PD first)",
"• Prevention: insecticide-treated nets, repellents, chemoprophylaxis"],
bg=C_PURPLE_LIGHT, border=C_PURPLE, title_bg=C_PURPLE,
title_fg=C_WHITE, font_size=7.5)
# ============================================================
# PAGE 2 – DETAILED REFERENCE TABLES
# ============================================================
def build_reference_content():
styles = getSampleStyleSheet()
story = []
TOP = 32*mm # reserve top for header
story.append(Spacer(1, TOP))
# ---- Section 1: Species Overview ----
story.append(build_section_title("1. MALARIA SPECIES COMPARISON", bg_color=C_BLUE_DARK))
story.append(Spacer(1, 3))
species_data = [
["Feature", "P. falciparum", "P. vivax", "P. ovale", "P. malariae", "P. knowlesi"],
["Distribution", "Sub-Saharan Africa\nS/SE Asia, Americas", "Widespread\n(temperate/tropical)", "West Africa\nPacific", "Worldwide\n(low endemic)", "SE Asia\n(Borneo)"],
["Fever cycle", "Irregular / quotidian", "Tertian (48h)", "Tertian (48h)", "Quartan (72h)", "Quotidian (24h)"],
["Severe disease", "YES – high risk", "Rare", "Rare", "Nephrotic syndrome", "YES – rapid course"],
["Relapse", "No", "YES (hypnozoites)", "YES (hypnozoites)", "Recrudesence", "No"],
["Radical cure", "Not needed", "Primaquine required", "Primaquine required", "Not needed", "Not needed"],
["Chloroquine Rx", "Usually resistant", "Sensitive*", "Sensitive", "Sensitive", "Sensitive"],
]
t1 = colored_table(species_data,
col_widths=[3.2*cm, 3.2*cm, 3.2*cm, 2.8*cm, 3*cm, 3*cm],
header_bg=C_BLUE_DARK, row_bg_alt=C_BLUE_LIGHT, font_size=7)
story.append(t1)
story.append(build_body("* P. vivax chloroquine resistance emerging in parts of PNG, Indonesia, and South America.", size=7, color=HexColor("#666666")))
story.append(Spacer(1, 6))
# ---- Section 2: Severe Malaria Criteria ----
story.append(build_section_title("2. WHO CRITERIA FOR SEVERE MALARIA (Any one criterion = Severe)", bg_color=C_RED))
story.append(Spacer(1, 3))
severe_data = [
["Clinical Criteria", "Laboratory Criteria"],
["Impaired consciousness / coma (cerebral malaria)", "Hyperparasitaemia: >5% parasitised RBCs"],
["Respiratory distress (deep breathing / ARDS)", "Severe anaemia: Hb <7 g/dL (child) or <8 g/dL (adult)"],
["Multiple convulsions (≥2 in 24h)", "Hypoglycaemia: blood glucose <2.2 mmol/L"],
["Circulatory collapse / shock (SBP <70 mmHg adult)", "Acute renal failure: creatinine >265 µmol/L"],
["Pulmonary oedema / ARDS", "Metabolic acidosis: bicarbonate <15 mmol/L"],
["Abnormal bleeding / DIC", "Elevated lactate: >5 mmol/L"],
["Jaundice (bilirubin >50 µmol/L + >2 other criteria)", "Haemoglobinuria (blackwater fever)"],
["Hyperparasitaemia with deterioration", ""],
]
t2 = colored_table(severe_data, col_widths=[9*cm, 9*cm],
header_bg=C_RED, row_bg_alt=C_RED_LIGHT, font_size=7.5)
story.append(t2)
story.append(Spacer(1, 6))
# ---- Section 3: Treatment Protocols ----
story.append(build_section_title("3. TREATMENT PROTOCOLS (WHO Guidelines 2024)", bg_color=C_BLUE_MED))
story.append(Spacer(1, 3))
# Severe treatment
story.append(build_body("SEVERE MALARIA – IV Treatment (Hospitalise)", bold=True, color=C_RED, size=9))
severe_tx_data = [
["Drug", "Dose", "Route", "Notes"],
["IV Artesunate\n(1st line – WHO preferred)", "2.4 mg/kg at 0h, 12h, 24h;\nthen once daily", "IV (or IM)", "Switch to oral ACT once patient can tolerate;\ncomplete 3-day ACT course after IV artesunate"],
["IV Quinine\n(if artesunate unavailable)", "20 mg/kg loading, then\n10 mg/kg every 8h", "IV infusion", "Add doxycycline 100mg BD or clindamycin\n(pregnant/children); monitor for hypoglycaemia"],
["Artemether IM\n(if IV access not possible)", "3.2 mg/kg stat, then\n1.6 mg/kg daily", "IM", "Use until IV access available;\nswitch to oral when possible"],
]
t3a = colored_table(severe_tx_data, col_widths=[4.5*cm, 5*cm, 2.5*cm, 6.5*cm],
header_bg=C_RED, row_bg_alt=C_RED_LIGHT, font_size=7)
story.append(t3a)
story.append(Spacer(1, 5))
# Uncomplicated treatment
story.append(build_body("UNCOMPLICATED MALARIA – Oral ACT Treatment", bold=True, color=C_GREEN, size=9))
unc_tx_data = [
["Regimen", "Dose (Adult)", "Duration", "Notes"],
["Artemether-lumefantrine\n(AL) – 1st line P. falciparum", "4 tabs at 0h, 8h;\nthen BD for 2 days\n(6 doses total)", "3 days", "Take with food (fat increases bioavailability);\navoid in 1st trimester of pregnancy"],
["Artesunate-amodiaquine\n(ASAQ)", "As per weight-based\nfixed-dose combination", "3 days", "Monitor for amodiaquine toxicity;\nalternative to AL"],
["Artesunate-mefloquine\n(AS-MQ)", "Artesunate 4 mg/kg/day\n+ mefloquine 25 mg/kg split", "3 days", "SE Asia preference;\navoid in psychiatric history"],
["Dihydroartemisinin-\npiperaquine (DHP)", "3 tablets (40/320mg)\nonce daily", "3 days", "Preferred in some SE Asia regions;\nonce daily improves adherence"],
["Chloroquine\n(P. vivax / P. ovale)", "620mg base stat, 310mg\nat 6h, 12h, 24h", "3 days", "Only where chloroquine-sensitive;\ncombine with primaquine for radical cure"],
["Primaquine\n(radical cure – hypnozoites)", "0.25 mg/kg/day (P. vivax)\n0.5 mg/kg/day (P. ovale)", "14 days", "TEST G6PD FIRST – haemolysis risk;\ncontraindicated in pregnancy"],
]
t3b = colored_table(unc_tx_data, col_widths=[4.5*cm, 4.5*cm, 2*cm, 7.5*cm],
header_bg=C_GREEN, row_bg_alt=C_GREEN_LIGHT, font_size=7)
story.append(t3b)
story.append(Spacer(1, 6))
# ---- Section 4: Special Populations ----
story.append(build_section_title("4. TREATMENT IN SPECIAL POPULATIONS", bg_color=C_PURPLE))
story.append(Spacer(1, 3))
sp_data = [
["Population", "First-Line Treatment", "Key Cautions"],
["Pregnant – 1st trimester", "Quinine + clindamycin × 7 days", "ACTs avoided in 1st trimester (limited data); artesunate if life-threatening severe malaria"],
["Pregnant – 2nd/3rd trimester", "AL or ASAQ (uncomplicated);\nIV artesunate (severe)", "Primaquine CONTRAINDICATED in pregnancy; increased risk of hypoglycaemia"],
["Children <5 years", "Weight-based ACT dosing;\nIV artesunate for severe", "Higher mortality risk; monitor glucose; rectal artesunate if referral delayed"],
["G6PD deficiency", "ACT for P. falciparum;\nWeekly primaquine 0.75 mg/kg × 8 wks\n(P. vivax radical cure)", "Daily primaquine CONTRAINDICATED;\nTest G6PD before any primaquine use"],
["HIV / immunocompromised", "Standard ACT;\nIV artesunate (severe)", "Drug interactions: artemether-lumefantrine + efavirenz/lopinavir;\nMonitor closely"],
["Returning traveller", "As per species + resistance\npattern of country visited", "Assume P. falciparum until excluded;\nseek infectious disease specialist input"],
]
t4 = colored_table(sp_data, col_widths=[4*cm, 6*cm, 8.5*cm],
header_bg=C_PURPLE, row_bg_alt=C_PURPLE_LIGHT, font_size=7)
story.append(t4)
story.append(Spacer(1, 6))
# ---- Section 5: Monitoring ----
story.append(build_section_title("5. MONITORING & TREATMENT RESPONSE", bg_color=C_BLUE_DARK))
story.append(Spacer(1, 3))
mon_data = [
["Timepoint", "Action", "Treatment Failure Criteria"],
["48–72h", "Repeat thick blood smear;\ncheck parasite density", "Parasite count not falling or clinical deterioration"],
["Day 3", "Clinical review;\nparasite count <25% baseline = adequate", "Parasite count >25% baseline on Day 3 suggests resistance"],
["Day 7", "Blood smear + clinical review", "Persistent parasitaemia = likely treatment failure"],
["Day 14", "Blood smear;\nsymptom check", "Reappearance of parasitaemia = recrudescence or re-infection"],
["Day 28", "Final smear + clinical review", "WHO standard endpoint for treatment efficacy assessment"],
]
t5 = colored_table(mon_data, col_widths=[3*cm, 7*cm, 8.5*cm],
header_bg=C_BLUE_DARK, row_bg_alt=C_BLUE_LIGHT, font_size=7)
story.append(t5)
story.append(Spacer(1, 6))
# ---- Section 6: Prevention ----
story.append(build_section_title("6. PREVENTION & CHEMOPROPHYLAXIS", bg_color=C_ORANGE))
story.append(Spacer(1, 3))
prev_data = [
["Agent", "Dosing", "Indication / Region", "Notes"],
["Atovaquone-proguanil\n(Malarone)", "1 adult tab daily;\nstart 1–2 days before,\ncontinue 7 days after", "All regions incl. resistant\nP. falciparum areas", "Well tolerated; no G6PD issue;\nhigh cost"],
["Doxycycline", "100 mg daily;\nstart 1–2 days before,\ncontinue 4 weeks after", "SE Asia (mefloquine\nresistance), sub-Saharan Africa", "Photosensitivity; GI side effects;\ncontraindicated in pregnancy + <8 yrs"],
["Mefloquine (Lariam)", "250 mg weekly;\nstart 3 weeks before,\ncontinue 4 weeks after", "Most endemic areas\n(check local resistance)", "Neuropsychiatric side effects;\ncontraindicated in seizure disorders"],
["Chloroquine", "500 mg (base 300mg)\nweekly", "Areas with only\nchloroquine-sensitive malaria", "Limited use due to widespread resistance"],
["Primaquine", "30 mg base daily\n(start day before travel)", "G6PD-normal individuals;\nVivax-endemic areas", "Test G6PD; terminal prophylaxis for\nP. vivax/ovale exposure"],
]
t6 = colored_table(prev_data, col_widths=[3.8*cm, 4*cm, 5.2*cm, 5.5*cm],
header_bg=C_ORANGE, row_bg_alt=C_ORANGE_LIGHT, font_size=7)
story.append(t6)
story.append(Spacer(1, 5))
# Personal protection reminder
prot_data = [["Personal Protection Measures"],
["• Insecticide-treated bed nets (ITNs) / Long-Lasting Insecticidal Nets (LLINs)"],
["• DEET-based repellents (20-50% DEET) applied to exposed skin"],
["• Permethrin-treated clothing"],
["• Indoor Residual Spraying (IRS) in endemic households"],
["• Wear long sleeves/trousers from dusk to dawn (peak Anopheles biting time)"],
["• RTS,S/AS01 (Mosquirix) vaccine – recommended for children in sub-Saharan Africa"]]
t_prot = Table(prot_data, colWidths=[18.5*cm])
t_prot.setStyle(TableStyle([
("BACKGROUND", (0, 0), (-1, 0), C_ORANGE),
("TEXTCOLOR", (0, 0), (-1, 0), C_WHITE),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 8),
("FONTNAME", (0, 1), (-1, -1), "Helvetica"),
("FONTSIZE", (0, 1), (-1, -1), 7.5),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [C_WHITE, C_ORANGE_LIGHT]),
("GRID", (0, 0), (-1, -1), 0.4, C_GREY),
("LEFTPADDING", (0, 0), (-1, -1), 8),
("TOPPADDING", (0, 0), (-1, -1), 3),
("BOTTOMPADDING", (0, 0), (-1, -1), 3),
]))
story.append(t_prot)
story.append(Spacer(1, 8))
# ---- Section 7: Key Drug Interactions / Cautions ----
story.append(build_section_title("7. KEY DRUG INTERACTIONS & CAUTIONS", bg_color=C_RED))
story.append(Spacer(1, 3))
int_data = [
["Drug", "Interaction / Caution", "Clinical Impact"],
["Artemether-lumefantrine", "CYP3A4 inducers (rifampicin, efavirenz)", "Reduced lumefantrine levels → treatment failure"],
["Artemether-lumefantrine", "QT-prolonging drugs (halofantrine, amiodarone)", "Additive QT prolongation → arrhythmia risk"],
["Quinine (IV)", "Mefloquine", "Increased quinine toxicity; avoid combination"],
["Quinine (IV)", "Digoxin", "Elevated digoxin levels; monitor closely"],
["Primaquine", "G6PD-deficient individuals", "Haemolytic anaemia – ALWAYS test G6PD before prescribing"],
["Doxycycline (prophylaxis)", "Antacids, dairy, iron supplements", "Reduced absorption – take on empty stomach"],
["Mefloquine", "Beta-blockers, calcium channel blockers", "Cardiac conduction disturbances"],
["Atovaquone-proguanil", "Rifampicin, tetracycline", "Reduced atovaquone levels → prophylaxis failure"],
]
t7 = colored_table(int_data, col_widths=[4.5*cm, 7*cm, 7*cm],
header_bg=C_RED, row_bg_alt=C_RED_LIGHT, font_size=7)
story.append(t7)
story.append(Spacer(1, 10))
# References
story.append(HRFlowable(width="100%", thickness=0.5, color=C_GREY_LIGHT))
story.append(Spacer(1, 3))
ref_style = ParagraphStyle("ref", fontName="Helvetica", fontSize=6.5,
textColor=HexColor("#555555"), leading=9)
story.append(Paragraph(
"<b>References:</b> "
"1. WHO Guidelines for Malaria, 30 November 2024 (WHO/UCN/GMP/2024.01 Rev.1). "
"2. Tintinalli JE et al. Tintinalli's Emergency Medicine: A Comprehensive Study Guide, 9th ed. McGraw-Hill, 2020. "
"3. Walls RM et al. Rosen's Emergency Medicine: Concepts and Clinical Practice, 9th ed. Elsevier, 2022. "
"4. Loscalzo J et al. Harrison's Principles of Internal Medicine, 22nd ed. McGraw-Hill, 2025. "
"5. CDC Malaria Diagnosis and Treatment Guidelines, 2024.",
ref_style))
return story
# ============================================================
# MAIN BUILD
# ============================================================
def build_pdf():
doc = SimpleDocTemplate(
OUTPUT_PATH,
pagesize=A4,
leftMargin=15*mm,
rightMargin=15*mm,
topMargin=32*mm,
bottomMargin=15*mm,
title="Malaria Clinical Reference Guide",
author="Orris Medical Reference",
subject="Malaria Symptoms, Diagnosis, and Treatment",
)
# --- Page 1: flowchart via canvas ---
class FlowChartDrawing:
def __init__(self):
self.width = W - 30*mm
self.height = H - 50*mm
def drawOn(self, canvas_obj, x, y):
fc = FlowChartPage()
fc.draw(canvas_obj)
def wrap(self, aw, ah):
return self.width, self.height
# We'll use a two-pass approach: first build reference pages, then prepend flowchart page
# Build reference tables content
story = build_reference_content()
# Custom first page (flowchart) using onFirstPage / onLaterPages
def on_first_page(canvas_obj, doc):
header_footer(canvas_obj, doc)
fc = FlowChartPage()
fc.draw(canvas_obj)
def on_later_pages(canvas_obj, doc):
header_footer(canvas_obj, doc)
# Insert a PageBreak at beginning so first page is blank (handled by canvas)
final_story = [Spacer(1, H - 50*mm), PageBreak()] + story
doc.build(final_story,
onFirstPage=on_first_page,
onLaterPages=on_later_pages)
print(f"PDF created: {OUTPUT_PATH}")
if __name__ == "__main__":
build_pdf()
cd /home/daytona/workspace/malaria-pdf && python generate_malaria_pdf.py 2>&1
~/malaria-pdf/generate_malaria_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/malaria-pdf/generate_malaria_pdf.py'
~/malaria-pdf/generate_malaria_pdf.py
Error: String not found in file: 'from reportlab.platypus import Image as RLImage
from reportlab.platypus import ('cd /home/daytona/workspace/malaria-pdf && python generate_malaria_pdf.py 2>&1
~/malaria-pdf/generate_malaria_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/malaria-pdf/generate_malaria_pdf.py'
cd /home/daytona/workspace/malaria-pdf && python generate_malaria_pdf.py 2>&1
ls -lh /home/daytona/workspace/malaria-pdf/Malaria_Clinical_Reference.pdf
Malaria Clinical Reference
PDF Document · PDF
| Section | Content |
|---|---|
| 1 | Species Comparison - P. falciparum, vivax, ovale, malariae, knowlesi |
| 2 | WHO Severe Malaria Criteria (clinical + laboratory) |
| 3 | Full Treatment Protocols with doses - IV artesunate, ACTs, chloroquine, primaquine |
| 4 | Special Populations - pregnancy, children, G6PD deficiency, HIV |
| 5 | Monitoring schedule - Day 3, 7, 14, 28 with treatment failure criteria |
| 6 | Chemoprophylaxis - atovaquone-proguanil, doxycycline, mefloquine, primaquine |
| 7 | Key Drug Interactions & Cautions |
Generate a quick reference card (PDF poster) for point-of-care use
~/malaria-pdf/generate_poc_card.py
#!/usr/bin/env python3
"""
Malaria Point-of-Care Quick Reference Card
Single A4 page – designed for wall/desk use at clinical settings
"""
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib.colors import HexColor, white, black
OUTPUT = "/home/daytona/workspace/malaria-pdf/Malaria_POC_QuickRef.pdf"
W, H = A4 # 595.28 x 841.89 pts
# ── Palette ──────────────────────────────────────────────────
BG = HexColor("#F0F4F8")
NAVY = HexColor("#0D2B4E")
BLUE = HexColor("#1A5EA8")
BLUE_LIGHT = HexColor("#C8DEFA")
BLUE_PALE = HexColor("#E8F2FF")
ORANGE = HexColor("#D4680A")
ORANGE_LITE = HexColor("#FEF0DC")
RED = HexColor("#B01C1C")
RED_LITE = HexColor("#FDECEA")
GREEN = HexColor("#1A6B38")
GREEN_LITE = HexColor("#D4EDDA")
PURPLE = HexColor("#5B2C8D")
PURPLE_LITE = HexColor("#EDE7F6")
GOLD = HexColor("#E8A020")
GREY = HexColor("#BBBBBB")
GREY_DARK = HexColor("#555555")
WHITE = white
BLACK = black
# ── Helpers ──────────────────────────────────────────────────
def filled_rect(c, x, y, w, h, fill, stroke=None, radius=3):
c.setFillColor(fill)
if stroke:
c.setStrokeColor(stroke)
c.setLineWidth(0.6)
c.roundRect(x, y, w, h, radius, fill=1, stroke=1)
else:
c.roundRect(x, y, w, h, radius, fill=1, stroke=0)
def section_header(c, x, y, w, h, text, bg=NAVY, fg=WHITE, fsize=8.5):
filled_rect(c, x, y, w, h, bg, radius=3)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", fsize)
c.drawCentredString(x + w / 2, y + h / 2 - fsize * 0.35, text)
def txt(c, x, y, text, font="Helvetica", size=7.5, color=BLACK, align="left"):
c.setFont(font, size)
c.setFillColor(color)
if align == "center":
c.drawCentredString(x, y, text)
elif align == "right":
c.drawRightString(x, y, text)
else:
c.drawString(x, y, text)
def bullet_lines(c, x, y, lines, size=7, lead=10, color=BLACK, bullet_color=BLUE, indent=8):
"""Draw bulleted lines, return final y."""
for line in lines:
c.setFillColor(bullet_color)
c.setFont("Helvetica-Bold", size + 1)
c.drawString(x, y, "•")
c.setFillColor(color)
c.setFont("Helvetica", size)
c.drawString(x + indent, y, line)
y -= lead
return y
def mini_table(c, x, y, rows, col_widths, row_h=11,
header_bg=NAVY, header_fg=WHITE,
alt_bg=None, font_size=7):
"""Draw a compact table. rows[0] = header."""
for ri, row in enumerate(rows):
cx = x
bg = header_bg if ri == 0 else (alt_bg if (alt_bg and ri % 2 == 0) else WHITE)
fg = header_fg if ri == 0 else BLACK
fn = "Helvetica-Bold" if ri == 0 else "Helvetica"
for ci, (cell, cw) in enumerate(zip(row, col_widths)):
filled_rect(c, cx, y - row_h, cw, row_h, bg)
c.setStrokeColor(GREY)
c.setLineWidth(0.3)
c.rect(cx, y - row_h, cw, row_h, fill=0, stroke=1)
c.setFillColor(fg)
c.setFont(fn, font_size)
c.drawString(cx + 3, y - row_h + 3, str(cell))
cx += cw
y -= row_h
return y
def arrow_down(c, x, y1, y2, color=BLUE):
c.setStrokeColor(color)
c.setFillColor(color)
c.setLineWidth(1.2)
c.line(x, y1, x, y2 + 5)
p = c.beginPath()
p.moveTo(x, y2); p.lineTo(x - 4, y2 + 7); p.lineTo(x + 4, y2 + 7)
p.close(); c.drawPath(p, fill=1, stroke=0)
def badge(c, x, y, w, h, text, bg=RED, fg=WHITE, fsize=7):
filled_rect(c, x, y, w, h, bg, radius=4)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", fsize)
c.drawCentredString(x + w / 2, y + h / 2 - fsize * 0.35, text)
# ══════════════════════════════════════════════════════════════
# MAIN DRAW
# ══════════════════════════════════════════════════════════════
def draw(c):
M = 6 * mm # margin
IW = W - 2 * M # inner width = ~183mm
# ── Background ──
c.setFillColor(BG)
c.rect(0, 0, W, H, fill=1, stroke=0)
# ── TOP HEADER BAR ──
hdr_h = 18 * mm
filled_rect(c, 0, H - hdr_h, W, hdr_h, NAVY, radius=0)
# Red accent stripe
filled_rect(c, 0, H - hdr_h - 2.5*mm, W, 2.5*mm, ORANGE, radius=0)
# Title
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 16)
c.drawCentredString(W / 2, H - 11 * mm, "MALARIA QUICK REFERENCE CARD")
c.setFont("Helvetica", 8)
c.setFillColor(GOLD)
c.drawCentredString(W / 2, H - 16 * mm,
"Point-of-Care | Symptoms · Diagnosis · Treatment | WHO Guidelines 2024")
# ── LAYOUT: 3 columns ──
top_y = H - hdr_h - 2.5*mm - 3*mm # just below orange stripe
col_w = (IW - 4 * mm) / 3
c1x = M
c2x = M + col_w + 2 * mm
c3x = M + 2 * (col_w + 2 * mm)
cy = top_y # current y (top of content)
# ━━━━━━━━━━━━━━━━━━━━━━━
# COLUMN 1
# ━━━━━━━━━━━━━━━━━━━━━━━
y = cy
# ── SUSPECT MALARIA ──
section_header(c, c1x, y - 9, col_w, 9, "▶ SUSPECT MALARIA WHEN…", bg=NAVY)
y -= 9
filled_rect(c, c1x, y - 55, col_w, 55, BLUE_PALE, radius=3)
y2 = y - 7
items = [
"Fever ≥38.5°C of unclear origin",
"Travel/residence in endemic area",
"Periodic chills + rigors + sweating",
"Headache + myalgia + fatigue",
"Thrombocytopenia on CBC",
"Altered mental status + fever → cerebral malaria",
]
for line in items:
txt(c, c1x + 10, y2, "•", size=7.5, color=BLUE); txt(c, c1x + 16, y2, line, size=7)
y2 -= 9
y -= 55
# ── SYMPTOMS box ──
y -= 3
section_header(c, c1x, y - 9, col_w, 9, "SYMPTOMS", bg=ORANGE)
y -= 9
sym_h = 70
filled_rect(c, c1x, y - sym_h, col_w, sym_h, ORANGE_LITE, stroke=ORANGE, radius=3)
y2 = y - 8
sym_lines = [
("Fever", "irregular early → periodic 48-72h"),
("Chills/rigors", "abrupt onset"),
("Profuse sweating", "after fever breaks"),
("Headache", "frontal / diffuse"),
("Myalgia", "arthralgia, backache"),
("Nausea/vomiting", "± diarrhea"),
("Splenomegaly", "chronic cases"),
]
for k, v in sym_lines:
c.setFont("Helvetica-Bold", 6.8); c.setFillColor(ORANGE)
c.drawString(c1x + 4, y2, k)
kw = c.stringWidth(k, "Helvetica-Bold", 6.8)
c.setFont("Helvetica", 6.8); c.setFillColor(BLACK)
c.drawString(c1x + 4 + kw + 2, y2, f"– {v}")
y2 -= 9.5
y -= sym_h
# ── CLASSIC TRIAD callout ──
y -= 3
filled_rect(c, c1x, y - 14, col_w, 14, GOLD, radius=4)
c.setFillColor(NAVY); c.setFont("Helvetica-Bold", 7.5)
c.drawCentredString(c1x + col_w / 2, y - 9.5, "CLASSIC TRIAD")
c.setFont("Helvetica", 6.8)
c.drawCentredString(c1x + col_w / 2, y - 3, "Fever + Splenomegaly + Thrombocytopenia")
y -= 14
# ── SPECIES quick-ref ──
y -= 4
section_header(c, c1x, y - 9, col_w, 9, "SPECIES AT A GLANCE", bg=PURPLE)
y -= 9
sp_rows = [
["Species", "Cycle", "Relapse", "Severity"],
["P. falciparum", "Irreg.", "No", "★★★"],
["P. vivax", "48h", "Yes", "★★"],
["P. ovale", "48h", "Yes", "★"],
["P. malariae", "72h", "No", "★"],
["P. knowlesi", "24h", "No", "★★★"],
]
cws = [col_w * 0.38, col_w * 0.18, col_w * 0.22, col_w * 0.22]
mini_table(c, c1x, y, sp_rows, cws, row_h=10,
header_bg=PURPLE, alt_bg=PURPLE_LITE, font_size=6.5)
y -= 10 * len(sp_rows)
# ━━━━━━━━━━━━━━━━━━━━━━━
# COLUMN 2
# ━━━━━━━━━━━━━━━━━━━━━━━
y = cy
# ── DIAGNOSIS ──
section_header(c, c2x, y - 9, col_w, 9, "DIAGNOSIS", bg=BLUE)
y -= 9
diag_h = 68
filled_rect(c, c2x, y - diag_h, col_w, diag_h, BLUE_PALE, stroke=BLUE, radius=3)
y2 = y - 8
diag = [
("Thick + thin smear", "GOLD STANDARD"),
(" → Species ID", "+ parasite density"),
("Rapid Diag. Test", "(RDT) – HRP2/pLDH"),
("PCR", "species confirm / low parasit."),
("CBC", "↓platelets, ↓Hb, leukopenia"),
("Glucose", "hypoglycaemia (severe)"),
("LFTs / Cr", "organ dysfunction screen"),
]
for k, v in diag:
c.setFont("Helvetica-Bold", 6.8); c.setFillColor(BLUE)
c.drawString(c2x + 4, y2, k)
kw = c.stringWidth(k, "Helvetica-Bold", 6.8)
c.setFont("Helvetica", 6.8); c.setFillColor(BLACK)
c.drawString(c2x + 4 + kw + 2, y2, v)
y2 -= 9.5
y -= diag_h
# ── SEVERITY ASSESSMENT ──
y -= 3
section_header(c, c2x, y - 9, col_w, 9, "SEVERE MALARIA – ANY ONE CRITERION", bg=RED)
y -= 9
sev_h = 90
filled_rect(c, c2x, y - sev_h, col_w, sev_h, RED_LITE, stroke=RED, radius=3)
y2 = y - 8
sev = [
"Impaired consciousness / coma",
"Respiratory distress / ARDS",
"Convulsions (≥2 in 24h)",
"Circulatory shock (SBP <70 mmHg)",
"Severe anaemia (Hb <7 g/dL)",
"Hyperparasitaemia (>5% RBCs)",
"Acute renal failure",
"Hypoglycaemia (<2.2 mmol/L)",
"Haemoglobinuria / jaundice",
]
for line in sev:
c.setFillColor(RED); c.setFont("Helvetica-Bold", 7.5)
c.drawString(c2x + 4, y2, "!")
c.setFillColor(BLACK); c.setFont("Helvetica", 6.8)
c.drawString(c2x + 11, y2, line)
y2 -= 9.5
y -= sev_h
# ── FOLLOW-UP ──
y -= 3
section_header(c, c2x, y - 9, col_w, 9, "MONITORING / FOLLOW-UP", bg=PURPLE)
y -= 9
fu_h = 52
filled_rect(c, c2x, y - fu_h, col_w, fu_h, PURPLE_LITE, stroke=PURPLE, radius=3)
y2 = y - 8
fu = [
"Day 1-3: repeat smear; density falling?",
"Day 3: count <25% baseline = adequate",
"Day 7, 14, 28: smear + clinical review",
"Treatment failure → switch ACT / IV art.",
"Primaquine: P. vivax/ovale radical cure",
" CHECK G6PD BEFORE PRESCRIBING",
]
for line in fu:
col = RED if "CHECK" in line else BLACK
fn = "Helvetica-Bold" if "CHECK" in line else "Helvetica"
c.setFillColor(PURPLE if "CHECK" not in line else RED)
c.setFont("Helvetica-Bold", 7.5)
if "CHECK" not in line:
c.drawString(c2x + 4, y2, "›")
c.setFillColor(col); c.setFont(fn, 6.8)
c.drawString(c2x + 11, y2, line)
y2 -= 9
y -= fu_h
# ━━━━━━━━━━━━━━━━━━━━━━━
# COLUMN 3
# ━━━━━━━━━━━━━━━━━━━━━━━
y = cy
# ── SEVERE Tx ──
section_header(c, c3x, y - 9, col_w, 9, "SEVERE MALARIA – TX (HOSPITALISE)", bg=RED)
y -= 9
sev_tx_h = 70
filled_rect(c, c3x, y - sev_tx_h, col_w, sev_tx_h, RED_LITE, stroke=RED, radius=3)
y2 = y - 8
badge(c, c3x + 4, y2 - 7, col_w - 8, 9, "1st LINE: IV ARTESUNATE", bg=RED)
y2 -= 11
rows_st = [
("IV Artesunate", "2.4 mg/kg @ 0h, 12h, 24h; then daily"),
("→ Switch to oral ACT", "when tolerating PO"),
("Alt: IV Quinine", "20 mg/kg load → 10 mg/kg q8h"),
("+ Doxycycline", "100 mg BD (or clindamycin in pregnancy)"),
("Artemether IM", "if no IV access: 3.2 mg/kg stat"),
]
for k, v in rows_st:
c.setFont("Helvetica-Bold", 6.8); c.setFillColor(RED)
c.drawString(c3x + 4, y2, k)
kw = c.stringWidth(k, "Helvetica-Bold", 6.8)
c.setFont("Helvetica", 6.5); c.setFillColor(BLACK)
c.drawString(c3x + 4 + kw + 2, y2, v)
y2 -= 9
y -= sev_tx_h
# Supportive care badge
y -= 2
filled_rect(c, c3x, y - 28, col_w, 28, RED_LITE, stroke=RED, radius=3)
y2 = y - 7
supp = ["Supportive: IV fluids, paracetamol",
"Monitor blood glucose (hypoglycaemia!)",
"Transfuse if Hb <7 g/dL",
"ICU: cerebral malaria / ARDS"]
for line in supp:
c.setFillColor(RED); c.setFont("Helvetica-Bold", 7)
c.drawString(c3x + 4, y2, "▸")
c.setFillColor(BLACK); c.setFont("Helvetica", 6.5)
c.drawString(c3x + 11, y2, line)
y2 -= 7
y -= 28
# ── UNCOMPLICATED Tx ──
y -= 4
section_header(c, c3x, y - 9, col_w, 9, "UNCOMPLICATED MALARIA – TX (ORAL)", bg=GREEN)
y -= 9
unc_h = 82
filled_rect(c, c3x, y - unc_h, col_w, unc_h, GREEN_LITE, stroke=GREEN, radius=3)
y2 = y - 7
# P. falciparum
c.setFillColor(GREEN); c.setFont("Helvetica-Bold", 7)
c.drawString(c3x + 3, y2, "P. falciparum / mixed → ACT (3-day course)")
y2 -= 9
act_lines = [
"Artemether-lumefantrine (AL) ← TAKE WITH FOOD",
"Artesunate-amodiaquine (ASAQ)",
"Dihydroartemisinin-piperaquine (DHP)",
"Artesunate-mefloquine (SE Asia)",
]
for line in act_lines:
c.setFillColor(GREY_DARK if "←" not in line else RED)
c.setFont("Helvetica-Bold" if "←" in line else "Helvetica", 6.5)
c.drawString(c3x + 8, y2, f"• {line}")
y2 -= 8
# P. vivax / ovale
y2 -= 2
c.setFillColor(GREEN); c.setFont("Helvetica-Bold", 7)
c.drawString(c3x + 3, y2, "P. vivax / P. ovale → Chloroquine (3 days)")
y2 -= 9
viv_lines = [
"Chloroquine 620mg → 310mg at 6h, 12h, 24h",
"+ PRIMAQUINE 0.25 mg/kg/day × 14 days",
" ⚠ CHECK G6PD BEFORE PRIMAQUINE",
]
for line in viv_lines:
col = RED if "⚠" in line else GREY_DARK
fn = "Helvetica-Bold" if "⚠" in line else "Helvetica"
c.setFillColor(col); c.setFont(fn, 6.5)
c.drawString(c3x + 8, y2, line)
y2 -= 8
# Antipyretic line
y2 -= 2
c.setFillColor(BLUE); c.setFont("Helvetica-Bold", 6.5)
c.drawString(c3x + 3, y2, "Antipyretic:"); c.setFont("Helvetica", 6.5); c.setFillColor(BLACK)
c.drawString(c3x + 40, y2, "Paracetamol (avoid aspirin)")
y -= unc_h
# ── PROPHYLAXIS ──
y -= 4
section_header(c, c3x, y - 9, col_w, 9, "CHEMOPROPHYLAXIS", bg=ORANGE)
y -= 9
proph_rows = [
["Drug", "Start", "After"],
["Atovaquone-\nproguanil", "1-2d pre","7d post"],
["Doxycycline", "1-2d pre", "4wk post"],
["Mefloquine", "3wk pre", "4wk post"],
["Chloroquine", "1wk pre", "4wk post"],
]
cws3 = [col_w * 0.44, col_w * 0.28, col_w * 0.28]
mini_table(c, c3x, y, proph_rows, cws3, row_h=10,
header_bg=ORANGE, alt_bg=ORANGE_LITE, font_size=6.5)
y -= 10 * len(proph_rows)
# ── SPECIAL POPULATIONS strip ──
y_sp = 32 * mm # fixed y position above footer
section_header(c, M, y_sp, IW, 9, "SPECIAL POPULATIONS", bg=PURPLE)
sp_y = y_sp - 9
sp_entries = [
("Pregnancy T1", "Quinine + clindamycin × 7d; artesunate only if life-threatening"),
("Pregnancy T2/T3","AL or ASAQ (uncomplicated); IV artesunate (severe); NO primaquine"),
("Children", "Weight-based ACT; IV artesunate severe; rectal artesunate if IV delayed"),
("G6PD deficiency","Weekly primaquine 0.75 mg/kg × 8 wks for radical cure; NEVER daily primaquine"),
("HIV (ART)", "AL + efavirenz/lopinavir → reduced lumefantrine; monitor for treatment failure"),
]
sp_col_w = IW / len(sp_entries)
for i, (title, note) in enumerate(sp_entries):
sx = M + i * sp_col_w
filled_rect(c, sx, sp_y - 22, sp_col_w, 22, PURPLE_LITE if i % 2 == 0 else WHITE,
stroke=GREY, radius=0)
c.setFillColor(PURPLE); c.setFont("Helvetica-Bold", 6.5)
c.drawCentredString(sx + sp_col_w / 2, sp_y - 8, title)
# wrap text
words = note.split()
lines_out = []; line_cur = ""
for w in words:
test = (line_cur + " " + w).strip()
if c.stringWidth(test, "Helvetica", 6) < sp_col_w - 6:
line_cur = test
else:
lines_out.append(line_cur); line_cur = w
lines_out.append(line_cur)
yy = sp_y - 15
for ln in lines_out[:2]:
c.setFillColor(BLACK); c.setFont("Helvetica", 6)
c.drawCentredString(sx + sp_col_w / 2, yy, ln)
yy -= 7
# ── FOOTER ──
filled_rect(c, 0, 0, W, 10 * mm, NAVY, radius=0)
c.setFillColor(GOLD); c.setFont("Helvetica-Bold", 7)
c.drawCentredString(W / 2, 6 * mm, "⚠ Always confirm with blood smear + RDT before treatment. "
"Treat suspected severe malaria IMMEDIATELY without waiting for results.")
c.setFillColor(HexColor("#99AABB")); c.setFont("Helvetica", 6)
c.drawCentredString(W / 2, 2.5 * mm,
"Sources: WHO Guidelines for Malaria (Nov 2024) | Tintinalli's EM 9e | "
"Rosen's EM 9e | Harrison's Principles 22e | CDC 2024")
def main():
c = canvas.Canvas(OUTPUT, pagesize=A4)
c.setTitle("Malaria Point-of-Care Quick Reference Card")
c.setAuthor("Orris Medical Reference")
c.setSubject("Malaria POC Quick Reference – Symptoms, Diagnosis, Treatment")
draw(c)
c.save()
print(f"Saved: {OUTPUT}")
if __name__ == "__main__":
main()
cd /home/daytona/workspace/malaria-pdf && python generate_poc_card.py 2>&1
ls -lh /home/daytona/workspace/malaria-pdf/Malaria_POC_QuickRef.pdf
Malaria POC QuickRef
PDF Document · PDF
Dengue symptoms, diagnosis, treatment flow chart diagram
dengue fever symptoms diagnosis treatment WHO classification 2024 guidelines
A clean, professional medical flowchart diagram titled "Dengue Fever: Symptoms, Diagnosis & Treatment" with the following detailed flow structure: START BOX at top (dark teal background, white text): "Patient presents with ACUTE FEVER (2-7 days) + Travel/Residence in dengue-endemic area" Arrow down to SYMPTOMS BOX (light amber/yellow background, amber border): Title: "SYMPTOMS – Febrile Phase (Days 1-3)" • Sudden high fever (39-40°C) • Severe headache + retro-orbital pain • Myalgia / arthralgia / bone pain ("breakbone fever") • Nausea and vomiting • Facial flushing / facial erythema • Maculopapular rash (trunk spreading to extremities) • Leukopenia (characteristic) • Petechiae / minor bleeding • Positive tourniquet test Arrow down to WHO CLASSIFICATION DIAMOND (decision diamond, amber border): "Apply WHO 2009 Classification" Three branches emerging: LEFT BRANCH - "Dengue WITHOUT Warning Signs" (blue-green box): Fever + ≥2 of: • Nausea/vomiting • Rash • Aches and pains • Leukopenia • Positive tourniquet test → Group A: Outpatient management CENTRE BRANCH - "Dengue WITH Warning Signs" (orange box): Any of the following (Days 3-7, Critical Phase): • Abdominal pain or tenderness • Persistent vomiting • Clinical fluid accumulation (ascites, pleural effusion) • Mucosal bleeding • Lethargy / restlessness • Liver enlargement >2 cm • ↑ Hematocrit + rapid ↓ platelet count → Group B: Hospitalise RIGHT BRANCH - "SEVERE Dengue" (red box): Any ONE of: • Severe plasma leakage → shock (DSS) • Fluid accumulation + respiratory distress • Severe bleeding (clinician assessed) • Severe organ involvement: - Liver: AST/ALT ≥1000 IU/L - CNS: impaired consciousness - Heart failure / other organ failure → Group C: Emergency/ICU Arrow down from all branches to DIAGNOSIS BOX (blue background): Title: "DIAGNOSIS" Time-based testing: • Days 1-5 (Febrile Phase): RT-PCR (dengue RNA) OR NS1 antigen test • Days 5-10 (Late febrile/Critical): IgM antibody (EIA) – detectable from Day 3-5 • Combined NS1 + IgM on single specimen: identifies ≥90% of cases • CBC: thrombocytopenia (platelets <100,000) + ↑ hematocrit (hemoconcentration) • Note: IgG may cross-react with Zika, West Nile, Yellow Fever, JE Arrow down to TREATMENT section splitting into THREE columns: LEFT COLUMN - Group A: Dengue WITHOUT Warning Signs (teal/green header): "OUTPATIENT MANAGEMENT" • Adequate oral hydration (ORS, fluids, coconut water) • Paracetamol for fever (max 4g/day adult) • AVOID: NSAIDs, aspirin, ibuprofen (bleeding risk) • Monitor daily: platelet count + hematocrit from Day 3 • Return immediately if warning signs develop • Rest and mosquito bite prevention (prevent spread) CENTRE COLUMN - Group B: Dengue WITH Warning Signs (orange header): "HOSPITALISE – IV Fluid Therapy" • IV crystalloid (0.9% NaCl or Ringer's lactate) • Fluid bolus 5-10 mL/kg over 1 hour if compensated shock • Monitor vital signs every 1-4 hours • CBC every 4-6 hours • Maintain urine output 0.5-1 mL/kg/hr • Observe during critical phase (24-48 hours) • Platelet transfusion only if <20,000 + active bleeding • Transition to oral fluids when improving RIGHT COLUMN - Group C: SEVERE Dengue (red header): "ICU / EMERGENCY MANAGEMENT" • Aggressive IV fluid resuscitation (10-20 mL/kg bolus) • Blood products: packed RBCs if Hb <7 g/dL • Platelet transfusion: <10,000 or active bleed • Fresh frozen plasma (FFP) for coagulopathy • Vasopressors if fluid-refractory shock • Mechanical ventilation if respiratory failure • Treat underlying organ dysfunction • Avoid excessive fluids (pulmonary oedema risk) Arrow down to MONITORING & DISCHARGE BOX (purple background): Title: "MONITORING PARAMETERS & DISCHARGE CRITERIA" • Platelet count + hematocrit monitoring: daily from Day 3 • Defervescence (Day 3-7): CRITICAL PHASE – increased risk of complications • Discharge criteria: afebrile ≥24h, improving appetite, stable hematocrit, platelets >50,000, no respiratory distress • Convalescent phase: bradypulse rash, fatigue may persist 2-4 weeks Bottom note box (light yellow): "NO specific antiviral therapy exists for dengue. Management is entirely supportive." Color scheme: teal/dark green header, amber/orange for warning signs, red for severe, blue for diagnosis, purple for monitoring. Clean white background, medical professional style with clear directional arrows.

| Group | Classification | Management |
|---|---|---|
| A | Dengue WITHOUT warning signs | Outpatient, oral hydration |
| B | Dengue WITH warning signs | Hospitalise, IV fluids |
| C | Severe dengue (shock/bleeding/organ failure) | ICU, emergency Tx |
Poc and refrence card pdf
~/dengue-pdf/generate_dengue_reference.py
#!/usr/bin/env python3
"""
Dengue Fever – Detailed Clinical Reference PDF (2 pages)
Page 1: Canvas flowchart | Page 2: Reference tables
"""
from reportlab.pdfgen import canvas as rl_canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib.colors import HexColor, white, black
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
OUTPUT = "/home/daytona/workspace/dengue-pdf/Dengue_Clinical_Reference.pdf"
W, H = A4
# ── Palette ──────────────────────────────────────────────────
TEAL = HexColor("#0D6B6E")
TEAL_LIGHT = HexColor("#D0ECEC")
TEAL_PALE = HexColor("#E8F7F7")
AMBER = HexColor("#C96A00")
AMBER_LIGHT = HexColor("#FEF0DC")
AMBER_PALE = HexColor("#FFFBF5")
ORANGE = HexColor("#D45A00")
ORANGE_LITE = HexColor("#FDECEA")
RED = HexColor("#B01C1C")
RED_LITE = HexColor("#FDECEA")
BLUE = HexColor("#1A5EA8")
BLUE_LIGHT = HexColor("#D6E8FA")
BLUE_PALE = HexColor("#EEF6FF")
PURPLE = HexColor("#5B2C8D")
PURPLE_LITE = HexColor("#EDE7F6")
NAVY = HexColor("#0D2B4E")
GOLD = HexColor("#E8A020")
GREY = HexColor("#BBBBBB")
GREY_DARK = HexColor("#555555")
GREY_LIGHT = HexColor("#F5F5F5")
WHITE = white
BLACK = black
# ── Canvas helpers ────────────────────────────────────────────
def rr(c, x, y, w, h, fill, stroke=None, lw=0.7, r=4):
c.setFillColor(fill)
if stroke:
c.setStrokeColor(stroke); c.setLineWidth(lw)
c.roundRect(x, y, w, h, r, fill=1, stroke=1)
else:
c.roundRect(x, y, w, h, r, fill=1, stroke=0)
def box_title(c, x, y, w, h, title, bg=NAVY, fg=WHITE, fsize=9):
rr(c, x, y, w, h, bg, r=3)
c.setFillColor(fg); c.setFont("Helvetica-Bold", fsize)
c.drawCentredString(x + w/2, y + h/2 - fsize*0.35, title)
def arrow_v(c, x, y1, y2, col=TEAL):
c.setStrokeColor(col); c.setFillColor(col); c.setLineWidth(1.4)
c.line(x, y1, x, y2+5)
p = c.beginPath()
p.moveTo(x, y2); p.lineTo(x-4, y2+7); p.lineTo(x+4, y2+7)
p.close(); c.drawPath(p, fill=1, stroke=0)
def arrow_h(c, x1, x2, y, col=TEAL):
c.setStrokeColor(col); c.setFillColor(col); c.setLineWidth(1.4)
dx = 1 if x2 > x1 else -1
c.line(x1, y, x2 - dx*5, y)
p = c.beginPath()
p.moveTo(x2, y); p.lineTo(x2 - dx*7, y+4); p.lineTo(x2 - dx*7, y-4)
p.close(); c.drawPath(p, fill=1, stroke=0)
def text_lines(c, x, y, lines, size=7.5, lead=10, font="Helvetica",
color=BLACK, bullet_color=None, indent=0):
for line in lines:
if bullet_color:
c.setFillColor(bullet_color); c.setFont("Helvetica-Bold", size+1)
c.drawString(x, y, "•")
c.setFillColor(color); c.setFont(font, size)
c.drawString(x + 9, y, line)
else:
c.setFillColor(color); c.setFont(font, size)
c.drawString(x + indent, y, line)
y -= lead
return y
def flowbox(c, x, y, w, h, title, lines, bg, border, tbg, tfg=WHITE,
fsize=7.5, tsize=8.5, lead=9):
rr(c, x, y, w, h, bg, stroke=border, lw=1.2, r=4)
rr(c, x, y+h-16, w, 16, tbg, r=3)
c.setFillColor(tfg); c.setFont("Helvetica-Bold", tsize)
c.drawCentredString(x+w/2, y+h-11, title)
cy = y+h-22
for line in lines:
if cy < y+3: break
if line.startswith("**"):
c.setFont("Helvetica-Bold", fsize); c.setFillColor(border)
c.drawString(x+5, cy, line[2:])
else:
c.setFont("Helvetica", fsize); c.setFillColor(BLACK)
c.drawString(x+5, cy, line)
cy -= lead
def draw_diamond(c, cx, cy, w, h, lines, bg=AMBER_LIGHT, border=AMBER, fsize=8):
pts = [cx, cy+h/2, cx+w/2, cy, cx, cy-h/2, cx-w/2, cy]
c.setFillColor(bg); c.setStrokeColor(border); c.setLineWidth(1.5)
p = c.beginPath()
p.moveTo(pts[0], pts[1])
for i in range(2, len(pts), 2): p.lineTo(pts[i], pts[i+1])
p.close(); c.drawPath(p, fill=1, stroke=1)
c.setFillColor(NAVY); c.setFont("Helvetica-Bold", fsize)
for i, ln in enumerate(lines):
c.drawCentredString(cx, cy + (len(lines)-1)*5 - i*10, ln)
# ── Header / Footer ───────────────────────────────────────────
def header_footer(cv, doc):
cv.saveState()
cv.setFillColor(TEAL)
cv.rect(0, H-26*mm, W, 26*mm, fill=1, stroke=0)
cv.setFillColor(AMBER)
cv.rect(0, H-28*mm, W, 2*mm, fill=1, stroke=0)
cv.setFillColor(WHITE); cv.setFont("Helvetica-Bold", 14)
cv.drawString(14*mm, H-13*mm, "DENGUE FEVER – Clinical Reference Guide")
cv.setFont("Helvetica", 8.5); cv.setFillColor(TEAL_LIGHT)
cv.drawRightString(W-14*mm, H-10*mm, "Symptoms · WHO Classification · Diagnosis · Treatment")
cv.drawRightString(W-14*mm, H-17*mm, "WHO 2009 | Red Book 2021 | Harrison's 22E | PAHO 2024")
cv.setFillColor(GREY_LIGHT); cv.rect(0, 0, W, 11*mm, fill=1, stroke=0)
cv.setFillColor(GREY_DARK); cv.setFont("Helvetica", 7)
cv.drawString(14*mm, 4*mm,
"Sources: WHO Dengue Guidelines 2009 | AAP Red Book 2021 | Harrison's Principles of Internal Medicine 22E | PAHO Algorithms 2024")
cv.drawRightString(W-14*mm, 4*mm, f"Page {doc.page}")
cv.restoreState()
# ══════════════════════════════════════════════════════════════
# PAGE 1 – FLOWCHART
# ══════════════════════════════════════════════════════════════
class DengueFlowchart:
def draw(self, cv):
# start box
sx = W/2-120; sy = H-78*mm; sw=240; sh=20
rr(cv, sx, sy, sw, sh, TEAL, r=6)
cv.setFillColor(WHITE); cv.setFont("Helvetica-Bold", 8.5)
cv.drawCentredString(W/2, sy+6,
"ACUTE FEVER (2-7 days) + Travel / Residence in Dengue-Endemic Area")
arrow_v(cv, W/2, sy, sy-10)
# incubation note
cv.setFillColor(GREY_DARK); cv.setFont("Helvetica-Oblique", 6.8)
cv.drawCentredString(W/2, sy-17, "Incubation: 3-14 days | Transmitted by Aedes aegypti (day-biting)")
# SYMPTOMS box
sym_y = sy-14-80; sym_x=W/2-120; sym_w=240; sym_h=80
flowbox(cv, sym_x, sym_y, sym_w, sym_h,
"SYMPTOMS (Febrile Phase Days 1–3)",
["Sudden high fever 39-40°C",
"Severe headache + retro-orbital pain",
'Myalgia / arthralgia / bone pain ("breakbone fever")',
"Nausea, vomiting | Facial flushing",
"Maculopapular rash (trunk → extremities)",
"Leukopenia (characteristic finding)",
"Petechiae / minor bleeding | Positive tourniquet test"],
bg=AMBER_LIGHT, border=AMBER, tbg=AMBER, tsize=9)
arrow_v(cv, W/2, sym_y, sym_y-10)
# WHO classification diamond
dia_cy = sym_y - 10 - 28
draw_diamond(cv, W/2, dia_cy, 220, 52,
["Apply WHO 2009 Classification", "(Days 3-7: Critical Phase)"],
bg=AMBER_LIGHT, border=AMBER, fsize=8)
# Branch labels
cv.setFont("Helvetica-Bold", 7.5)
cv.setFillColor(BLUE); cv.drawString(14*mm, dia_cy+2, "Group A")
cv.setFillColor(ORANGE); cv.drawCentredString(W/2, dia_cy-32, "Group B")
cv.setFillColor(RED); cv.drawRightString(W-14*mm, dia_cy+2, "Group C")
# Three branch boxes
bx_h = 90
# Group A – no warning signs (left)
ax = 13*mm; aw = 120
ay = dia_cy - 30 - bx_h
arrow_h(cv, W/2-110, ax+aw, dia_cy, col=BLUE)
arrow_v(cv, ax+aw/2, dia_cy, ay+bx_h, col=BLUE)
flowbox(cv, ax, ay, aw, bx_h,
"WITHOUT Warning Signs",
["Fever + ≥2 of:",
"• Nausea/vomiting",
"• Rash",
"• Aches and pains",
"• Leukopenia",
"• +ve tourniquet test",
"",
"→ OUTPATIENT (Group A)"],
bg=TEAL_PALE, border=TEAL, tbg=TEAL, tsize=8)
# Group B – with warning signs (centre)
bx = W/2-65; bw = 130
bby = dia_cy-30-bx_h
arrow_v(cv, W/2, dia_cy-26, bby+bx_h, col=ORANGE)
flowbox(cv, bx, bby, bw, bx_h,
"WITH Warning Signs",
["• Abdominal pain/tenderness",
"• Persistent vomiting",
"• Fluid accumulation",
"• Mucosal bleeding",
"• Lethargy/restlessness",
"• Liver >2 cm",
"• ↑HCT + rapid ↓platelets",
"→ HOSPITALISE (Group B)"],
bg=AMBER_LIGHT, border=ORANGE, tbg=ORANGE, tsize=8)
# Group C – severe (right)
cx2 = W-13*mm-120; cw2 = 120
cy2 = dia_cy-30-bx_h
arrow_h(cv, W/2+110, cx2, dia_cy, col=RED)
arrow_v(cv, cx2+cw2/2, dia_cy, cy2+bx_h, col=RED)
flowbox(cv, cx2, cy2, cw2, bx_h,
"SEVERE Dengue",
["Severe plasma leakage:",
"• Shock (DSS)",
"• Resp. distress",
"Severe bleeding",
"Organ involvement:",
"• AST/ALT ≥1000",
"• Impaired consciousness",
"→ ICU (Group C)"],
bg=RED_LITE, border=RED, tbg=RED, tsize=8)
# DIAGNOSIS box
diag_y = ay - 12 - 80; diag_x = W/2-145; diag_w = 290; diag_h = 80
# arrows converging
arrow_v(cv, ax+aw/2, ay, ay-6, col=BLUE)
arrow_h(cv, ax+aw/2, W/2, ay-6, col=TEAL)
arrow_v(cv, cx2+cw2/2, cy2, cy2-6, col=RED)
arrow_h(cv, cx2+cw2/2, W/2, cy2-6, col=TEAL)
arrow_v(cv, W/2, bby, bby-6, col=ORANGE)
# horizontal merge line
cv.setStrokeColor(TEAL); cv.setLineWidth(1.4)
merge_y = min(ay, cy2, bby)-6
cv.line(ax+aw/2, merge_y, cx2+cw2/2, merge_y)
arrow_v(cv, W/2, merge_y, diag_y+diag_h)
flowbox(cv, diag_x, diag_y, diag_w, diag_h,
"DIAGNOSIS (Time-Based Testing)",
["Days 1-5 (Febrile): RT-PCR (dengue RNA) OR NS1 antigen test",
"Days 3-10 (Late febrile/Critical): IgM antibody (EIA) – 99% by Day 10",
"Combined NS1 + IgM on single specimen → identifies ≥90% of cases",
"CBC: thrombocytopenia (plt <100,000) + rising haematocrit (haemoconcentration)",
"⚠ IgM cross-reacts with Zika, West Nile, Yellow Fever, Japanese Encephalitis",
"IgG elevated lifelong – use acute+convalescent paired sera (≥4× rise = confirmed)"],
bg=BLUE_PALE, border=BLUE, tbg=BLUE, tsize=9)
arrow_v(cv, W/2, diag_y, diag_y-10)
# TREATMENT boxes – 3 columns
tx_h = 95
tx_y = diag_y - 12 - tx_h
tw = (W - 30*mm) / 3 - 2*mm
t1x = 14*mm; t2x = t1x+tw+3*mm; t3x = t2x+tw+3*mm
# Split arrow
cv.setStrokeColor(TEAL); cv.setLineWidth(1.2)
cv.line(W/2, diag_y-10, W/2, tx_y+tx_h+8)
# horizontal split
cv.line(t1x+tw/2, tx_y+tx_h+8, t3x+tw/2, tx_y+tx_h+8)
for tx in [t1x+tw/2, t2x+tw/2, t3x+tw/2]:
arrow_v(cv, tx, tx_y+tx_h+8, tx_y+tx_h, col=TEAL)
flowbox(cv, t1x, tx_y, tw, tx_h,
"Group A – Outpatient",
["• Adequate oral hydration",
" (ORS, water, coconut water)",
"• Paracetamol for fever",
" (max 4 g/day adult)",
"• AVOID NSAIDs/aspirin!",
"• Daily platelet + HCT",
" from Day 3",
"• Return if warning signs",
"• Mosquito bite prevention"],
bg=TEAL_PALE, border=TEAL, tbg=TEAL, tsize=8)
flowbox(cv, t2x, tx_y, tw, tx_h,
"Group B – Hospitalise",
["• IV crystalloid (0.9% NaCl",
" or Ringer's lactate)",
"• 5-10 mL/kg/hr bolus",
" if compensated shock",
"• Vitals every 1-4 hrs",
"• CBC every 4-6 hrs",
"• Urine output 0.5-1 mL/kg/hr",
"• Plt transfusion only if",
" <20,000 + active bleeding"],
bg=AMBER_LIGHT, border=ORANGE, tbg=ORANGE, tsize=8)
flowbox(cv, t3x, tx_y, tw, tx_h,
"Group C – ICU/Emergency",
["• Aggressive IV resus.",
" 10-20 mL/kg bolus",
"• pRBCs if Hb <7 g/dL",
"• Plt transfusion <10,000",
" or active bleeding",
"• FFP for coagulopathy",
"• Vasopressors if refractory",
"• Mechanical ventilation",
" if respiratory failure"],
bg=RED_LITE, border=RED, tbg=RED, tsize=8)
# Follow-up box
fu_y = tx_y - 12 - 48; fu_x = 14*mm; fu_w = W-28*mm; fu_h = 48
cv.setStrokeColor(TEAL); cv.setLineWidth(1.2)
cv.line(t1x+tw/2, tx_y, t1x+tw/2, fu_y+fu_h+6)
cv.line(t3x+tw/2, tx_y, t3x+tw/2, fu_y+fu_h+6)
cv.line(t1x+tw/2, fu_y+fu_h+6, t3x+tw/2, fu_y+fu_h+6)
arrow_v(cv, W/2, fu_y+fu_h+6, fu_y+fu_h)
flowbox(cv, fu_x, fu_y, fu_w, fu_h,
"MONITORING & DISCHARGE CRITERIA",
["• Critical phase (Days 3-7 / defervescence): highest risk of plasma leakage, shock, haemorrhage – monitor hourly",
"• Discharge criteria: afebrile ≥24h, no warning signs, improving appetite, stable HCT, platelets >50,000, adequate urine output",
"• Convalescent phase: bradycardia, convalescent rash (isles of white in sea of red), fatigue may persist 2-4 weeks",
"• NO specific antiviral exists – management is entirely SUPPORTIVE"],
bg=PURPLE_LITE, border=PURPLE, tbg=PURPLE, tsize=9, lead=10)
# ══════════════════════════════════════════════════════════════
# PAGE 2 – REFERENCE TABLES
# ══════════════════════════════════════════════════════════════
def build_reference(story):
def sec(text, bg=TEAL):
return Paragraph(f" {text}", ParagraphStyle("sh", fontName="Helvetica-Bold",
fontSize=9, textColor=white, backColor=bg, leading=15,
leftIndent=4, spaceAfter=2, spaceBefore=6, borderPad=3))
def body(text, bold=False, size=8, color=BLACK, indent=0):
return Paragraph(text, ParagraphStyle("b", fontName="Helvetica-Bold" if bold else "Helvetica",
fontSize=size, textColor=color, leftIndent=indent, leading=size+4, spaceAfter=1))
def tbl(data, cws, hbg=TEAL, altbg=TEAL_LIGHT, fs=7.5):
t = Table(data, colWidths=cws)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), hbg),
("TEXTCOLOR", (0,0), (-1,0), white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), fs),
("FONTNAME", (0,1), (-1,-1), "Helvetica"),
("FONTSIZE", (0,1), (-1,-1), fs-0.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, altbg]),
("GRID", (0,0), (-1,-1), 0.4, GREY),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("LEFTPADDING",(0,0), (-1,-1), 5),
("RIGHTPADDING",(0,0), (-1,-1), 5),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING",(0,0), (-1,-1), 3),
]))
return t
story.append(Spacer(1, 31*mm))
# 1. WHO Classification
story.append(sec("1. WHO 2009 DENGUE CLASSIFICATION & MANAGEMENT GROUPS", bg=TEAL))
story.append(Spacer(1,3))
d1 = [
["Group","Classification","Key Features","Setting","Action"],
["A","Dengue WITHOUT\nWarning Signs",
"Fever + ≥2: nausea/vomiting, rash, aches/pains,\nleukopenia, +ve tourniquet test",
"Outpatient","Oral fluids, paracetamol, daily CBC"],
["B","Dengue WITH\nWarning Signs",
"Abdominal pain, persistent vomiting, fluid accumulation,\nmucosal bleed, lethargy, liver >2 cm, ↑HCT+↓plt",
"Hospital ward","IV fluids, close monitoring"],
["C","SEVERE Dengue",
"Severe plasma leakage → shock (DSS); severe bleeding;\norgan impairment (AST/ALT ≥1000, coma, heart failure)",
"ICU","Emergency resuscitation"],
]
story.append(tbl(d1, [1.2*mm*10, 3*mm*10, 6.5*mm*10, 2.5*mm*10, 4.3*mm*10], hbg=TEAL))
story.append(Spacer(1,6))
# 2. Warning Signs detail
story.append(sec("2. WARNING SIGNS IN DETAIL (Group B – Hospitalise)", bg=ORANGE))
story.append(Spacer(1,3))
d2 = [
["Warning Sign","Clinical Significance"],
["Abdominal pain or tenderness","Ascites or hepatic congestion – plasma leakage imminent"],
["Persistent vomiting (≥3× in 1h)","Prevents oral hydration; fluid depletion risk"],
["Clinical fluid accumulation","Pleural effusion, ascites – confirms plasma leakage"],
["Mucosal bleed (nose, gums, vagina)","Coagulopathy or thrombocytopenia-related"],
["Lethargy / restlessness","Early CNS compromise or haemodynamic instability"],
["Liver enlargement >2 cm","Hepatitis / dengue hepatopathy"],
["Rapid ↑HCT concurrent with rapid ↓platelets","Hallmark of significant plasma leakage"],
]
story.append(tbl(d2, [6*mm*10, 12.5*mm*10], hbg=ORANGE, altbg=AMBER_LIGHT))
story.append(Spacer(1,6))
# 3. Diagnosis
story.append(sec("3. DIAGNOSTIC TESTS – TIME-BASED GUIDE", bg=BLUE))
story.append(Spacer(1,3))
d3 = [
["Test","Window","Detects","Sensitivity","Notes"],
["RT-PCR","Days 1-7","Dengue RNA","High (early)","Gold standard for early phase; also serotypes 1-4"],
["NS1 Antigen (EIA/RDT)","Days 1-9","Viral NS1 protein","80-90%","Positive from day 1; combined NS1+IgM ≥90%"],
["IgM Antibody (EIA)","Day 3-5 onset;\npeak 2 weeks","Anti-dengue IgM","99% by Day 10","Cross-reacts with Zika, WNV, JE, YFV"],
["IgG Antibody","Lifetime","Anti-dengue IgG","High (convalescent)","≥4× rise acute vs. convalescent = confirmed"],
["CBC","Any time","Thrombocytopenia\n+ haemoconcentration","—","Platelets <100,000 + ↑HCT = plasma leakage"],
["Tourniquet test","Any time","Capillary fragility","Supportive","Inflate BP cuff mid-systolic/diastolic × 5 min; ≥10 petechiae/in² = positive"],
]
story.append(tbl(d3, [3.8*mm*10, 3*mm*10, 3.5*mm*10, 2.8*mm*10, 5.4*mm*10], hbg=BLUE, altbg=BLUE_LIGHT))
story.append(Spacer(1,6))
# 4. Treatment
story.append(sec("4. TREATMENT PROTOCOLS BY GROUP", bg=TEAL))
story.append(Spacer(1,3))
d4 = [
["Parameter","Group A (Outpatient)","Group B (Hospital)","Group C (ICU)"],
["Fluids","Oral hydration (ORS)\n≥5 glasses/day","IV crystalloid (0.9% NaCl or\nRL) 5-10 mL/kg/hr",
"Aggressive bolus 10-20 mL/kg;\nthen titrate to response"],
["Fever","Paracetamol 500-1000 mg\nq6h (max 4 g/day)","Paracetamol; tepid sponging",
"Paracetamol; temperature\nmanagement"],
["Avoid","NSAIDs, aspirin,\nibuprofen (bleed risk)","NSAIDs, aspirin",
"Excessive IV fluids\n(pulmonary oedema risk)"],
["Platelet transfusion","Not indicated","Only if <20,000\n+ active bleeding",
"If <10,000 or\nclinically significant bleed"],
["Blood transfusion","Not indicated","If Hb <7 g/dL\n+ haemodynamic instability",
"pRBCs if Hb <7 g/dL;\nFFP for coagulopathy"],
["Monitoring","Daily CBC (Day 3 onwards)\nUntil 1-2 days post-defervescence",
"Vitals q1-4h; CBC q4-6h;\nurine output q1h",
"Continuous monitoring;\nICU-level care"],
["Antivirals","NONE – no approved antiviral","NONE","NONE"],
]
story.append(tbl(d4, [3.5*mm*10, 5*mm*10, 5*mm*10, 5*mm*10], hbg=TEAL, altbg=TEAL_LIGHT))
story.append(Spacer(1,6))
# 5. Disease Phases
story.append(sec("5. THREE CLINICAL PHASES OF DENGUE", bg=PURPLE))
story.append(Spacer(1,3))
d5 = [
["Phase","Duration","Key Features","Clinical Action"],
["FEBRILE","Days 1-3",
"High fever, facial flushing, rash, myalgia, headache,\nretro-orbital pain; minor bleeding possible",
"Oral hydration; paracetamol; monitor for warning signs;\nNSAIDs CONTRAINDICATED"],
["CRITICAL","Days 3-7\n(defervescence)",
"Plasma leakage (↑HCT), thrombocytopenia; risk of\nshock (DSS), severe bleeding, organ damage",
"HIGHEST RISK PERIOD – intensive monitoring;\nIV fluids for Groups B/C; hourly vitals"],
["CONVALESCENT","Days 7-10+",
"Reabsorption of leaked fluids; bradycardia common;\nconvalescent rash (isles of white); gradual recovery",
"Beware fluid overload during reabsorption;\nmonitor for pulmonary oedema"],
]
story.append(tbl(d5, [3*mm*10, 2.8*mm*10, 6.7*mm*10, 6*mm*10], hbg=PURPLE, altbg=PURPLE_LITE))
story.append(Spacer(1,6))
# 6. Special populations
story.append(sec("6. SPECIAL POPULATIONS & RISK FACTORS", bg=RED))
story.append(Spacer(1,3))
d6 = [
["Population","Risk","Management"],
["Second dengue infection (different serotype)",
"Antibody-dependent enhancement → severe dengue (DHF/DSS)",
"High index of suspicion; early hospitalisation"],
["Infants (<1 year)","Higher mortality; atypical presentation",
"Lower threshold for hospitalisation; weight-based fluid management"],
["Pregnant women","Vertical transmission ~20%; severe complications",
"Close fetal monitoring; avoid NSAIDs; manage post-partum haemorrhage risk"],
["Chronic disease (asthma, sickle cell, diabetes)",
"Increased severe disease risk","Hospitalise early; tighter glycaemic control"],
["Dengue vaccine (Dengvaxia / CYD-TDV)",
"Increases risk of severe dengue in seronegative individuals",
"Vaccinate only if pre-vaccination serostatus confirmed positive; not for naive individuals"],
["Returning travellers","May present outside endemic area; clinicians unfamiliar",
"CBC, NS1+IgM testing; consider dengue in any febrile returning traveller"],
]
story.append(tbl(d6, [5*mm*10, 5.5*mm*10, 8*mm*10], hbg=RED, altbg=RED_LITE))
story.append(Spacer(1,6))
# 7. Discharge
story.append(sec("7. DISCHARGE CRITERIA", bg=TEAL))
story.append(Spacer(1,3))
d7 = [["Criterion","Target / Definition"],
["Afebrile","≥24 hours without antipyretics"],
["No warning signs","No abdominal pain, vomiting, bleeding, restlessness"],
["Improving appetite","Able to tolerate oral fluids and diet"],
["Haematocrit","Stable (not rising)"],
["Platelet count",">50,000 per µL and rising"],
["Urine output","Adequate (>1 mL/kg/hr for previous 24 hours)"],
["No respiratory distress","No pleural effusion causing distress"],
]
story.append(tbl(d7, [8*mm*10, 10.5*mm*10], hbg=TEAL, altbg=TEAL_LIGHT))
story.append(Spacer(1,8))
story.append(HRFlowable(width="100%", thickness=0.5, color=GREY))
story.append(Spacer(1,3))
story.append(Paragraph(
"<b>References:</b> "
"1. WHO. Dengue: Guidelines for Diagnosis, Treatment, Prevention and Control. WHO/TDR, 2009. "
"2. AAP Red Book 2021 – Report of the Committee on Infectious Diseases, 32nd Edition. "
"3. Loscalzo J et al. Harrison's Principles of Internal Medicine, 22nd ed. McGraw-Hill, 2025. "
"4. PAHO. Algorithms for the Clinical Management of Dengue Patients. June 2024. "
"5. CDC. Guidelines for Classifying Dengue. cdc.gov/dengue, 2024.",
ParagraphStyle("ref", fontName="Helvetica", fontSize=6.5, textColor=GREY_DARK, leading=9)))
return story
# ══════════════════════════════════════════════════════════════
# BUILD
# ══════════════════════════════════════════════════════════════
def build():
import os; os.makedirs("/home/daytona/workspace/dengue-pdf", exist_ok=True)
doc = SimpleDocTemplate(OUTPUT, pagesize=A4,
leftMargin=14*mm, rightMargin=14*mm,
topMargin=30*mm, bottomMargin=13*mm,
title="Dengue Fever Clinical Reference Guide",
author="Orris Medical Reference",
subject="Dengue Symptoms, Diagnosis, Treatment – WHO 2009 Classification")
def on_first(cv, doc):
header_footer(cv, doc)
DengueFlowchart().draw(cv)
def on_later(cv, doc):
header_footer(cv, doc)
story = [Spacer(1, 1), PageBreak()]
build_reference(story)
doc.build(story, onFirstPage=on_first, onLaterPages=on_later)
print(f"Saved: {OUTPUT}")
if __name__ == "__main__":
build()
~/dengue-pdf/generate_dengue_poc.py
#!/usr/bin/env python3
"""
Dengue Fever – Point-of-Care Quick Reference Card
Single A4 page – 3 column layout for clinical wall/desk use
"""
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib.colors import HexColor, white, black
OUTPUT = "/home/daytona/workspace/dengue-pdf/Dengue_POC_QuickRef.pdf"
W, H = A4
TEAL = HexColor("#0D6B6E")
TEAL_LIGHT = HexColor("#D0ECEC")
TEAL_PALE = HexColor("#E8F7F7")
AMBER = HexColor("#C96A00")
AMBER_LIGHT = HexColor("#FEF0DC")
ORANGE = HexColor("#D45A00")
ORANGE_LITE = HexColor("#FDECEA")
RED = HexColor("#B01C1C")
RED_LITE = HexColor("#FDECEA")
BLUE = HexColor("#1A5EA8")
BLUE_LIGHT = HexColor("#D6E8FA")
BLUE_PALE = HexColor("#EEF6FF")
PURPLE = HexColor("#5B2C8D")
PURPLE_LITE = HexColor("#EDE7F6")
NAVY = HexColor("#0D2B4E")
GOLD = HexColor("#E8A020")
GREY = HexColor("#BBBBBB")
GREY_DARK = HexColor("#444444")
WHITE = white
BLACK = black
def rr(c, x, y, w, h, fill, stroke=None, lw=0.6, r=3):
c.setFillColor(fill)
if stroke:
c.setStrokeColor(stroke); c.setLineWidth(lw)
c.roundRect(x, y, w, h, r, fill=1, stroke=1)
else:
c.roundRect(x, y, w, h, r, fill=1, stroke=0)
def sec_hdr(c, x, y, w, h, text, bg=TEAL, fg=WHITE, fsize=8.5):
rr(c, x, y, w, h, bg, r=3)
c.setFillColor(fg); c.setFont("Helvetica-Bold", fsize)
c.drawCentredString(x+w/2, y+h/2-fsize*0.35, text)
def txt(c, x, y, t, font="Helvetica", size=7.5, color=BLACK):
c.setFont(font, size); c.setFillColor(color); c.drawString(x, y, t)
def ctxt(c, x, y, t, font="Helvetica", size=7.5, color=BLACK):
c.setFont(font, size); c.setFillColor(color); c.drawCentredString(x, y, t)
def mini_tbl(c, x, y, rows, cws, rh=10.5, hbg=TEAL, hfg=WHITE, altbg=None, fs=7):
for ri, row in enumerate(rows):
cx = x
is_hdr = ri == 0
for ci, (cell, cw) in enumerate(zip(row, cws)):
bg = hbg if is_hdr else (altbg if altbg and ri%2==0 else WHITE)
fg = hfg if is_hdr else BLACK
fn = "Helvetica-Bold" if is_hdr else "Helvetica"
rr(c, cx, y-rh, cw, rh, bg)
c.setStrokeColor(GREY); c.setLineWidth(0.3)
c.rect(cx, y-rh, cw, rh, fill=0, stroke=1)
c.setFillColor(fg); c.setFont(fn, fs)
# wrap if needed
words = str(cell).split('\n')
line_y = y - rh + 3 + (len(words)-1)*7
for ln in words:
c.drawString(cx+3, line_y, ln)
line_y -= 7
cx += cw
y -= rh
return y
def draw(c):
M = 6*mm
IW = W - 2*M
# BG
c.setFillColor(HexColor("#F2F7F7")); c.rect(0,0,W,H,fill=1,stroke=0)
# Header
hh = 19*mm
rr(c, 0, H-hh, W, hh, TEAL, r=0)
rr(c, 0, H-hh-2.5*mm, W, 2.5*mm, AMBER, r=0)
c.setFillColor(WHITE); c.setFont("Helvetica-Bold", 16)
c.drawCentredString(W/2, H-11.5*mm, "DENGUE FEVER QUICK REFERENCE CARD")
c.setFont("Helvetica", 8); c.setFillColor(TEAL_LIGHT)
c.drawCentredString(W/2, H-17*mm,
"Point-of-Care | WHO 2009 Classification | Symptoms · Diagnosis · Treatment")
TOP = H - hh - 2.5*mm - 3*mm
col_w = (IW - 4*mm) / 3
c1x = M
c2x = M + col_w + 2*mm
c3x = M + 2*(col_w+2*mm)
# ── COLUMN 1 ─────────────────────────────────────────────
y = TOP
# Suspect dengue
sec_hdr(c, c1x, y-9, col_w, 9, "▶ SUSPECT DENGUE WHEN…", bg=NAVY)
y -= 9
rr(c, c1x, y-44, col_w, 44, TEAL_PALE, stroke=TEAL, r=3)
y2 = y-7
for ln in ["Fever ≥38°C + endemic area travel (14 days)",
"Severe headache + retro-orbital pain",
"Myalgia/arthralgia – 'breakbone fever'",
"Rash + flushing + leukopenia",
"Positive tourniquet test"]:
c.setFillColor(TEAL); c.setFont("Helvetica-Bold",8); c.drawString(c1x+4,y2,"•")
c.setFillColor(BLACK); c.setFont("Helvetica",7); c.drawString(c1x+11,y2,ln)
y2 -= 8.5
y -= 44
# Incubation
y -= 2
rr(c, c1x, y-12, col_w, 12, GOLD, r=3)
c.setFillColor(NAVY); c.setFont("Helvetica-Bold",7)
c.drawCentredString(c1x+col_w/2, y-4.5, "Incubation: 3-14 days | Vector: Aedes aegypti (day-biting)")
c.setFont("Helvetica",6.5)
c.drawCentredString(c1x+col_w/2, y-10, "Serotypes: DENV-1, 2, 3, 4 | 2nd infection → severe disease risk")
y -= 12
# SYMPTOMS
y -= 3
sec_hdr(c, c1x, y-9, col_w, 9, "SYMPTOMS (Febrile Phase Days 1–3)", bg=AMBER)
y -= 9
sym_h = 78
rr(c, c1x, y-sym_h, col_w, sym_h, AMBER_LIGHT, stroke=AMBER, r=3)
y2 = y-8
sym = [("Fever","39-40°C, abrupt onset"),
("Headache","severe, frontal + retro-orbital"),
("Myalgia/Arthralgia","bone pain – 'breakbone fever'"),
("Rash","maculopapular, trunk → extremities"),
("Flushing","facial erythema, conjunctival injection"),
("Leukopenia","characteristic CBC finding"),
("Bleeding","petechiae, gum bleed, +ve tourniquet"),
("Nausea/Vomiting","early, non-specific")]
for k,v in sym:
c.setFont("Helvetica-Bold",6.8); c.setFillColor(AMBER)
c.drawString(c1x+4, y2, k)
kw = c.stringWidth(k,"Helvetica-Bold",6.8)
c.setFont("Helvetica",6.8); c.setFillColor(BLACK)
c.drawString(c1x+4+kw+2, y2, f"– {v}")
y2 -= 9.2
y -= sym_h
# Three phases
y -= 3
sec_hdr(c, c1x, y-9, col_w, 9, "THREE CLINICAL PHASES", bg=PURPLE)
y -= 9
ph_h = 54
rr(c, c1x, y-ph_h, col_w, ph_h, PURPLE_LITE, stroke=PURPLE, r=3)
y2 = y-7
phases = [
("FEBRILE","Days 1-3","Fever, myalgia, rash"),
("CRITICAL","Days 3-7","Plasma leakage, shock, bleed ⚠"),
("CONVALESC.","Days 7+","Fluid reabsorption, recovery"),
]
for ph,days,desc in phases:
c.setFont("Helvetica-Bold",7); c.setFillColor(PURPLE)
c.drawString(c1x+4,y2,ph)
pw = c.stringWidth(ph,"Helvetica-Bold",7)
c.setFont("Helvetica-Bold",6.5); c.setFillColor(GREY_DARK)
c.drawString(c1x+4+pw+3,y2,days)
y2 -= 7.5
c.setFont("Helvetica",6.8); c.setFillColor(BLACK)
c.drawString(c1x+10,y2,desc)
y2 -= 10
y -= ph_h
# ── COLUMN 2 ─────────────────────────────────────────────
y = TOP
# WHO Classification
sec_hdr(c, c2x, y-9, col_w, 9, "WHO 2009 CLASSIFICATION", bg=TEAL)
y -= 9
rr(c, c2x, y-82, col_w, 82, TEAL_PALE, stroke=TEAL, r=3)
y2 = y-8
groups = [
(TEAL, "GROUP A","No Warning Signs",
["Fever + ≥2: nausea, rash,","aches, leukopenia, +ve TT","→ OUTPATIENT"]),
(ORANGE,"GROUP B","With Warning Signs",
["Abd. pain, persistent vomit,","fluid accumulation, mucosal","bleed, lethargy, liver >2cm","→ HOSPITALISE"]),
(RED, "GROUP C","SEVERE Dengue",
["Shock (DSS), severe bleeding,","AST/ALT ≥1000, coma, organ","failure → ICU"]),
]
for grp_col, grp, sub, lines in groups:
rr(c, c2x+3, y2-8, col_w-6, 8, grp_col, r=2)
c.setFillColor(WHITE); c.setFont("Helvetica-Bold",7)
c.drawString(c2x+6, y2-5.5, f"{grp}: {sub}")
y2 -= 9
for ln in lines:
col = RED if "→" in ln else BLACK
fn = "Helvetica-Bold" if "→" in ln else "Helvetica"
c.setFillColor(col); c.setFont(fn,6.5)
c.drawString(c2x+8,y2,ln)
y2 -= 7.5
y2 -= 2
y -= 82
# Warning signs
y -= 3
sec_hdr(c, c2x, y-9, col_w, 9, "WARNING SIGNS (Admit if ANY)", bg=ORANGE)
y -= 9
ws_h = 72
rr(c, c2x, y-ws_h, col_w, ws_h, AMBER_LIGHT, stroke=ORANGE, r=3)
y2 = y-8
ws = ["! Abdominal pain or tenderness",
"! Persistent vomiting (≥3×/hr)",
"! Fluid accumulation (effusion/ascites)",
"! Mucosal bleeding",
"! Lethargy / restlessness",
"! Liver enlargement >2 cm",
"! ↑Haematocrit + rapid ↓platelets"]
for ln in ws:
c.setFillColor(RED); c.setFont("Helvetica-Bold",8); c.drawString(c2x+4,y2,ln[0])
c.setFillColor(BLACK); c.setFont("Helvetica",6.8); c.drawString(c2x+11,y2,ln[2:])
y2 -= 9.5
y -= ws_h
# Diagnosis
y -= 3
sec_hdr(c, c2x, y-9, col_w, 9, "DIAGNOSIS (Time-Based)", bg=BLUE)
y -= 9
diag_h = 60
rr(c, c2x, y-diag_h, col_w, diag_h, BLUE_PALE, stroke=BLUE, r=3)
y2 = y-8
diag = [
("Days 1-7","RT-PCR or NS1 antigen test"),
("Day 3-10","IgM antibody (EIA)"),
("Combined","NS1 + IgM → ≥90% detection"),
("CBC","Plt <100k + ↑HCT = plasma leakage"),
("Tourniquet","≥10 petechiae/in² = positive"),
("Note","IgM cross-reacts: Zika, WNV, JE, YFV"),
]
for k,v in diag:
c.setFont("Helvetica-Bold",6.8); c.setFillColor(BLUE); c.drawString(c2x+4,y2,k)
kw = c.stringWidth(k,"Helvetica-Bold",6.8)
c.setFont("Helvetica",6.8); c.setFillColor(BLACK); c.drawString(c2x+4+kw+2,y2,v)
y2 -= 9.2
y -= diag_h
# ── COLUMN 3 ─────────────────────────────────────────────
y = TOP
# Group A treatment
sec_hdr(c, c3x, y-9, col_w, 9, "GROUP A – OUTPATIENT Tx", bg=TEAL)
y -= 9
rr(c, c3x, y-62, col_w, 62, TEAL_PALE, stroke=TEAL, r=3)
y2 = y-8
for ln in ["Oral hydration (ORS, water, coconut water)",
"Paracetamol fever (max 4g/day adult)",
"⛔ NO NSAIDs / aspirin / ibuprofen",
"Daily CBC from Day 3",
"Until 1-2 days post-defervescence",
"Return IMMEDIATELY if warning signs",
"Mosquito nets to prevent spread"]:
is_warn = "⛔" in ln
c.setFillColor(RED if is_warn else TEAL); c.setFont("Helvetica-Bold",8)
c.drawString(c3x+4,y2,"▸" if not is_warn else "")
c.setFillColor(RED if is_warn else BLACK); c.setFont("Helvetica-Bold" if is_warn else "Helvetica",6.8)
c.drawString(c3x+11,y2,ln)
y2 -= 8.5
y -= 62
# Group B treatment
y -= 3
sec_hdr(c, c3x, y-9, col_w, 9, "GROUP B – HOSPITALISE", bg=ORANGE)
y -= 9
rr(c, c3x, y-62, col_w, 62, AMBER_LIGHT, stroke=ORANGE, r=3)
y2 = y-8
for ln in ["IV crystalloid (0.9% NaCl or Ringer's)",
"5-10 mL/kg bolus if compensated shock",
"Vitals every 1-4 hours",
"CBC every 4-6 hours",
"Urine output 0.5-1 mL/kg/hr",
"Plt transfusion: <20,000 + active bleed",
"Transition oral when improving"]:
c.setFillColor(ORANGE); c.setFont("Helvetica-Bold",8); c.drawString(c3x+4,y2,"▸")
c.setFillColor(BLACK); c.setFont("Helvetica",6.8); c.drawString(c3x+11,y2,ln)
y2 -= 8.5
y -= 62
# Group C treatment
y -= 3
sec_hdr(c, c3x, y-9, col_w, 9, "GROUP C – ICU / EMERGENCY", bg=RED)
y -= 9
rr(c, c3x, y-68, col_w, 68, RED_LITE, stroke=RED, r=3)
y2 = y-8
for ln in ["Aggressive bolus: 10-20 mL/kg IV",
"pRBCs if Hb <7 g/dL",
"Platelet transfusion <10,000",
"or clinically significant bleeding",
"FFP for coagulopathy",
"Vasopressors: fluid-refractory shock",
"Mechanical ventilation if resp. failure",
"⚠ Avoid excessive fluids (pulm. oedema)"]:
is_w = "⚠" in ln
c.setFillColor(RED); c.setFont("Helvetica-Bold",8)
c.drawString(c3x+4,y2,"⚠" if is_w else "▸")
c.setFillColor(RED if is_w else BLACK)
c.setFont("Helvetica-Bold" if is_w else "Helvetica",6.8)
c.drawString(c3x+11,y2,ln)
y2 -= 8.2
y -= 68
# Discharge criteria
y -= 3
sec_hdr(c, c3x, y-9, col_w, 9, "DISCHARGE CRITERIA (ALL must be met)", bg=PURPLE)
y -= 9
rr(c, c3x, y-54, col_w, 54, PURPLE_LITE, stroke=PURPLE, r=3)
y2 = y-8
for ln in ["Afebrile ≥24h (no antipyretics)",
"No warning signs",
"Improving appetite + oral intake",
"Platelets >50,000 and rising",
"Stable haematocrit",
"No respiratory distress"]:
c.setFillColor(PURPLE); c.setFont("Helvetica-Bold",8); c.drawString(c3x+4,y2,"✓")
c.setFillColor(BLACK); c.setFont("Helvetica",6.8); c.drawString(c3x+11,y2,ln)
y2 -= 8.5
y -= 54
# ── BOTTOM BAND: Monitoring strip ────────────────────────
y_sp = 32*mm
sec_hdr(c, M, y_sp, IW, 9, "MONITORING SCHEDULE & CRITICAL PHASE ALERT", bg=NAVY)
sp_y = y_sp - 9
entries = [
("Day 3 onwards","CBC daily (PLT+HCT)\nUntil 1-2d post-defervescence"),
("CRITICAL PHASE\n(Days 3-7)","⚠ HIGHEST RISK: plasma leakage,\nshock, haemorrhage – hourly vitals"),
("Shock (DSS)","Fluid bolus + close monitoring;\npressor if fluid-refractory"),
("Haematocrit","↑HCT = haemoconcentration;\nmarker of plasma leakage"),
("Platelet nadirs","Usually Day 4-6;\nrebound in convalescence"),
]
ew = IW / len(entries)
for i,(title,note) in enumerate(entries):
sx = M + i*ew
is_warn = "⚠" in note
bg = RED_LITE if is_warn else (TEAL_PALE if i%2==0 else WHITE)
rr(c, sx, sp_y-22, ew, 22, bg, stroke=GREY, lw=0.3, r=0)
c.setFillColor(RED if is_warn else TEAL); c.setFont("Helvetica-Bold",6.5)
c.drawCentredString(sx+ew/2, sp_y-8, title)
words = note.split('\n')
yy = sp_y-15
for ln in words:
c.setFillColor(RED if is_warn else BLACK); c.setFont("Helvetica",6)
c.drawCentredString(sx+ew/2, yy, ln)
yy -= 7
# ── FOOTER ─────────────────────────────────────────────
rr(c, 0, 0, W, 10*mm, NAVY, r=0)
c.setFillColor(GOLD); c.setFont("Helvetica-Bold",7)
c.drawCentredString(W/2, 6*mm,
"⚠ NO antiviral therapy exists – management is SUPPORTIVE. "
"NSAIDs / aspirin CONTRAINDICATED. Critical phase (Days 3-7) is highest risk.")
c.setFillColor(HexColor("#99AABB")); c.setFont("Helvetica",6)
c.drawCentredString(W/2, 2.5*mm,
"Sources: WHO Dengue Guidelines 2009 | AAP Red Book 2021 | "
"Harrison's Principles 22E | PAHO Clinical Algorithms 2024 | CDC 2024")
def main():
import os; os.makedirs("/home/daytona/workspace/dengue-pdf", exist_ok=True)
c = canvas.Canvas(OUTPUT, pagesize=A4)
c.setTitle("Dengue Fever Point-of-Care Quick Reference Card")
c.setAuthor("Orris Medical Reference")
c.setSubject("Dengue POC Quick Reference – WHO 2009 Classification")
draw(c)
c.save()
print(f"Saved: {OUTPUT}")
if __name__ == "__main__":
main()
cd /home/daytona/workspace/dengue-pdf && python generate_dengue_reference.py 2>&…
ls -lh /home/daytona/workspace/dengue-pdf/
Dengue POC QuickRef
PDF Document · PDF
Dengue Clinical Reference
PDF Document · PDF
| Column 1 - Recognition | Column 2 - Classify & Diagnose | Column 3 - Treat |
|---|---|---|
| "Suspect dengue when..." checklist | WHO 2009 Groups A / B / C | Group A outpatient protocol |
| Symptom list with descriptors | Warning signs (admit if ANY) | Group B IV fluid protocol |
| Three clinical phases (Febrile/Critical/Convalescent) | Time-based diagnosis guide | Group C ICU/emergency protocol |
| Incubation + vector note | NS1/RT-PCR/IgM windows | Discharge criteria (all 6 must be met) |