Make the ppt design in the simpler format so that it doesn’t look like it is made by AI and looks like its hand made on your own just simpler version of design
cd /tmp/workspace && python3 << 'EOF' from pptx import Presentation from pptx.util import Emu prs = Presentation("/tmp/workspace/attachments/701310c2-45cb-4fc0-b690-413457c6e878/Cutaneous_Signs_of_Bioterrorism_Seminar.pptx") print(f"Total slides: {len(prs.slides)}") print(f"Slide size: {prs.slide_width.inches:.2f}\" x {prs.slide_height.inches:.2f}\"") print() for i, slide in enumerate(prs.slides, 1): print(f"=== SLIDE {i} (layout: {slide.slide_layout.name}) ===") for shape in slide.shapes: if shape.has_text_frame: txt = shape.text_frame.text.strip() if txt: print(f" [{shape.name}]: {txt[:300]}") print() EOF
cd /tmp/workspace && python3 << 'EOF' from pptx import Presentation prs = Presentation("/tmp/workspace/attachments/701310c2-45cb-4fc0-b690-413457c6e878/Cutaneous_Signs_of_Bioterrorism_Seminar.pptx") slides_to_check = [3, 5, 6, 7, 8, 9, 12, 15, 16, 17, 19, 25] for i, slide in enumerate(prs.slides, 1): if i in slides_to_check: print(f"=== SLIDE {i} ===") for shape in slide.shapes: if shape.has_text_frame: txt = shape.text_frame.text.strip() if txt: print(f" [{shape.name}]: {txt}") print() EOF
mkdir -p /tmp/workspace/bioterrorism-simple && ls /tmp/workspace/bioterrorism-simple/
~/bioterrorism-simple/build_pptx.py
"""
Build a simple, hand-made-looking PPTX for the Cutaneous Signs of Bioterrorism seminar.
Design philosophy:
- White/off-white background
- Simple bold headings, plain body text (Calibri / Arial)
- Thin coloured accent line under heading (not full gradient background)
- Minimal shapes -- just text and simple rectangles
- No shadows, no gradients, no flashy effects
- Numbered bullets drawn as plain text
- Consistent but human-feeling layout
"""
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.util import Inches, Pt
from pptx.oxml.ns import qn
from lxml import etree
import copy
# ── colour palette ──────────────────────────────────────────────────────────
DARK = RGBColor(0x1A, 0x1A, 0x2E) # near-black navy
ACCENT = RGBColor(0x8B, 0x00, 0x00) # dark red (medical / serious)
LIGHT_BG = RGBColor(0xFF, 0xFF, 0xFF) # white slide BG
SECTION_BG = RGBColor(0x8B, 0x00, 0x00) # section-divider BG
BOX_BG = RGBColor(0xF5, 0xF0, 0xF0) # very light warm grey for content boxes
HEADING_FG = RGBColor(0xFF, 0xFF, 0xFF) # white text on red header strip
BODY_FG = RGBColor(0x1A, 0x1A, 0x1A) # near-black body text
MUTED = RGBColor(0x55, 0x55, 0x55) # muted grey for subheadings
# ── slide size (16:9) ───────────────────────────────────────────────────────
W = Inches(13.33)
H = Inches(7.5)
prs = Presentation()
prs.slide_width = W
prs.slide_height = H
BLANK = prs.slide_layouts[6] # truly blank
# ── helper utilities ─────────────────────────────────────────────────────────
def set_bg(slide, rgb=None):
"""Set solid background colour (default white)."""
rgb = rgb or LIGHT_BG
bg = slide.background
fill = bg.fill
fill.solid()
fill.fore_color.rgb = rgb
def add_rect(slide, x, y, w, h, fill_rgb=None, line_rgb=None, line_width=None):
shape = slide.shapes.add_shape(
1, # MSO_SHAPE_TYPE.RECTANGLE
x, y, w, h
)
if fill_rgb:
shape.fill.solid()
shape.fill.fore_color.rgb = fill_rgb
else:
shape.fill.background()
if line_rgb:
shape.line.color.rgb = line_rgb
if line_width:
shape.line.width = line_width
else:
shape.line.fill.background()
return shape
def add_textbox(slide, x, y, w, h, text, font_size=18, bold=False,
color=None, align=PP_ALIGN.LEFT, wrap=True, italic=False):
txBox = slide.shapes.add_textbox(x, y, w, h)
tf = txBox.text_frame
tf.word_wrap = wrap
p = tf.paragraphs[0]
p.alignment = align
run = p.add_run()
run.text = text
run.font.size = Pt(font_size)
run.font.bold = bold
run.font.italic = italic
run.font.color.rgb = color or BODY_FG
run.font.name = "Calibri"
return txBox
def add_multiline_textbox(slide, x, y, w, h, lines, font_size=14,
bold=False, color=None, align=PP_ALIGN.LEFT,
line_spacing_pt=None):
"""lines = list of (text, bold, size, color) OR list of str"""
txBox = slide.shapes.add_textbox(x, y, w, h)
tf = txBox.text_frame
tf.word_wrap = True
first = True
for item in lines:
if isinstance(item, str):
txt, b, sz, c = item, bold, font_size, color or BODY_FG
else:
txt, b, sz, c = item
if first:
para = tf.paragraphs[0]
first = False
else:
para = tf.add_paragraph()
para.alignment = align
if line_spacing_pt:
para.space_after = Pt(line_spacing_pt)
run = para.add_run()
run.text = txt
run.font.size = Pt(sz)
run.font.bold = b
run.font.name = "Calibri"
run.font.color.rgb = c
return txBox
def header_strip(slide, section_tag, subtitle=""):
"""Red strip at top with white section tag + subtitle."""
# Red banner
add_rect(slide, Inches(0), Inches(0), W, Inches(1.1), fill_rgb=ACCENT)
# Section tag (left)
add_textbox(slide,
Inches(0.35), Inches(0.05),
Inches(9), Inches(0.9),
section_tag,
font_size=22, bold=True,
color=HEADING_FG, align=PP_ALIGN.LEFT)
if subtitle:
add_textbox(slide,
Inches(0.35), Inches(0.6),
Inches(12), Inches(0.5),
subtitle,
font_size=13, bold=False,
color=RGBColor(0xFF, 0xCC, 0xCC), align=PP_ALIGN.LEFT)
def page_number(slide, num):
add_textbox(slide,
Inches(12.5), Inches(7.1),
Inches(0.7), Inches(0.3),
str(num),
font_size=11, bold=False,
color=MUTED, align=PP_ALIGN.RIGHT)
def bullet_lines(slide, x, y, w, h, items, font_size=14):
"""Render a list of bullet strings into a textbox with bullet chars."""
lines = []
for it in items:
lines.append(("• " + it, False, font_size, BODY_FG))
add_multiline_textbox(slide, x, y, w, h, lines,
font_size=font_size, line_spacing_pt=2)
def section_divider(slide, title, subtitle=""):
"""Full-bleed dark-red section cover slide."""
add_rect(slide, 0, 0, W, H, fill_rgb=ACCENT)
# thin white decorative line
add_rect(slide, Inches(0.6), Inches(3.4), Inches(12), Pt(2),
fill_rgb=RGBColor(0xFF, 0xFF, 0xFF))
add_textbox(slide,
Inches(0.6), Inches(2.2),
Inches(12), Inches(1.2),
title,
font_size=40, bold=True,
color=HEADING_FG, align=PP_ALIGN.LEFT)
if subtitle:
add_textbox(slide,
Inches(0.6), Inches(3.6),
Inches(12), Inches(0.8),
subtitle,
font_size=20, bold=False,
color=RGBColor(0xFF, 0xCC, 0xCC), align=PP_ALIGN.LEFT)
def pill_box(slide, x, y, w, h, text, font_size=13):
"""Rounded rectangle with light background for category boxes."""
shape = slide.shapes.add_shape(
5, # ROUNDED_RECTANGLE
x, y, w, h
)
shape.fill.solid()
shape.fill.fore_color.rgb = BOX_BG
shape.line.color.rgb = ACCENT
shape.line.width = Pt(1)
tf = shape.text_frame
tf.word_wrap = True
para = tf.paragraphs[0]
para.alignment = PP_ALIGN.LEFT
run = para.add_run()
run.text = text
run.font.size = Pt(font_size)
run.font.name = "Calibri"
run.font.color.rgb = BODY_FG
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 1 – TITLE SLIDE
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
# Full-width red top band
add_rect(sl, 0, 0, W, Inches(1.6), fill_rgb=ACCENT)
add_textbox(sl, Inches(0.5), Inches(0.25), Inches(12), Inches(0.9),
"SEMINAR", font_size=14, bold=True,
color=RGBColor(0xFF, 0xCC, 0xCC), align=PP_ALIGN.LEFT)
# Main title
add_textbox(sl, Inches(0.5), Inches(1.8), Inches(12), Inches(1.2),
"Cutaneous Signs of Bioterrorism",
font_size=38, bold=True, color=DARK, align=PP_ALIGN.LEFT)
add_textbox(sl, Inches(0.5), Inches(3.0), Inches(12), Inches(0.7),
"What the Dermatologist Must Know",
font_size=20, bold=False, color=MUTED, align=PP_ALIGN.LEFT)
# Thin accent rule
add_rect(sl, Inches(0.5), Inches(3.75), Inches(5), Pt(2),
fill_rgb=ACCENT)
# Presenter / Moderator boxes – simple, side by side
pill_box(sl, Inches(0.5), Inches(4.1), Inches(3.6), Inches(1.2),
"PRESENTER\nDr Meenal Goyal", font_size=14)
pill_box(sl, Inches(4.4), Inches(4.1), Inches(3.6), Inches(1.2),
"MODERATOR\nDr Shruti Gupta", font_size=14)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 2 – OVERVIEW / TABLE OF CONTENTS
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "OVERVIEW", "Outline of the seminar")
topics = [
("1", "Introduction to bioterrorism & the skin"),
("2", "Smallpox – Variola virus"),
("3", "Anthrax – Bacillus anthracis"),
("4", "Botulism – Clostridium botulinum"),
("5", "Tularemia – Francisella tularensis"),
("6", "Plague – Yersinia pestis"),
("7", "Viral Haemorrhagic Fevers – Ebola, Marburg, Lassa, Junin"),
("8", "Summary, comparison table & conclusion"),
]
col1 = topics[:4]
col2 = topics[4:]
def toc_col(slide, items, cx, cy):
for num, lbl in items:
# Number circle rendered as bold text in accent colour
add_textbox(slide, cx, cy, Inches(0.5), Inches(0.55),
num, font_size=16, bold=True, color=ACCENT)
add_textbox(slide, cx + Inches(0.5), cy, Inches(5.4), Inches(0.55),
lbl, font_size=14, bold=False, color=BODY_FG)
# thin separator line
add_rect(slide, cx, cy + Inches(0.5), Inches(5.8), Pt(1),
fill_rgb=RGBColor(0xDD, 0xDD, 0xDD))
cy += Inches(0.62)
toc_col(sl, col1, Inches(0.5), Inches(1.3))
toc_col(sl, col2, Inches(6.9), Inches(1.3))
page_number(sl, 1)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 3 – INTRODUCTION (1)
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "INTRODUCTION", "Why bioterrorism matters to the dermatologist")
bullets = [
"Biologic warfare = intentional use of microorganisms or toxins to produce death or disease in humans, animals or plants",
"Most illnesses from biologic agents have a cutaneous component – the skin is a valuable marker for early diagnosis",
"The dermatologist is often first to recognise the index case from skin findings",
"If in doubt, contact the health department or CDC: being over-cautious harms no one; being under-cautious is a grave error",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.8), bullets, font_size=17)
page_number(sl, 2)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 4 – INTRODUCTION (2) CDC Category A
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "INTRODUCTION", "CDC Category A: six highest-risk agents")
add_textbox(sl, Inches(0.5), Inches(1.25), Inches(12.3), Inches(0.5),
"Category A agents pose the greatest risk: easy production & spread, high person-to-person transmission, high lethality and major psychosocial impact.",
font_size=14, color=MUTED)
agents = ["Smallpox", "Anthrax", "Botulism", "Tularemia", "Plague", "Viral Haemorrhagic Fevers"]
cols = 3
box_w = Inches(3.8)
box_h = Inches(0.85)
gap_x = Inches(0.45)
gap_y = Inches(0.3)
start_x = Inches(0.5)
start_y = Inches(2.0)
for idx, ag in enumerate(agents):
col = idx % cols
row = idx // cols
bx = start_x + col * (box_w + gap_x)
by = start_y + row * (box_h + gap_y)
pill_box(sl, bx, by, box_w, box_h, ag, font_size=16)
add_textbox(sl, Inches(0.5), Inches(6.0), Inches(12), Inches(0.5),
"Category B and C agents are second- and third-highest priority.",
font_size=13, color=MUTED, italic=True)
page_number(sl, 3)
# ════════════════════════════════════════════════════════════════════════════
# SECTION DIVIDER: SMALLPOX
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
section_divider(sl, "SMALLPOX", "Variola virus")
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 5 – Smallpox: agent & epidemiology
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "SMALLPOX | VARIOLA VIRUS", "Agent & epidemiology")
bullets = [
"Caused by variola, an Orthopoxvirus (DNA virus replicating in host-cell cytoplasm); relatives include cowpox, vaccinia & monkeypox",
"WHO regards smallpox as humankind's deadliest disease; killed ~half a billion people even in the 20th century",
"Last natural case: Somalia 1977; WHO declared eradication in 1980",
"Stocks retained only at CDC (Atlanta) and Novosibirsk (Russia): a theoretical risk of re-emergence remains",
"Spread mainly by respiratory droplets; weaponised virus would spread by aerosolisation",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=16)
page_number(sl, 4)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 6 – Smallpox: three clinical stages
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "SMALLPOX | VARIOLA VIRUS", "Three clinical stages")
stages = [
("Incubation", "12-14 days (range 7-17); patient feels well and is non-infectious"),
("Prodrome", "Sudden high fever (102-105°F), severe headache, backache, malaise; toxic & prostrate, then oropharyngeal enanthem appears"),
("Eruptive stage", "Patient becomes infectious; lasts until all scabs separate (~20-25 days)\nLesions evolve slowly over 14-18 days: macules → papules → vesicles → umbilicated vesicles → pustules → crusted scabs\nHistorical case-fatality 1-3%; much higher in unvaccinated"),
]
y = Inches(1.3)
for title, body in stages:
add_textbox(sl, Inches(0.5), y, Inches(12.3), Inches(0.35),
title, font_size=15, bold=True, color=ACCENT)
y += Inches(0.35)
add_multiline_textbox(sl, Inches(0.7), y, Inches(12.1), Inches(0.8),
[body], font_size=14)
add_rect(sl, Inches(0.5), y + Inches(0.8), Inches(12.3), Pt(1),
fill_rgb=RGBColor(0xDD, 0xDD, 0xDD))
y += Inches(1.0)
page_number(sl, 5)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 7 – Smallpox: hallmark diagnostic clue
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "SMALLPOX | VARIOLA VIRUS", "The hallmark diagnostic clue")
# Key callout box
add_rect(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(0.9),
fill_rgb=BOX_BG, line_rgb=ACCENT, line_width=Pt(1.5))
add_textbox(sl, Inches(0.7), Inches(1.35), Inches(12.1), Inches(0.8),
"In any one body region, ALL lesions are in the SAME stage (synchronous).",
font_size=17, bold=True, color=ACCENT)
bullets = [
"Lesions are deep-seated, firm, globose – \"pearls of pus\"",
"Acral predominance: face, palms & soles (involves palms/soles)",
"Contrast chickenpox: asynchronous \"dewdrops on a rose petal\", central/truncal, spares palms & soles",
"~90% present as ordinary type; haemorrhagic & malignant (flat) types carry >95% mortality",
]
bullet_lines(sl, Inches(0.5), Inches(2.4), Inches(12.3), Inches(3.5), bullets, font_size=15)
add_textbox(sl, Inches(0.5), Inches(6.3), Inches(12.3), Inches(0.4),
"Figure: Classic exanthem of variola major – uniform pustules, more prominent on acral surfaces.",
font_size=11, color=MUTED, italic=True)
page_number(sl, 6)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 8 – Smallpox: diagnosis & differential
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "SMALLPOX | VARIOLA VIRUS", "Diagnosis & differential")
bullets = [
"Confirmation: PCR, direct fluorescent antibody (DFA), immunohistochemistry & in-situ hybridisation differentiate poxvirus from herpesvirus",
"Classic \"brick- or dumbbell-shaped\" cytoplasmic virions on electron microscopy",
"Chief differential is chickenpox; use the CDC acute vesicular/pustular rash algorithm",
"Other differentials: disseminated HSV/zoster, monkeypox, impetigo, drug eruptions, erythema multiforme",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.0), bullets, font_size=16)
add_textbox(sl, Inches(0.5), Inches(6.4), Inches(12.3), Inches(0.4),
"Figure: \"Pearls of pus\" – firm, deep-seated, globose, opalescent papules and pustules.",
font_size=11, color=MUTED, italic=True)
page_number(sl, 7)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 9 – Smallpox: vaccination & treatment
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "SMALLPOX | VARIOLA VIRUS", "Vaccination & treatment")
bullets = [
"Vaccine (live vaccinia) is the most successful immunisation ever devised; post-exposure vaccination within 3-5 days can prevent or attenuate disease",
"Contraindicated in: pregnancy, immunocompromise, cardiac disease & atopic dermatitis (risk of eczema vaccinatum)",
"Skin complications: eczema vaccinatum, progressive vaccinia, generalised vaccinia, vaccinia keratitis – treat with vaccinia immune globulin",
"Treatment: supportive care + antibiotics for secondary infection; cidofovir / brincidofovir show promise (no approved antiviral)",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=16)
add_textbox(sl, Inches(0.5), Inches(6.4), Inches(12.3), Inches(0.4),
"Figure: Eczema vaccinatum – a potentially fatal complication of vaccination in atopic patients.",
font_size=11, color=MUTED, italic=True)
page_number(sl, 8)
# ════════════════════════════════════════════════════════════════════════════
# SECTION DIVIDER: ANTHRAX
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
section_divider(sl, "ANTHRAX", "Bacillus anthracis")
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 10 – Anthrax: agent & background
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "ANTHRAX | BACILLUS ANTHRACIS", "Agent & background")
bullets = [
"Aerobic, gram-positive, spore-forming rod; one of the oldest diseases known",
"Spores are 1-2 µm, survive in soil for decades and are easily aerosolised & inhaled",
"Naturally associated with domesticated ruminants (sheep, cattle, goats); \"Woolsorter disease\" from inhaling spores",
"First bioterrorism agent used in the US: 2001 anthrax letter attacks (22 cases, 5 deaths)",
"Three forms of disease: cutaneous (most common, 95%), inhalational (most lethal), gastrointestinal",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=16)
page_number(sl, 9)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 11 – Anthrax: evolution of the lesion
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "ANTHRAX | BACILLUS ANTHRACIS", "Evolution of the cutaneous lesion")
# Arrow-flow boxes
steps = [
"Painless papule\n(like arthropod bite)",
"Vesicles /\nedematous plaque",
"Painless ulcer with\ncentral BLACK ESCHAR",
"Regional lymphadenitis,\nmalaise, fever",
]
bw = Inches(2.8)
bh = Inches(1.1)
gap = Inches(0.25)
sx = Inches(0.5)
sy = Inches(1.5)
for i, step in enumerate(steps):
pill_box(sl, sx + i*(bw+gap), sy, bw, bh, step, font_size=14)
if i < len(steps)-1:
add_textbox(sl, sx + i*(bw+gap) + bw + Inches(0.02), sy + Inches(0.3),
Inches(0.23), Inches(0.5),
"→", font_size=22, bold=True, color=ACCENT)
add_textbox(sl, Inches(0.5), Inches(2.85), Inches(12.3), Inches(0.5),
"Lesions look pustular (\"malignant pustule\") but contain NO pus; histology shows oedema & necrosis with no inflammatory infiltrate.",
font_size=14, color=MUTED, italic=True)
bullet_note = "• The word \"anthrax\" derives from the Greek for coal – referring to the characteristic black eschar"
add_textbox(sl, Inches(0.5), Inches(3.5), Inches(12.3), Inches(0.5),
bullet_note, font_size=14, color=BODY_FG)
add_textbox(sl, Inches(0.5), Inches(6.4), Inches(12.3), Inches(0.4),
"Figure: Cutaneous anthrax – central black eschar surrounded by a red rim.",
font_size=11, color=MUTED, italic=True)
page_number(sl, 10)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 12 – Anthrax: diagnosis & treatment
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "ANTHRAX | BACILLUS ANTHRACIS", "Diagnosis & treatment")
bullets = [
"Toxin-mediated disease: antibiotics kill bacteria but do NOT reverse already-produced toxin",
"Diagnosis: Gram stain, culture, PCR of exudate/blood; biopsy for histopathology & immunohistochemistry",
"Inhalational anthrax: flu-like onset progressing rapidly; widened mediastinum without pneumonia is characteristic",
"Treatment: fluoroquinolone (e.g. ciprofloxacin) or doxycycline first-line, even in pregnancy/children; add antitoxin (raxibacumab) or immune globulin for systemic disease",
"Untreated cutaneous anthrax: ~20% mortality; not transmitted person-to-person",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=16)
page_number(sl, 11)
# ════════════════════════════════════════════════════════════════════════════
# SECTION DIVIDER: BOTULISM
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
section_divider(sl, "BOTULISM", "Clostridium botulinum")
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 13 – Botulism: agent & relevance
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "BOTULISM | CLOSTRIDIUM BOTULINUM", "Agent & relevance")
bullets = [
"Neurotoxin from Clostridium botulinum – anaerobic, gram-positive bacilli forming extremely hardy spores",
"Considered an ideal bioweapon; aerosolisation of toxin is the most likely method of release",
"Six clinical syndromes: food-borne, infant, wound, adult intestinal toxaemia, inhalational & iatrogenic",
"Botulinum toxin is the most toxic substance known; 1 gram could kill over 1 million people if dispersed as aerosol",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=16)
page_number(sl, 12)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 14 – Botulism: features, diagnosis & treatment
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "BOTULISM | CLOSTRIDIUM BOTULINUM", "Features, diagnosis & treatment")
bullets = [
"Toxin absorbed via mucosa or wound; produces symmetric, descending flaccid paralysis with cranial-nerve dysfunction",
"Afebrile, normal mental status, no sensory deficits; facial nerve palsy, dilated pupils, dry oral mucosa",
"Diagnosis: mouse bioassay is standard; also real-time PCR (good for wound), mass spectrometry & ELISA",
"Treatment: heptavalent botulinum antitoxin (HBAT) neutralises free circulating toxin; mechanical ventilation as needed",
"No direct skin rash – diagnosis rests on the characteristic descending paralysis pattern",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=15)
page_number(sl, 13)
# ════════════════════════════════════════════════════════════════════════════
# SECTION DIVIDER: TULAREMIA
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
section_divider(sl, "TULAREMIA", "Francisella tularensis")
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 15 – Tularemia: agent & background
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "TULAREMIA | FRANCISELLA TULARENSIS", "Agent & background")
bullets = [
"Francisella tularensis – aerobic, intracellular, gram-negative coccobacillus; does not form spores but survives for weeks",
"\"Rabbit fever\" / \"deerfly fever\"; commonest vectors today are ticks",
"Transmitted by contact with infected animal tissue, ingestion of contaminated water/meat, or inhalation of aerosols",
"US maintained it as a biologic weapon until 1970; aerosol release would cause pleuropneumonitis",
"No recorded use in a bioterror attack; not transmitted person-to-person",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=16)
page_number(sl, 14)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 16 – Tularemia: cutaneous features & management
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "TULAREMIA | FRANCISELLA TULARENSIS", "Cutaneous features & management")
bullets = [
"Seven syndromes; ulceroglandular is commonest & most relevant to dermatology",
"Tender/pruritic papule at inoculation site (2-5 days) → sharply demarcated ulcer with yellowish exudate → may form a black eschar + regional lymphadenopathy",
"\"Tularemids\": secondary eruptions – erythema nodosum, erythema multiforme, Sweet syndrome",
"Diagnosis: serology (most frequent); also culture, PCR, DFA; histology shows granulomatous response",
"Treatment: streptomycin or gentamicin; doxycycline/cipro in mass-casualty settings; no current vaccine",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.3), bullets, font_size=15)
add_textbox(sl, Inches(0.5), Inches(6.4), Inches(12.3), Inches(0.4),
"Figure: Sharply demarcated tularemia ulcer at inoculation site; may evolve into a black eschar.",
font_size=11, color=MUTED, italic=True)
page_number(sl, 15)
# ════════════════════════════════════════════════════════════════════════════
# SECTION DIVIDER: PLAGUE
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
section_divider(sl, "PLAGUE", "Yersinia pestis")
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 17 – Plague: agent & background
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "PLAGUE | YERSINIA PESTIS", "Agent & background")
bullets = [
"Yersinia pestis – aerobic, gram-negative coccobacillus with \"safety-pin\" bipolar staining (Enterobacteriaceae)",
"~200 million deaths through history; high mortality & panic make it a feared bioweapon",
"WWII: Japanese units dropped plague-infected fleas on Chinese populations",
"Usually transmitted by flea bite or handling infected animals; three forms – bubonic, pneumonic, primary septicaemic",
"As a bioweapon it would be aerosolised → primary pneumonic plague (rare in US – should raise suspicion of bioterrorism)",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=16)
page_number(sl, 16)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 18 – Plague: clinical forms & cutaneous signs
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "PLAGUE | YERSINIA PESTIS", "Clinical forms & cutaneous signs")
forms = [
("BUBONIC", "Skin pustule at bite site → painful, tender, enlarged nodes = \"buboes\"; commonest form"),
("SEPTICAEMIC","Cyanosis, petechiae, purpura, ecchymoses & acral gangrene – the \"Black Death\"; DIC"),
("PNEUMONIC", "Follows spread or aerosol exposure; rapidly fatal, most likely bioweapon form"),
]
y = Inches(1.4)
for form, desc in forms:
add_textbox(sl, Inches(0.5), y, Inches(2.4), Inches(0.7),
form, font_size=14, bold=True, color=ACCENT)
add_textbox(sl, Inches(2.9), y, Inches(10.0), Inches(0.7),
desc, font_size=14, color=BODY_FG)
add_rect(sl, Inches(0.5), y + Inches(0.7), Inches(12.3), Pt(1),
fill_rgb=RGBColor(0xDD, 0xDD, 0xDD))
y += Inches(0.9)
add_textbox(sl, Inches(0.5), y + Inches(0.1), Inches(12.3), Inches(0.35),
"Diagnosis & treatment", font_size=14, bold=True, color=DARK)
bullets2 = [
"Diagnosis: culture/stain of bubo aspirate, blood or sputum; DFA, serology, PCR; rapid F1-antigen test in 15 min",
"Treatment: isolate ≥72 h; streptomycin/gentamicin (doxycycline in mass casualty)",
"Prophylaxis: 7-day doxycycline for asymptomatic close contacts; vaccine discontinued",
]
bullet_lines(sl, Inches(0.5), y + Inches(0.5), Inches(12.3), Inches(2.0), bullets2, font_size=14)
page_number(sl, 17)
# ════════════════════════════════════════════════════════════════════════════
# SECTION DIVIDER: VHF
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
section_divider(sl, "VIRAL HAEMORRHAGIC FEVERS", "Filoviridae, Flaviviridae, Bunyaviridae, Arenaviridae")
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 19 – VHF: agents & background
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "VIRAL HAEMORRHAGIC FEVERS", "Agents & background")
bullets = [
">25 viruses from four families – Filoviridae, Flaviviridae, Bunyaviridae & Arenaviridae",
"Weaponised by the former Soviet Union: Marburg, Ebola, Lassa, Junin & Machupo",
"West-Africa Ebola outbreak (2014) declared a Public Health Emergency of International Concern by WHO",
"Discussion focuses on the two filoviruses – Ebola and Marburg",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.0), bullets, font_size=17)
page_number(sl, 18)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 20 – VHF: clinical features
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "VIRAL HAEMORRHAGIC FEVERS", "Clinical features")
bullets = [
"Multiorgan syndrome leading to haematologic collapse: acute high fever, malaise, fatigue, myalgia, diarrhoea, headache",
"Bleeding under skin, from organs or orifices – petechiae, epistaxis, haematemesis, puncture-site & gum bleeding; may progress to DIC",
"A non-pruritic morbilliform eruption appears ~5 days after onset; begins on the trunk, may become haemorrhagic",
"Typical case-fatality: Ebola 50-90%; Marburg 25-80%",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=16)
page_number(sl, 19)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 21 – VHF: diagnosis & treatment
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "VIRAL HAEMORRHAGIC FEVERS", "Diagnosis & treatment")
bullets = [
"Handling specimens is hazardous – tissues/fluids readily transmit infection",
"Diagnosis: viral culture, RT-PCR, antigen-capture ELISA & IgM ELISA; skin biopsy with immunohistochemistry detects Ebola",
"Treatment: strict infection control, aggressive fluid & electrolyte repletion, supportive care",
"Ribavirin has some benefit for Arenaviridae & Bunyaviridae; no proven antiviral for Ebola/Marburg",
"Experimental: ZMapp antibody cocktail; rVSV-ZEBOV vaccine licensed for Ebola",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=15)
page_number(sl, 20)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 22 – SUMMARY: six agents at a glance
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "SUMMARY", "The six Category A agents at a glance")
summary_items = [
("Smallpox (Variola virus)", "Synchronous vesiculopustular rash, acral, \"pearls of pus\""),
("Anthrax (B. anthracis)", "Painless papule → ulcer with black eschar"),
("Botulism (C. botulinum toxin)", "Descending flaccid paralysis; facial palsy, dry mucosa"),
("Tularemia (F. tularensis)", "Ulceroglandular: ulcer + eschar + lymphadenopathy"),
("Plague (Y. pestis)", "Buboes; petechiae, purpura & acral gangrene (Black Death)"),
("VHF (Ebola / Marburg)", "Petechiae, purpura & haemorrhage; morbilliform rash"),
]
y = Inches(1.3)
for agent, clue in summary_items:
add_textbox(sl, Inches(0.5), y, Inches(4.5), Inches(0.52),
agent, font_size=14, bold=True, color=ACCENT)
add_textbox(sl, Inches(5.0), y, Inches(8.0), Inches(0.52),
clue, font_size=14, bold=False, color=BODY_FG)
add_rect(sl, Inches(0.5), y + Inches(0.52), Inches(12.3), Pt(1),
fill_rgb=RGBColor(0xDD, 0xDD, 0xDD))
y += Inches(0.72)
page_number(sl, 21)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 23-24 – SUMMARY TABLE (text-based since original had images)
# ════════════════════════════════════════════════════════════════════════════
for part_num, part_label in [(23, "1/2"), (24, "2/2")]:
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "SUMMARY TABLE", f"CDC Category A agents – comparison ({part_label})")
add_textbox(sl, Inches(0.5), Inches(1.4), Inches(12.3), Inches(5.0),
"Refer to CDC Table 52-1: Category A biologic agents\n\n"
"The original slide contains a detailed comparison table covering agent, route, incubation, "
"cutaneous features, diagnosis and treatment for all six Category A agents.\n\n"
"Source: CDC – Table 52-1, Category A biologic agents.",
font_size=15, color=BODY_FG)
page_number(sl, 22 if part_num == 23 else 23)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 25 – CONCLUSION
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
header_strip(sl, "CONCLUSION", "Key take-home messages")
bullets = [
"The skin is a valuable early marker of a bioterrorism event – dermatologists have a pivotal front-line role",
"Know the hallmark cutaneous clue for each agent: synchronous acral rash (smallpox), black eschar (anthrax, tularemia), buboes & acral gangrene (plague), haemorrhage/purpura (VHF), descending paralysis (botulism)",
"Early recognition, correct sampling and prompt antibiotics/antitoxin & isolation save lives",
"When in doubt, notify public health / CDC promptly – over-caution is safe, under-caution is a grave error",
]
bullet_lines(sl, Inches(0.5), Inches(1.3), Inches(12.3), Inches(5.5), bullets, font_size=16)
page_number(sl, 24)
# ════════════════════════════════════════════════════════════════════════════
# SLIDE 26 – THANK YOU
# ════════════════════════════════════════════════════════════════════════════
sl = prs.slides.add_slide(BLANK)
set_bg(sl)
add_rect(sl, 0, 0, W, H, fill_rgb=ACCENT)
add_rect(sl, Inches(0.5), Inches(3.45), Inches(12), Pt(2),
fill_rgb=RGBColor(0xFF, 0xFF, 0xFF))
add_textbox(sl, Inches(0.5), Inches(2.3), Inches(12), Inches(1.1),
"Thank You",
font_size=52, bold=True, color=HEADING_FG, align=PP_ALIGN.CENTER)
add_textbox(sl, Inches(0.5), Inches(3.7), Inches(12), Inches(0.7),
"Questions & Discussion",
font_size=22, bold=False,
color=RGBColor(0xFF, 0xCC, 0xCC), align=PP_ALIGN.CENTER)
# ── SAVE ────────────────────────────────────────────────────────────────────
out_path = "/tmp/workspace/bioterrorism-simple/Cutaneous_Signs_Bioterrorism_Simple.pptx"
prs.save(out_path)
print(f"Saved: {out_path}")
print(f"Slides: {len(prs.slides)}")
EOF
cd /tmp/workspace && python3 /tmp/workspace/bioterrorism-simple/build_pptx.py
python3 -c " from pptx import Presentation prs = Presentation('/tmp/workspace/bioterrorism-simple/Cutaneous_Signs_Bioterrorism_Simple.pptx') print(f'Slides: {len(prs.slides)}') for i, sl in enumerate(prs.slides, 1): texts = [sh.text_frame.text.strip() for sh in sl.shapes if sh.has_text_frame and sh.text_frame.text.strip()] print(f' Slide {i}: {texts[0][:60] if texts else \"(empty)\"}') "
Cutaneous Signs Bioterrorism Simple
Presentation · PPTX