Write a research on Covid-19 pandemic or Ebola outbreak and describe in detail the investigation process: stages of case identification, data analysis and control measures. Including references and make it a humanised research
"COVID-19"[MeSH Terms] AND "contact tracing"[MeSH Terms] AND "epidemiologic investigation"
"Ebola virus disease"[MeSH Terms] AND "outbreak investigation"
COVID-19 vs Ebola outbreak investigation epidemiology case identification control measures WHO CDC guidelines
"Ebola virus"[MeSH Terms] AND "epidemiology" AND "contact tracing"
"COVID-19"[MeSH Terms] AND "epidemiologic surveillance" AND "control measures"
https://pmc.ncbi.nlm.nih.gov/articles/PMC8176515
"COVID-19" AND "outbreak investigation" AND "case identification"
"Ebola" AND "contact tracing" AND "case fatality"
PMID: 34889315
PMID: 36649296
PMID: 35721786
"SARS-CoV-2" AND "epidemiological investigation" AND "surveillance"
WHO COVID-19 epidemiological investigation steps case definition data analysis 2020 2021
PMID: 12460399
"COVID-19" AND "case fatality rate" AND "epidemiology" AND "2020"
PMID: 25474983
Generate a PowerPoint presentation summarizing the outbreak investigation frameworks
ls -la /tmp/workspace/ 2>/dev/null || echo "workspace empty or missing"
mkdir -p /tmp/workspace/outbreak-investigation-pptx
~/outbreak-investigation-pptx/build_pptx.py
"""
Outbreak Investigation Frameworks: COVID-19 vs Ebola
Professional PowerPoint Presentation Builder
"""
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from io import BytesIO
# ── Colour palette ───────────────────────────────────────────────────────────
C_DARK_NAVY = RGBColor(0x0D, 0x2B, 0x4E) # deep navy – headers / bg
C_BLUE = RGBColor(0x1A, 0x6B, 0xA8) # mid blue – accents
C_TEAL = RGBColor(0x1A, 0x9E, 0x8F) # teal – COVID highlight
C_RED = RGBColor(0xC0, 0x39, 0x2B) # red – Ebola highlight
C_AMBER = RGBColor(0xE6, 0x7E, 0x22) # amber – warnings / notes
C_WHITE = RGBColor(0xFF, 0xFF, 0xFF)
C_LIGHT_GREY = RGBColor(0xF0, 0xF4, 0xF8)
C_MID_GREY = RGBColor(0x7F, 0x8C, 0x8D)
C_DARK_GREY = RGBColor(0x2C, 0x3E, 0x50)
def make_prs():
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
return prs
def blank(prs):
return prs.slides.add_slide(prs.slide_layouts[6])
def rect(slide, x, y, w, h, fill_rgb, line_rgb=None, line_width_pt=0):
from pptx.enum.shapes import MSO_SHAPE_TYPE
from pptx.enum.shapes import MSO_SHAPE
shp = slide.shapes.add_shape(
MSO_SHAPE.RECTANGLE, Inches(x), Inches(y), Inches(w), Inches(h)
)
shp.fill.solid()
shp.fill.fore_color.rgb = fill_rgb
if line_rgb:
shp.line.color.rgb = line_rgb
shp.line.width = Pt(line_width_pt)
else:
shp.line.fill.background()
shp.shadow.inherit = False
return shp
def rounded_rect(slide, x, y, w, h, fill_rgb, line_rgb=None, line_width_pt=1):
from pptx.enum.shapes import MSO_SHAPE
shp = slide.shapes.add_shape(
MSO_SHAPE.ROUNDED_RECTANGLE, Inches(x), Inches(y), Inches(w), Inches(h)
)
shp.fill.solid()
shp.fill.fore_color.rgb = fill_rgb
if line_rgb:
shp.line.color.rgb = line_rgb
shp.line.width = Pt(line_width_pt)
else:
shp.line.fill.background()
shp.shadow.inherit = False
return shp
def add_text(slide, x, y, w, h, text, font_size, color=C_WHITE, bold=False,
align=PP_ALIGN.LEFT, v_anchor=MSO_ANCHOR.TOP, italic=False,
wrap=True, font_name="Calibri"):
tb = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = tb.text_frame
tf.word_wrap = wrap
tf.vertical_anchor = v_anchor
tf.margin_left = Pt(4)
tf.margin_right = Pt(4)
tf.margin_top = Pt(2)
tf.margin_bottom = Pt(2)
p = tf.paragraphs[0]
p.alignment = align
r = p.add_run()
r.text = text
r.font.name = font_name
r.font.size = Pt(font_size)
r.font.bold = bold
r.font.italic = italic
r.font.color.rgb = color
return tb
def add_bullet_box(slide, x, y, w, h, items, font_size=13, color=C_DARK_GREY,
font_name="Calibri", bold_first=False):
"""Add a text box with bullet-style lines (use en-dash prefix)."""
tb = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tf = tb.text_frame
tf.word_wrap = True
tf.margin_left = Pt(4)
tf.margin_right = Pt(4)
tf.margin_top = Pt(2)
tf.margin_bottom = Pt(2)
for i, item in enumerate(items):
if i == 0:
p = tf.paragraphs[0]
else:
p = tf.add_paragraph()
p.alignment = PP_ALIGN.LEFT
r = p.add_run()
r.text = item
r.font.name = font_name
r.font.size = Pt(font_size)
r.font.color.rgb = color
r.font.bold = (bold_first and i == 0)
return tb
def h_line(slide, x, y, w, color=C_BLUE, width_pt=1.5):
from pptx.enum.shapes import MSO_CONNECTOR
ln = slide.shapes.add_connector(
MSO_CONNECTOR.STRAIGHT,
Inches(x), Inches(y), Inches(x + w), Inches(y)
)
ln.line.color.rgb = color
ln.line.width = Pt(width_pt)
return ln
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 1 – Title Slide
# ═══════════════════════════════════════════════════════════════════════════════
def slide_title(prs):
sl = blank(prs)
# full background
rect(sl, 0, 0, 13.333, 7.5, C_DARK_NAVY)
# left accent bar
rect(sl, 0, 0, 0.45, 7.5, C_BLUE)
# teal stripe bottom
rect(sl, 0, 6.6, 13.333, 0.9, C_TEAL)
# main title
add_text(sl, 0.7, 1.2, 11.5, 1.4,
"Outbreak Investigation Frameworks",
font_size=40, color=C_WHITE, bold=True,
align=PP_ALIGN.LEFT, v_anchor=MSO_ANCHOR.MIDDLE)
# subtitle line 1
add_text(sl, 0.7, 2.75, 11.5, 0.7,
"A Comparative Analysis: COVID-19 Pandemic vs Ebola Outbreaks",
font_size=22, color=RGBColor(0xA8, 0xD8, 0xEA),
bold=False, align=PP_ALIGN.LEFT)
# divider
h_line(sl, 0.7, 3.55, 9.0, C_AMBER, 2)
# descriptors
add_text(sl, 0.7, 3.75, 11.5, 0.55,
"Case Identification | Data Analysis | Control Measures",
font_size=16, color=C_MID_GREY, align=PP_ALIGN.LEFT)
# footer
add_text(sl, 0.7, 6.65, 11.0, 0.5,
"Professional Public Health Practitioner Series | July 2026",
font_size=11, color=C_WHITE, italic=True, align=PP_ALIGN.LEFT)
# COVID badge
rounded_rect(sl, 9.8, 1.8, 2.9, 0.65, C_TEAL)
add_text(sl, 9.8, 1.83, 2.9, 0.55, "COVID-19 (SARS-CoV-2)",
font_size=13, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
# Ebola badge
rounded_rect(sl, 9.8, 2.65, 2.9, 0.65, C_RED)
add_text(sl, 9.8, 2.68, 2.9, 0.55, "Ebola Virus Disease",
font_size=13, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 2 – Agenda
# ═══════════════════════════════════════════════════════════════════════════════
def slide_agenda(prs):
sl = blank(prs)
rect(sl, 0, 0, 13.333, 7.5, C_LIGHT_GREY)
rect(sl, 0, 0, 13.333, 1.05, C_DARK_NAVY)
rect(sl, 0, 0, 0.45, 7.5, C_DARK_NAVY)
add_text(sl, 0.65, 0.18, 12.0, 0.7, "Agenda",
font_size=28, color=C_WHITE, bold=True)
topics = [
("01", "The Two Pathogens: Understanding the Enemy", C_BLUE),
("02", "Stage 1 - Diagnosis Verification & Outbreak Confirmation", C_TEAL),
("03", "Stage 2 - Case Definition", C_DARK_NAVY),
("04", "Stage 3 - Case Identification & Contact Tracing", C_BLUE),
("05", "Stage 4 - Population at Risk & The Line List", C_TEAL),
("06", "Stage 5 - Data Analysis: Time, Place, Person", C_DARK_NAVY),
("07", "Stage 6-8 - Hypothesis Formulation, Testing & Ecology", C_BLUE),
("08", "Stage 9 - Control Measures", C_RED),
("09", "Comparative Lessons & Conclusion", C_AMBER),
]
cols = 3
row_h = 0.82
col_w = 4.2
start_x = 0.6
start_y = 1.25
for i, (num, label, clr) in enumerate(topics):
col = i % cols
row = i // cols
x = start_x + col * (col_w + 0.2)
y = start_y + row * row_h
rounded_rect(sl, x, y, col_w, 0.68, clr)
add_text(sl, x + 0.1, y + 0.05, 0.55, 0.58, num,
font_size=18, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
add_text(sl, x + 0.7, y + 0.04, col_w - 0.85, 0.62, label,
font_size=11.5, color=C_WHITE,
align=PP_ALIGN.LEFT, v_anchor=MSO_ANCHOR.MIDDLE)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 3 – The Two Pathogens
# ═══════════════════════════════════════════════════════════════════════════════
def slide_pathogens(prs):
sl = blank(prs)
rect(sl, 0, 0, 13.333, 7.5, C_LIGHT_GREY)
rect(sl, 0, 0, 13.333, 1.1, C_DARK_NAVY)
rect(sl, 0, 0, 0.45, 7.5, C_DARK_NAVY)
add_text(sl, 0.65, 0.2, 12.0, 0.72,
"The Two Pathogens: Understanding the Enemy",
font_size=26, color=C_WHITE, bold=True)
# COVID box
rect(sl, 0.6, 1.25, 5.9, 5.9, C_WHITE,
line_rgb=C_TEAL, line_width_pt=2)
rect(sl, 0.6, 1.25, 5.9, 0.52, C_TEAL)
add_text(sl, 0.65, 1.28, 5.8, 0.44,
"COVID-19 (SARS-CoV-2)",
font_size=17, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
covid_facts = [
"- Family: Betacoronavirus",
"- Transmission: Respiratory droplets & aerosols",
"- Incubation: 2-14 days (mean 5-6 days)",
"- Pre/asymptomatic spread: YES (key challenge)",
"- R0 (original strain): 2-3; Omicron: ~8-15",
"- Global CFR: ~1-2%",
"- Scale: Pandemic - 216 countries",
"- Vaccine available: YES (mRNA, viral vector, protein)",
"- Special challenge: Silent transmission; scale",
]
add_bullet_box(sl, 0.7, 1.85, 5.7, 5.1, covid_facts,
font_size=13, color=C_DARK_GREY)
# Ebola box
rect(sl, 6.9, 1.25, 5.9, 5.9, C_WHITE,
line_rgb=C_RED, line_width_pt=2)
rect(sl, 6.9, 1.25, 5.9, 0.52, C_RED)
add_text(sl, 6.95, 1.28, 5.8, 0.44,
"Ebola Virus Disease (EVD)",
font_size=17, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
ebola_facts = [
"- Family: Filoviridae (Zaire ebolavirus, Sudan ebolavirus)",
"- Transmission: Direct contact with blood/body fluids",
"- Incubation: 2-21 days",
"- Pre/asymptomatic spread: NO (only symptomatic)",
"- R0: ~1.5-2.5 (highly containable if caught early)",
"- CFR: 40-70% (varies by strain & setting)",
"- Scale: Regional outbreaks - sub-Saharan Africa",
"- Vaccine available: Ervebo (Zaire only); none for Sudan",
"- Special challenge: High lethality; corpses infectious",
]
add_bullet_box(sl, 7.0, 1.85, 5.7, 5.1, ebola_facts,
font_size=13, color=C_DARK_GREY)
# vs badge
rounded_rect(sl, 6.0, 3.7, 0.85, 0.7, C_AMBER)
add_text(sl, 6.0, 3.72, 0.85, 0.66, "VS",
font_size=18, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 4 – Stages Overview (Framework Flow)
# ═══════════════════════════════════════════════════════════════════════════════
def slide_framework_overview(prs):
sl = blank(prs)
rect(sl, 0, 0, 13.333, 7.5, C_DARK_NAVY)
rect(sl, 0, 0, 0.45, 7.5, C_BLUE)
add_text(sl, 0.65, 0.2, 12.0, 0.72,
"The 9-Stage Epidemic Investigation Framework",
font_size=26, color=C_WHITE, bold=True)
add_text(sl, 0.65, 0.88, 10.0, 0.45,
"Based on Park's Textbook of Preventive and Social Medicine & WHO Outbreak Toolkit",
font_size=12, color=C_MID_GREY, italic=True)
stages = [
("1", "Verify\nDiagnosis", C_TEAL),
("2", "Confirm\nEpidemic", C_BLUE),
("3", "Define\nCase", C_TEAL),
("4", "Find\nCases", C_BLUE),
("5", "Define\nPop. at Risk", C_TEAL),
("6", "Analyse\nData", C_BLUE),
("7", "Hypotheses\nFormulation", C_TEAL),
("8", "Ecology\nFactors", C_BLUE),
("9", "Control\nMeasures", C_RED),
]
box_w = 1.2
box_h = 1.35
gap = 0.12
total = len(stages) * box_w + (len(stages) - 1) * gap
start_x = (13.333 - total) / 2
y = 1.8
for i, (num, label, clr) in enumerate(stages):
x = start_x + i * (box_w + gap)
rounded_rect(sl, x, y, box_w, box_h, clr)
add_text(sl, x, y + 0.05, box_w, 0.42, num,
font_size=22, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
add_text(sl, x, y + 0.5, box_w, 0.82, label,
font_size=10, color=C_WHITE, bold=False,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
# Arrow connector (not last)
if i < len(stages) - 1:
ax = x + box_w + 0.01
ay = y + box_h / 2
from pptx.enum.shapes import MSO_CONNECTOR
ln = sl.shapes.add_connector(
MSO_CONNECTOR.STRAIGHT,
Inches(ax), Inches(ay), Inches(ax + gap - 0.01), Inches(ay)
)
ln.line.color.rgb = C_MID_GREY
ln.line.width = Pt(1.5)
# Two-row key comparison table below
rect(sl, 0.6, 3.55, 12.1, 0.08, C_BLUE) # separator
headers = ["Stage", "COVID-19 Application", "EVD Application"]
col_ws = [1.5, 5.1, 5.1]
col_xs = [0.65, 2.2, 7.35]
# header row
for hdr, cx, cw in zip(headers, col_xs, col_ws):
rounded_rect(sl, cx, 3.72, cw, 0.45, C_BLUE)
add_text(sl, cx + 0.05, 3.74, cw - 0.1, 0.41, hdr,
font_size=13, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
rows = [
("Case ID", "RT-PCR / Ag-RDT, symptom surveillance, serosurveys",
"Clinical scoring (alert/suspected/probable/confirmed)"),
("Contact", "Digital apps + manual tracing; 14-day follow-up",
"Daily home visits; 21-day follow-up"),
("Data Anal.","Epi curves, GIS, wastewater surveillance, genomics",
"Spot maps, attack rates, cluster analysis"),
("Control", "NPIs, mass vaccination, digital surveillance",
"Isolation, safe burials, ring vaccination (Zaire only)"),
]
row_h2 = 0.55
for ri, (stage, cv, ev) in enumerate(rows):
y2 = 4.25 + ri * row_h2
bg = C_WHITE if ri % 2 == 0 else C_LIGHT_GREY
rect(sl, 0.65, y2, 12.05, row_h2 - 0.04, bg,
line_rgb=RGBColor(0xCC, 0xCC, 0xCC), line_width_pt=0.5)
add_text(sl, 0.7, y2 + 0.03, 1.4, row_h2 - 0.08, stage,
font_size=11, color=C_BLUE, bold=True,
v_anchor=MSO_ANCHOR.MIDDLE)
add_text(sl, 2.2, y2 + 0.03, 5.0, row_h2 - 0.08, cv,
font_size=11, color=C_DARK_GREY,
v_anchor=MSO_ANCHOR.MIDDLE)
add_text(sl, 7.35, y2 + 0.03, 5.0, row_h2 - 0.08, ev,
font_size=11, color=C_DARK_GREY,
v_anchor=MSO_ANCHOR.MIDDLE)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 5 – Case Definition
# ═══════════════════════════════════════════════════════════════════════════════
def slide_case_definition(prs):
sl = blank(prs)
rect(sl, 0, 0, 13.333, 7.5, C_LIGHT_GREY)
rect(sl, 0, 0, 13.333, 1.1, C_DARK_NAVY)
rect(sl, 0, 0, 0.45, 7.5, C_DARK_NAVY)
add_text(sl, 0.65, 0.2, 12.0, 0.72,
"Stage 2-3 - Case Definition: The Diagnostic Backbone",
font_size=26, color=C_WHITE, bold=True)
# COVID case def
rect(sl, 0.6, 1.2, 5.9, 5.95, C_WHITE, C_TEAL, 2)
rect(sl, 0.6, 1.2, 5.9, 0.5, C_TEAL)
add_text(sl, 0.65, 1.23, 5.8, 0.44, "COVID-19 Case Definition (WHO 2022)",
font_size=15, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
covid_def = [
"CONFIRMED (Option A):",
" Positive NAAT (RT-PCR) regardless of symptoms",
"",
"CONFIRMED (Option B):",
" Clinical/epidemiological criteria (suspect case)",
" + Positive professional Ag-RDT",
"",
"CONTACT defined as:",
" < 1 metre, > 15 minutes exposure",
" OR direct physical contact",
" OR unprotected exposure to secretions",
" Within 48h before symptom onset",
"",
"* 9 case definition updates issued 2020-2022",
"* Incorporated vaccine status from 2021",
]
add_bullet_box(sl, 0.7, 1.78, 5.7, 5.25, covid_def,
font_size=12, color=C_DARK_GREY)
# EVD case def
rect(sl, 6.9, 1.2, 5.9, 5.95, C_WHITE, C_RED, 2)
rect(sl, 6.9, 1.2, 5.9, 0.5, C_RED)
add_text(sl, 6.95, 1.23, 5.8, 0.44, "Ebola Case Definition (Uganda 2000 / WHO)",
font_size=15, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
evd_def = [
"ALERT CASE:",
" Any unexplained fever in outbreak area",
"",
"SUSPECTED CASE:",
" Fever + >= 3 symptoms (headache, vomiting,",
" diarrhoea, myalgia, bleeding) + epi link",
"",
"PROBABLE CASE:",
" Suspected case + epi link to confirmed case",
" (no lab confirmation available)",
"",
"CONFIRMED CASE:",
" Any above + positive RT-PCR for EVD",
"",
"* Tiered structure enables action before lab results",
"* 21-day contact monitoring window",
]
add_bullet_box(sl, 7.0, 1.78, 5.7, 5.25, evd_def,
font_size=12, color=C_DARK_GREY)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 6 – Case ID and Contact Tracing
# ═══════════════════════════════════════════════════════════════════════════════
def slide_case_id(prs):
sl = blank(prs)
rect(sl, 0, 0, 13.333, 7.5, C_LIGHT_GREY)
rect(sl, 0, 0, 13.333, 1.1, C_DARK_NAVY)
rect(sl, 0, 0, 0.45, 7.5, C_DARK_NAVY)
add_text(sl, 0.65, 0.2, 12.0, 0.72,
"Stage 4 - Case Identification & Contact Tracing",
font_size=26, color=C_WHITE, bold=True)
# Left panel
rect(sl, 0.6, 1.25, 5.9, 5.9, C_WHITE, C_BLUE, 1.5)
rect(sl, 0.6, 1.25, 5.9, 0.42, C_BLUE)
add_text(sl, 0.65, 1.28, 5.8, 0.36, "COVID-19",
font_size=15, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
c_items = [
"ACTIVE CASE FINDING:",
" - Mass PCR testing (centralised -> point-of-care)",
" - Antigen RDTs for community screening",
" - Symptom surveillance hotlines",
" - Wastewater epidemiology (5-7 day early warning)",
" - Seroprevalence surveys for true burden",
"",
"CONTACT TRACING:",
" - Manual + digital (Bluetooth apps)",
" - 14-day quarantine for contacts",
" - Asymptomatic contacts tested on Day 7 & 12",
" - Digital tracing limited by privacy & uptake",
" - Systematic review: app adoption 0.01-58.3%",
" (Mazza et al., 2021)",
"",
"EPIDEMIOLOGICAL CASE SHEET CAPTURES:",
" Demographics, exposure history, travel,",
" contacts at home/work/school, clinical timeline",
]
add_bullet_box(sl, 0.7, 1.75, 5.7, 5.3, c_items,
font_size=11.5, color=C_DARK_GREY)
# Right panel
rect(sl, 6.9, 1.25, 5.9, 5.9, C_WHITE, C_RED, 1.5)
rect(sl, 6.9, 1.25, 5.9, 0.42, C_RED)
add_text(sl, 6.95, 1.28, 5.8, 0.36, "Ebola Virus Disease",
font_size=15, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
e_items = [
"ACTIVE CASE FINDING:",
" - Community health worker door-to-door visits",
" - Hospital-based surveillance",
" - Traditional/community leader involvement",
" - Post-mortem surveillance (corpses highly infectious)",
" - Funeral reporting to identify exposure events",
"",
"CONTACT TRACING:",
" - Daily home visits for ALL contacts - 21 days",
" - ~5,000 contacts traced in Uganda 2000 outbreak",
" - Secondary attack rate: 2.5% (Okware et al., 2002)",
" - EVD model: rapid tracing is highest-impact action",
" (Bouba et al., 2023)",
"",
"KEY INSIGHT:",
" EVD contacts are asymptomatic until they become",
" infectious - window for intervention is narrow.",
" Every day of tracing delay widens the chain.",
]
add_bullet_box(sl, 7.0, 1.75, 5.7, 5.3, e_items,
font_size=11.5, color=C_DARK_GREY)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 7 – Data Analysis: Time-Place-Person
# ═══════════════════════════════════════════════════════════════════════════════
def slide_data_analysis(prs):
sl = blank(prs)
rect(sl, 0, 0, 13.333, 7.5, C_DARK_NAVY)
rect(sl, 0, 0, 0.45, 7.5, C_TEAL)
add_text(sl, 0.65, 0.15, 12.0, 0.72,
"Stage 5-6 - Data Analysis: Time, Place & Person",
font_size=26, color=C_WHITE, bold=True)
add_text(sl, 0.65, 0.82, 10.0, 0.4,
"Park's Textbook: 'The purpose of data analysis is to identify common event or experience'",
font_size=12, color=C_MID_GREY, italic=True)
pillars = [
("TIME", C_TEAL,
[
"Epidemic Curve (epi curve):",
"- Histogram of case onset dates",
"- Point-source: sharp single peak",
"- Propagated: successive waves",
"- Common-source: plateau pattern",
"",
"COVID-19: multi-wave pattern",
"Tracked variant surges & NPI impact",
"Genomic sequencing adds temporal",
"resolution to transmission chains",
"",
"EVD: single propagated wave",
"Outbreak ended 42 days post-last case",
"(2 x max incubation period rule)",
]),
("PLACE", C_BLUE,
[
"Spot Map (Geographic Distribution):",
"- Maps cases to locations",
"- Reveals clustering & common sources",
"- John Snow: 1854 Broad St cholera",
"",
"COVID-19: GIS mapping of spread",
"Urban density, care homes, workplaces",
"Wastewater catchment heatmaps",
"Air travel network analysis",
"",
"EVD: forest village -> city routes",
"Road/market transmission corridors",
"ETU placement guided by GIS data",
"Border monitoring stations",
]),
("PERSON", C_RED,
[
"Demographic Stratification:",
"- Age, sex, occupation, exposure",
"- Attack rates & CFR by subgroup",
"",
"COVID-19 risk factors:",
"Age > 65: CFR exponentially higher",
"Male sex: higher severity",
"Comorbidities: diabetes, obesity,",
" hypertension, immunosuppression",
"Occupation: HCW, transport, food",
"",
"EVD risk factors:",
"Women: highest AR (caregiving role)",
"Healthcare workers: major exposure",
"Funeral attendees: key amplification",
]),
]
col_w = 3.9
for i, (title, clr, items) in enumerate(pillars):
x = 0.55 + i * (col_w + 0.25)
rounded_rect(sl, x, 1.35, col_w, 5.75, RGBColor(0x14, 0x2D, 0x4A))
rect(sl, x, 1.35, col_w, 0.55, clr)
add_text(sl, x, 1.38, col_w, 0.49, title,
font_size=18, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
add_bullet_box(sl, x + 0.1, 2.0, col_w - 0.15, 5.0, items,
font_size=11, color=RGBColor(0xCC, 0xDD, 0xEE))
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 8 – Control Measures
# ═══════════════════════════════════════════════════════════════════════════════
def slide_control(prs):
sl = blank(prs)
rect(sl, 0, 0, 13.333, 7.5, C_LIGHT_GREY)
rect(sl, 0, 0, 13.333, 1.1, C_DARK_NAVY)
rect(sl, 0, 0, 0.45, 7.5, C_DARK_NAVY)
add_text(sl, 0.65, 0.2, 12.0, 0.72,
"Stage 9 - Control Measures",
font_size=26, color=C_WHITE, bold=True)
# 3-tier framework header
tiers = [("Source Control", C_RED), ("Host Protection", C_BLUE), ("Systemic / Environmental", C_TEAL)]
for i, (t, clr) in enumerate(tiers):
tx = 0.6 + i * 4.2
rounded_rect(sl, tx, 1.2, 3.9, 0.5, clr)
add_text(sl, tx, 1.22, 3.9, 0.46, t,
font_size=14, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
# COVID boxes
add_text(sl, 0.6, 1.82, 12.6, 0.35, "COVID-19",
font_size=12, color=C_TEAL, bold=True)
covid_ctrl = [
[
"- Case isolation",
"- Physical distancing",
"- Mask mandates",
"- Ventilation improvement",
"- Travel restrictions",
"- Lockdowns (severe waves)",
],
[
"- Mass vaccination",
" (mRNA/viral vector/protein)",
"- Hand hygiene campaigns",
"- PPE for HCWs",
"- Prophylactic protocols",
"- Antivirals (remdesivir, etc.)",
],
[
"- National testing strategies",
"- Digital contact tracing apps",
"- Wastewater surveillance",
"- WHO surveillance dashboard",
"- IHR reporting obligations",
"- International coordination",
],
]
for i, items in enumerate(covid_ctrl):
tx = 0.6 + i * 4.2
rect(sl, tx, 2.18, 3.9, 2.2, C_WHITE, C_TEAL, 1)
add_bullet_box(sl, tx + 0.1, 2.22, 3.7, 2.1, items,
font_size=11.5, color=C_DARK_GREY)
# EVD boxes
add_text(sl, 0.6, 4.5, 12.6, 0.35, "Ebola Virus Disease",
font_size=12, color=C_RED, bold=True)
ebola_ctrl = [
[
"- Ebola Treatment Units (ETUs)",
"- Full PPE barrier nursing",
"- Safe & dignified burials",
"- Funeral practice guidelines",
"- Healthcare worker training",
"- Community isolation support",
],
[
"- Ervebo vaccine (Zaire EVD)",
" Ring vaccination protocol",
"- No approved therapy (Sudan)",
"- Supportive care in ETUs",
"- Experimental mAbs (Zaire)",
"- Community behaviour change",
],
[
"- National Task Force (NTF)",
"- District Task Force (DTF)",
"- WHO Global Alert & Response",
"- Cross-border coordination",
"- Lab capacity building",
"- Mathematical modelling tools",
],
]
for i, items in enumerate(ebola_ctrl):
tx = 0.6 + i * 4.2
rect(sl, tx, 4.85, 3.9, 2.4, C_WHITE, C_RED, 1)
add_bullet_box(sl, tx + 0.1, 4.9, 3.7, 2.3, items,
font_size=11.5, color=C_DARK_GREY)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 9 – Comparative Lessons
# ═══════════════════════════════════════════════════════════════════════════════
def slide_lessons(prs):
sl = blank(prs)
rect(sl, 0, 0, 13.333, 7.5, C_DARK_NAVY)
rect(sl, 0, 0, 0.45, 7.5, C_AMBER)
add_text(sl, 0.65, 0.15, 12.0, 0.72,
"Key Comparative Lessons",
font_size=28, color=C_WHITE, bold=True)
lessons = [
(C_TEAL, "1. SOPs Transfer Between Diseases",
"Ebola 2014-2016 SOPs were directly repurposed as COVID-19 response templates. "
"Contact tracing method, case forms, and coordination structures crossed with "
"minor modifications (14 vs 21-day follow-up). Investment in response architecture "
"pays dividends for the next outbreak - whatever it is."),
(C_BLUE, "2. Lab Infrastructure Built for One Crisis Serves the Next",
"PCR equipment procured for COVID-19 in Guinea was immediately available for "
"Ebola RT-PCR when the 2021 outbreak began. Vertical disease-specific investment "
"is wasteful; horizontal health system strengthening is the sustainable approach."),
(C_AMBER, "3. Community Trust is Irreplaceable",
"In both crises, communities that trusted health authorities cooperated with reporting, "
"tracing, isolation, and protective measures. Mistreatment, misinformation, and perceived "
"abandonment made communities transmission hotspots - in rural Guinea and in marginalised "
"urban COVID-19 settings alike. Trust is a public health intervention."),
(C_TEAL, "4. Mathematical Modelling is Operational - Not Just Academic",
"Real-time R0 estimation, scenario projections, and intervention impact modelling shaped "
"policy in both crises. Bouba et al. (2023) demonstrated that case isolation alone is "
"insufficient for EVD; only the combination with safe burials AND tracing contains it. "
"Models must be integrated into Emergency Operations Centres from Day 1."),
(C_RED, "5. Molecular Epidemiology Adds a New Investigative Layer",
"Whole-genome sequencing of SARS-CoV-2 enabled tracking of variant emergence, "
"confirmation of transmission chains, and identification of superspreader events. "
"Similar tools exist for Ebola. Integration with classic field epidemiology - not "
"as replacement but as complement - is the frontier of outbreak investigation."),
]
row_h = 1.12
for i, (clr, title, body) in enumerate(lessons):
y = 1.05 + i * row_h
rounded_rect(sl, 0.55, y, 0.75, row_h - 0.08, clr)
add_text(sl, 0.55, y + 0.05, 0.75, row_h - 0.18, str(i + 1),
font_size=24, color=C_WHITE, bold=True,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
rect(sl, 1.38, y, 11.5, row_h - 0.08, RGBColor(0x12, 0x2B, 0x45),
line_rgb=clr, line_width_pt=1)
add_text(sl, 1.5, y + 0.03, 11.2, 0.36, title,
font_size=12.5, color=clr, bold=True, v_anchor=MSO_ANCHOR.TOP)
add_text(sl, 1.5, y + 0.36, 11.2, row_h - 0.46, body,
font_size=10.5, color=RGBColor(0xCC, 0xDD, 0xEE),
v_anchor=MSO_ANCHOR.TOP)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 10 – Conclusion & References
# ═══════════════════════════════════════════════════════════════════════════════
def slide_conclusion(prs):
sl = blank(prs)
rect(sl, 0, 0, 13.333, 7.5, C_LIGHT_GREY)
rect(sl, 0, 0, 13.333, 1.1, C_DARK_NAVY)
rect(sl, 0, 0, 0.45, 7.5, C_DARK_NAVY)
add_text(sl, 0.65, 0.2, 12.0, 0.72,
"Conclusion & Key References",
font_size=26, color=C_WHITE, bold=True)
# Conclusion box
rect(sl, 0.6, 1.2, 12.2, 1.95, C_WHITE, C_DARK_NAVY, 1.5)
rect(sl, 0.6, 1.2, 12.2, 0.42, C_DARK_NAVY)
add_text(sl, 0.65, 1.22, 12.1, 0.38, "Core Conclusion",
font_size=14, color=C_WHITE, bold=True, v_anchor=MSO_ANCHOR.MIDDLE)
add_text(sl, 0.75, 1.68, 12.0, 1.4,
"Epidemic investigation - whether for a novel respiratory pandemic or a haemorrhagic fever outbreak - "
"follows the same disciplined arc: verify, define, find, analyse, hypothesise, test, evaluate, control. "
"The differences between COVID-19 and Ebola lie in the biology (asymptomatic spread vs blood-borne "
"transmission), the scale (global vs regional), and the tools (digital mass surveillance vs intensive "
"community field work). The failures in both crises were not scientific - they were failures of "
"preparedness investment, trust-building, and political will.",
font_size=12, color=C_DARK_GREY, v_anchor=MSO_ANCHOR.TOP)
# References
rect(sl, 0.6, 3.3, 12.2, 3.85, C_WHITE, C_BLUE, 1)
rect(sl, 0.6, 3.3, 12.2, 0.4, C_BLUE)
add_text(sl, 0.65, 3.32, 12.1, 0.36, "Key References",
font_size=13, color=C_WHITE, bold=True, v_anchor=MSO_ANCHOR.MIDDLE)
refs = [
"1. Okware SI et al. An outbreak of Ebola in Uganda. Trop Med Int Health. 2002. PMID: 12460399",
"2. Osungbade KO, Oni AA. Outbreaks of EVD in West Africa. Afr J Med. 2014. PMID: 25474983",
"3. Bouba A et al. Case isolation, safe funerals & contact tracing in EVD. PLoS One. 2023. PMID: 36649296",
"4. Mazza C et al. Digital contact tracing in COVID-19: systematic review. Acta Biomed. 2021. PMID: 34889315",
"5. Chakrabartty I et al. Comparative overview of emerging RNA viruses. Ann Med Surg. 2022. PMID: 35721786",
"6. Lorenzo-Redondo R et al. Molecular epidemiology in HIV and SARS-CoV-2. Curr Opin HIV AIDS. 2021. PMID: 33186230",
"7. Balde AT et al. Ebola outbreak amid COVID-19 in Guinea. Am J Trop Med Hyg. 2021. PMC8176515",
"8. Park K. Park's Textbook of Preventive and Social Medicine, 24th Ed. 2017. pp. 150-155",
"9. WHO Outbreak Toolkit - Stages of an Outbreak Investigation. who.int/emergencies/outbreak-toolkit. 2026",
"10. WHO COVID-19 Surveillance Database. PLoS One. 2022. PMC9685131",
]
add_bullet_box(sl, 0.7, 3.76, 11.9, 3.3, refs,
font_size=10.5, color=C_DARK_GREY)
# ═══════════════════════════════════════════════════════════════════════════════
# BUILD
# ═══════════════════════════════════════════════════════════════════════════════
prs = make_prs()
slide_title(prs)
slide_agenda(prs)
slide_pathogens(prs)
slide_framework_overview(prs)
slide_case_definition(prs)
slide_case_id(prs)
slide_data_analysis(prs)
slide_control(prs)
slide_lessons(prs)
slide_conclusion(prs)
out_path = "/tmp/workspace/outbreak-investigation-pptx/Outbreak_Investigation_Frameworks.pptx"
buf = BytesIO()
prs.save(buf)
with open(out_path, "wb") as f:
f.write(buf.getvalue())
print(f"Saved: {out_path}")
print(f"Slides: {len(prs.slides)}")
cd /tmp/workspace/outbreak-investigation-pptx && python build_pptx.py 2>&1
Outbreak Investigation Frameworks
Presentation · PPTX
| Slide | Content |
|---|---|
| 1 - Title | Full-bleed branded cover with COVID-19 and Ebola badges |
| 2 - Agenda | 9-topic colour-coded grid overview |
| 3 - The Two Pathogens | Side-by-side comparison of SARS-CoV-2 vs EVD biology, R₀, CFR, vaccine status |
| 4 - Framework Overview | Visual 9-stage flow diagram + comparison table of how each stage applies to each disease |
| 5 - Case Definition | WHO COVID-19 tiered definition (Options A/B) vs the EVD alert/suspected/probable/confirmed hierarchy |
| 6 - Case ID & Contact Tracing | Active case finding methods and contact tracing protocols for both diseases (14-day vs 21-day) |
| 7 - Data Analysis | Three-column layout: Time (epi curves), Place (spot maps/GIS), Person (demographic risk stratification) |
| 8 - Control Measures | 3-tier framework (source / host / systemic) with COVID-19 and Ebola rows |
| 9 - Comparative Lessons | 5 numbered lessons with colour-coded highlight bars (SOPs, lab infrastructure, community trust, modelling, genomics) |
| 10 - Conclusion & References | Summary statement + 10 cited references with PMIDs |