using this presentation create for me a presentation on cholera with about 20-25 slides for a clinical meeting as there is an outbreak ongoing. you can use images from this, make it bright themed and colourful with cartoon like images and also visually thrilling

Reading File
Reading File
Reading File
Running Command

cd /tmp/workspace/attachments/9febb409-b645-4895-b5f3-22ded5518d5a/ && python -c " from pptx import Presentation from pptx.util import Emu prs=Presentation('Cholera Case Management 11022025.pptx') print(prs.slide_width,prs.slide_height,len(prs.slides)) for i,s in enumerate(prs.slides,1): print('--- slide',i) for sh in s.shapes: t=sh.text_frame.text.strip().replace('\n',' | ') if sh.has_text_frame else '' print(sh.shape_type,sh.name,sh.width,sh.height,t[:400]) if s.has_notes_slide: print('NOTES',s.notes_slide.notes_text_frame.text[:300]) "

Running Command

mkdir -p /tmp/workspace/cholera/src /tmp/workspace/cholera/media && cd /tmp/workspace/cholera && python -c " from pptx import Presentation from pptx.enum.shapes import MSO_SHAPE_TYPE as T import hashlib prs=Presentation('/tmp/workspace/attachments/9febb409-b645-4895-b5f3-22ded5518d5a/Cholera Case Management 11022025.pptx') seen={} def walk(shapes,i): for sh in shapes: if sh.shape_type==T.GROUP: walk(sh.shapes,i) elif sh.shape_type==T.PICTURE: im=sh.image; h=hashlib.md5(im.blob).hexdigest()[:8] fn=f'media/s{i:02d}_{h}.{im.ext}' open(fn,'wb').write(im.blob) print(i,fn,im.size,len(im.blob),sh.name) for i,s in enumerate(prs.slides,1): walk(s.shapes,i) "

Running Command

cd /tmp/workspace/cholera && python -c " from pptx import Presentation prs=Presentation('/tmp/workspace/attachments/9febb409-b645-4895-b5f3-22ded5518d5a/Cholera Case Management 11022025.pptx') for i in [5,11,13,16,17,19,25,27,28,30,31,33,34,36,37,43,45,46]: s=prs.slides[i-1] print('=== slide',i) for sh in s.shapes: if sh.has_text_frame: print(sh.text_frame.text) if sh.has_table: for r in sh.table.rows: print(' || '.join(c.text.replace('\n',' / ') for c in r.cells)) if s.has_notes_slide: print('NOTES:',s.notes_slide.notes_text_frame.text[:900]) "

Running Command

mkdir -p /tmp/workspace/cholera/media && cd /tmp/workspace/cholera && python -c " from pptx import Presentation from pptx.enum.shapes import MSO_SHAPE_TYPE as T import hashlib prs=Presentation('/tmp/workspace/attachments/9febb409-b645-4895-b5f3-22ded5518d5a/Cholera Case Management 11022025.pptx') def walk(shapes,i): for sh in shapes: if sh.shape_type==T.GROUP: walk(sh.shapes,i) elif sh.shape_type==T.PICTURE: try: im=sh.image except Exception: continue h=hashlib.md5(im.blob).hexdigest()[:8] fn=f'media/s{i:02d}_{h}.{im.ext}' open(fn,'wb').write(im.blob) print(i,fn,im.size,len(im.blob),sh.name) for i,s in enumerate(prs.slides,1): walk(s.shapes,i) " python -c " from pptx import Presentation prs=Presentation('/tmp/workspace/attachments/9febb409-b645-4895-b5f3-22ded5518d5a/Cholera Case Management 11022025.pptx') for i in [5,11,13,16,17,19,25,28,31,33,34,36,37,43,45,46]: s=prs.slides[i-1] print('=== slide',i) for sh in s.shapes: if sh.has_text_frame: print(sh.text_frame.text[:700]) if getattr(sh,'has_table',False) and sh.has_table: for r in sh.table.rows: print(' || '.join(c.text.replace('\n',' / ') for c in r.cells)) if s.has_notes_slide: print('NOTES:',s.notes_slide.notes_text_frame.text[:500]) "

Running Command

cd /tmp/workspace/cholera && python -c " from PIL import Image, ImageDraw import glob fs=sorted(glob.glob('media/*')) seen=set();items=[] for f in fs: k=f.split('_')[1] if k in seen: continue seen.add(k); items.append(f) W=300;cols=5 rows=(len(items)+cols-1)//cols sheet=Image.new('RGB',(cols*W,rows*W),'white') d=ImageDraw.Draw(sheet) for n,f in enumerate(items): im=Image.open(f).convert('RGBA');bg=Image.new('RGBA',im.size,(200,200,200,255));bg.alpha_composite(im);im=bg.convert('RGB') im.thumbnail((W-10,W-30)) x=(n%cols)*W;y=(n//cols)*W sheet.paste(im,(x+5,y+25));d.text((x+5,y+5),f.split('/')[1],fill='red') sheet.save('contact.png');print(len(items)) "

Finding Sources
Searching PubMed

"cholera"[MeSH Terms] AND "treatment"

Searching the Web

WHO cholera global situation 2026 outbreak cases deaths oral cholera vaccine

Reading File
Running Command

cd /tmp/workspace/cholera && python -c " from PIL import Image im=Image.open('contact.png'); im=im.resize((im.width*2//3, im.height*2//3)); im.convert('RGB').save('contact.jpg',quality=70) import os;print(os.path.getsize('contact.jpg'), im.size)"

Reading File
Generating Image

A cute cartoon comma-shaped Vibrio cholerae bacterium villain character with one long flagellum tail and mischievous face, bright colorful flat illustration, white background

Generating Image

Cartoon illustration of a friendly doctor handing a glass of oral rehydration solution and an ORS sachet to a smiling child patient, bright colorful flat style, white background

Generating Image

Cartoon illustration of prevention: washing hands with soap under a tap, a clean water bucket with chlorine, and a toilet, bright colorful flat style, white background

Generating Image

Cartoon illustration of a sad dehydrated person with sunken eyes next to an empty water drop character and a thermometer, bright colorful flat style, white background

Running Command

cd /tmp/workspace/cholera && mkdir -p gen && python /tmp/skills/shared/scripts/fetch_images.py "https://cdn.orris.care/image-gen/0c25856a008c4411a30cb59a5939ea1b.png" "https://cdn.orris.care/image-gen/46c911c2af094c8db3c6d4f11494fa8d.png" "https://cdn.orris.care/image-gen/c813d68be7954ca49d113eceb09bf081.png" "https://cdn.orris.care/image-gen/7e46b3236a3a45d4a76e4ec8279860d4.png" > gen/out.json; python -c " import json,base64 from PIL import Image r=json.load(open('gen/out.json')) names=['bact','doc','wash','dehyd'] ims=[] for n,x in zip(names,r): print(n,x['error']) b=x['base64'].split('base64,')[1] open(f'gen/{n}.png','wb').write(base64.b64decode(b)) im=Image.open(f'gen/{n}.png');print(im.size,im.mode, im.getpixel((5,5))) ims.append(im.convert('RGB').resize((400,400))) s=Image.new('RGB',(800,800)) for i,im in enumerate(ims): s.paste(im,((i%2)*400,(i//2)*400)) s.save('gen/sheet.jpg',quality=70) "

Reading File
Writing File

~/cholera/build.py

import math, os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE
from PIL import Image, ImageChops

B = '/tmp/workspace/cholera/'
M = B + 'media/'
NAVY = '1B2A5E'; TEAL = '0DB7A9'; CORAL = 'FF5E6C'; SUN = 'FFC531'; PURPLE = '7A5AF8'
BLUE = '2E9BF0'; GREEN = '39C97E'; ORANGE = 'FF9142'; PINK = 'FF7EB6'; CREAM = 'FFF9EC'; WHITE = 'FFFFFF'
WARN = []

def rgb(h): return RGBColor.from_string(h)
def tint(h, f):
    r, g, b = [int(h[i:i + 2], 16) for i in (0, 2, 4)]
    return '%02X%02X%02X' % tuple(int(c + (255 - c) * f) for c in (r, g, b))

# autocrop generated cartoons
for n in ['bact', 'doc', 'wash', 'dehyd']:
    im = Image.open(B + f'gen/{n}.png').convert('RGB')
    bg = Image.new('RGB', im.size, (255, 255, 255))
    bbox = ImageChops.difference(im, bg).getbbox()
    x0, y0, x1, y1 = bbox
    im.crop((max(0, x0 - 10), max(0, y0 - 10), min(im.width, x1 + 10), min(im.height, y1 + 10))).save(B + f'gen/{n}_c.png')
G = lambda n: B + f'gen/{n}_c.png'

prs = Presentation()
prs.slide_width = Inches(13.333); prs.slide_height = Inches(7.5)
blank = prs.slide_layouts[6]
CUR = {'n': 0, 'title': ''}

def box(s, x, y, w, h, fill, shape=MSO_SHAPE.ROUNDED_RECTANGLE, line=None, lw=0, radius=0.12):
    sh = s.shapes.add_shape(shape, Inches(x), Inches(y), Inches(w), Inches(h))
    if fill: sh.fill.solid(); sh.fill.fore_color.rgb = rgb(fill)
    else: sh.fill.background()
    if line: sh.line.color.rgb = rgb(line); sh.line.width = Pt(lw)
    else: sh.line.fill.background()
    if shape == MSO_SHAPE.ROUNDED_RECTANGLE: sh.adjustments[0] = radius
    sh.shadow.inherit = False
    return sh

def tx(s, x, y, w, h, paras, size=16, color=NAVY, bold=False, align='l', anchor='t', font='Calibri', spacing=3, shape=None, margin=0.08):
    if shape is None:
        shape = s.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
    tf = shape.text_frame; tf.word_wrap = True
    tf.margin_left = tf.margin_right = Inches(margin); tf.margin_top = tf.margin_bottom = Inches(0.04)
    tf.vertical_anchor = {'t': MSO_ANCHOR.TOP, 'm': MSO_ANCHOR.MIDDLE, 'b': MSO_ANCHOR.BOTTOM}[anchor]
    if isinstance(paras, str): paras = [paras]
    total = 0
    for i, p in enumerate(paras):
        opts = {}
        if isinstance(p, tuple): p, opts = p
        sz = opts.get('size', size); col = opts.get('color', color); bd = opts.get('bold', bold)
        para = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        para.alignment = {'l': PP_ALIGN.LEFT, 'c': PP_ALIGN.CENTER, 'r': PP_ALIGN.RIGHT}[opts.get('align', align)]
        para.space_after = Pt(spacing)
        r = para.add_run(); r.text = p
        r.font.size = Pt(sz); r.font.bold = bd; r.font.color.rgb = rgb(col); r.font.name = opts.get('font', font)
        cw = 0.58 if (bd or font != 'Calibri') else 0.5
        lines = max(1, math.ceil(len(p) * sz * cw / 72 / max(0.3, w - 2 * margin)))
        total += lines * sz * 1.2 / 72 + spacing / 72
    if total > h - 0.05:
        WARN.append(f'slide {CUR["n"]} ({CUR["title"]}): text est {total:.2f}in > {h:.2f}in : {str(paras[0])[:40]}')
    return shape

def fit(s, path, x, y, w, h, frame=None, pad=0.0):
    im = Image.open(path); iw, ih = im.size
    sc = min((w - 2 * pad) / iw, (h - 2 * pad) / ih)
    pw, ph = iw * sc, ih * sc
    px, py = x + (w - pw) / 2, y + (h - ph) / 2
    if frame: box(s, x, y, w, h, WHITE, line=frame, lw=3)
    s.shapes.add_picture(path, Inches(px), Inches(py), Inches(pw), Inches(ph))

def new(title, color, notes=None, bg=CREAM):
    s = prs.slides.add_slide(blank)
    CUR['n'] += 1; CUR['title'] = title
    s.background.fill.solid(); s.background.fill.fore_color.rgb = rgb(bg)
    box(s, 0, 0, 13.333, 1.15, color, MSO_SHAPE.RECTANGLE)
    box(s, 11.4, -0.6, 1.5, 1.5, tint(color, .25), MSO_SHAPE.OVAL)
    box(s, 12.4, 0.1, 0.9, 0.9, tint(color, .5), MSO_SHAPE.OVAL)
    box(s, 10.7, 0.55, 0.4, 0.4, SUN, MSO_SHAPE.OVAL)
    tx(s, 0.5, 0.1, 10.2, 0.95, title, size=28, color=WHITE, bold=True, anchor='m', font='Trebuchet MS')
    for i, c in enumerate([TEAL, CORAL, SUN, PURPLE, BLUE, GREEN]):
        box(s, i * 13.333 / 6, 7.38, 13.333 / 6, 0.12, c, MSO_SHAPE.RECTANGLE)
    tx(s, 12.3, 7.05, 0.9, 0.3, str(CUR['n']), size=11, color='8A93B5', align='r')
    if notes: s.notes_slide.notes_text_frame.text = notes
    return s

def card(s, x, y, w, h, color, title, lines, tsize=18, bsize=14, hh=0.55, bullet=True, fill=WHITE):
    box(s, x, y, w, h, fill, line=color, lw=3)
    hd = box(s, x, y, w, hh, color)
    tx(s, 0, 0, 0, 0, title, size=tsize, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS', shape=hd)
    ps = [('\u2022  ' + l if bullet else l) for l in lines]
    tx(s, x + 0.08, y + hh + 0.06, w - 0.16, h - hh - 0.1, ps, size=bsize, spacing=4)

def circle_num(s, x, y, d, color, text, size=18):
    c = box(s, x, y, d, d, color, MSO_SHAPE.OVAL)
    tx(s, 0, 0, 0, 0, text, size=size, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS', shape=c, margin=0)

def chev(s, x, y, w, h, color, text, size=15, first=False):
    sh = box(s, x, y, w, h, color, MSO_SHAPE.PENTAGON if first else MSO_SHAPE.CHEVRON)
    tx(s, 0, 0, 0, 0, text, size=size, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS', shape=sh, margin=0.25)

def arrow(s, x, y, w, h, color, down=False):
    box(s, x, y, w, h, color, MSO_SHAPE.DOWN_ARROW if down else MSO_SHAPE.RIGHT_ARROW)

def table(s, x, y, colw, rows, hdr, size=13, rowh=0.5, fills=None, bold_first=True):
    gs = s.shapes.add_table(len(rows), len(colw), Inches(x), Inches(y), Inches(sum(colw)), Inches(rowh * len(rows)))
    t = gs.table
    tblPr = gs._element.graphic.graphicData.tbl.tblPr
    tblPr.set('bandRow', '0'); tblPr.set('firstRow', '0')
    for i, wv in enumerate(colw): t.columns[i].width = Inches(wv)
    for r, row in enumerate(rows):
        t.rows[r].height = Inches(rowh if not isinstance(rowh, list) else rowh[r])
        for c, val in enumerate(row):
            cell = t.cell(r, c); cell.margin_left = cell.margin_right = Inches(0.08)
            cell.margin_top = cell.margin_bottom = Inches(0.04)
            cell.vertical_anchor = MSO_ANCHOR.MIDDLE
            cell.fill.solid()
            cell.fill.fore_color.rgb = rgb(hdr if r == 0 else (fills[r - 1] if fills else (WHITE if r % 2 else tint(hdr, .88))))
            tf = cell.text_frame; tf.word_wrap = True
            lines = val.split('\n')
            for i, ln in enumerate(lines):
                p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
                run = p.add_run(); run.text = ln; run.font.size = Pt(size); run.font.name = 'Calibri'
                run.font.bold = (r == 0) or (c == 0 and bold_first)
                run.font.color.rgb = rgb(WHITE if r == 0 else NAVY)
    return t

# ============ 1. TITLE ============
s = prs.slides.add_slide(blank); CUR['n'] += 1; CUR['title'] = 'title'
s.background.fill.solid(); s.background.fill.fore_color.rgb = rgb(TEAL)
box(s, -1.5, -1.5, 5, 5, tint(TEAL, .25), MSO_SHAPE.OVAL)
box(s, 10.5, 4.8, 4.5, 4.5, tint(TEAL, .25), MSO_SHAPE.OVAL)
box(s, 9.6, 0.4, 0.5, 0.5, SUN, MSO_SHAPE.OVAL)
box(s, 0.6, 6.0, 0.35, 0.35, CORAL, MSO_SHAPE.OVAL)
box(s, 12.3, 3.9, 0.6, 0.6, PINK, MSO_SHAPE.OVAL)
box(s, 6.9, 1.0, 5.9, 4.4, WHITE, radius=0.08)
fit(s, G('bact'), 7.1, 1.2, 5.5, 4.0)
tx(s, 0.7, 1.2, 6.2, 1.4, 'CHOLERA', size=66, color=WHITE, bold=True, font='Trebuchet MS')
box(s, 0.8, 2.75, 5.6, 0.12, SUN, MSO_SHAPE.RECTANGLE)
tx(s, 0.7, 3.0, 6.0, 1.5, ['Outbreak response:', 'clinical case management'], size=30, color=WHITE, bold=True, font='Trebuchet MS')
tx(s, 0.7, 4.7, 6.0, 0.6, 'Clinical meeting  |  Rehydrate fast, save lives', size=20, color=NAVY, bold=True)
tx(s, 0.7, 6.3, 12, 0.7, 'Adapted from "Case Management in Cholera Control" (Dr Sinkala Annel) with WHO / GTFCC guidance and standard textbooks',
   size=13, color=WHITE)
s.notes_slide.notes_text_frame.text = 'Opening: this is a case management refresher for the ongoing outbreak. Key message: cholera kills by dehydration, and dehydration is treatable.'

# ============ 2. OUTBREAK PICTURE ============
s = new('The outbreak picture: why we are here', CORAL,
        'Regional figures are from the WHO AFRO rapid risk assessment (data to 20 September 2026). Replace the bottom box with our own line list: cases, deaths, CFR, hotspots.')
stats = [('160,799', 'suspected cases in 2026', CORAL), ('2,466', 'deaths reported', PURPLE),
         ('1.53%', 'case fatality ratio (goal: below 1%)', ORANGE), ('19', 'countries in WHO African Region', TEAL)]
for i, (n, l, c) in enumerate(stats):
    x = 0.5 + i * 3.1
    box(s, x, 1.5, 2.9, 2.5, c)
    box(s, x + 2.2, 1.3, 0.5, 0.5, SUN, MSO_SHAPE.OVAL)
    tx(s, x, 1.75, 2.9, 1.0, n, size=42, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS')
    tx(s, x + 0.1, 2.8, 2.7, 1.1, l, size=17, color=WHITE, bold=True, align='c')
box(s, 0.5, 4.3, 12.3, 1.0, tint(BLUE, .8), line=BLUE, lw=2.5)
tx(s, 0.7, 4.3, 11.9, 1.0, 'DR Congo, Nigeria and South Sudan together account for 83% of cases. A CFR above 1% signals gaps in access to rehydration and early care.',
   size=18, bold=True, anchor='m')
box(s, 0.5, 5.55, 12.3, 1.2, SUN, radius=0.15)
tx(s, 0.7, 5.55, 11.9, 1.2, [('OUR LOCAL SITUATION', {'size': 14, 'bold': True}), ('Insert today\'s cases, deaths, CFR and hotspot districts here', {'size': 20, 'bold': True})],
   anchor='m', align='c', font='Trebuchet MS')
tx(s, 0.5, 6.85, 11.5, 0.3, 'Source: WHO AFRO rapid risk assessment, epidemiological weeks 1-38, data to 20 September 2026', size=11, color='6B7499')

# ============ 3. KEY FACTS ============
s = new('Cholera: key facts', PURPLE,
        'Short incubation means rapid exponential rise. If you see some cases, there are probably more in the community.')
facts = [('All ages', 'Affects children and adults alike.', TEAL),
         ('Healthy adults die too', 'Unlike most diarrhoeal diseases, untreated cholera can kill healthy adults, not just children.', CORAL),
         ('Pregnancy', 'Pregnant women are at higher risk of complications, including loss of the pregnancy.', PINK),
         ('Under 5s', 'Children under 5, especially malnourished ones, are at greater risk of dying.', ORANGE)]
for i, (t, d, c) in enumerate(facts):
    x = 0.5 + (i % 2) * 6.25; y = 1.45 + (i // 2) * 2.2
    box(s, x, y, 6.0, 2.0, WHITE, line=c, lw=3)
    circle_num(s, x + 0.25, y + 0.3, 0.9, c, str(i + 1), 30)
    tx(s, x + 1.3, y + 0.15, 4.6, 0.55, t, size=22, bold=True, color=c, font='Trebuchet MS')
    tx(s, x + 1.3, y + 0.7, 4.6, 1.2, d, size=16)
box(s, 0.5, 5.95, 12.3, 1.0, PURPLE)
tx(s, 0.7, 5.95, 11.9, 1.0, 'Hits the poorest and most vulnerable hardest. A short incubation period can cause an exponential rise in cases.', size=18, color=WHITE, bold=True, anchor='m', align='c')

# ============ 4. CULPRIT ============
s = new('Meet the culprit: Vibrio cholerae', TEAL,
        'Source deck: transmission through contaminated water or food; fecal contamination can cause large epidemics; shellfish. Incubation 18 hours to 5 days.')
box(s, 0.5, 1.5, 5.0, 5.3, WHITE, line=TEAL, lw=3)
fit(s, G('bact'), 0.6, 1.9, 4.8, 3.6)
tx(s, 0.6, 5.7, 4.8, 1.0, 'Curved Gram-negative rod. Serogroups O1 (classical, El Tor) and O139 cause epidemics.', size=14, align='c')
rows = [('Organism', 'Vibrio cholerae serogroup O1 or O139, acquired by ingestion.', TEAL),
        ('Transmission', 'Contaminated drinking water or food. Faecal contamination can drive large epidemics. Raw or undercooked shellfish.', CORAL),
        ('Incubation', 'Short: 18 hours to 5 days. Cases can climb exponentially.', PURPLE)]
for i, (t, d, c) in enumerate(rows):
    y = 1.5 + i * 1.8
    box(s, 5.8, y, 7.0, 1.6, tint(c, .85), line=c, lw=2.5)
    b = box(s, 5.8, y, 1.9, 1.6, c)
    tx(s, 0, 0, 0, 0, t, size=18, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS', shape=b)
    tx(s, 7.8, y, 4.9, 1.6, d, size=16, anchor='m')

# ============ 5. CHAIN ============
s = new('Breaking the chain of death', BLUE,
        'Each link of the chain has an intervention. The last link, death, is almost entirely preventable with prompt rehydration.')
labels = ['Vibrio in the environment', 'Exposure', 'Infected', 'Diseased', 'Dead']
cols = [TEAL, BLUE, PURPLE, ORANGE, CORAL]
brk = ['Safe water, sanitation, chlorination', 'Handwashing, safe food, cook shellfish, OCV', 'Early detection, contact tracing, community alert',
       'Fast ORS or IV fluids at the nearest point of care', 'Zero deaths is the target: rehydrate before shock']
for i in range(5):
    chev(s, 0.4 + i * 2.5, 1.6, 2.65, 1.3, cols[i], labels[i], size=15, first=(i == 0))
    arrow(s, 1.4 + i * 2.5, 3.1, 0.5, 0.6, SUN, down=True)
    box(s, 0.5 + i * 2.5, 3.85, 2.3, 2.3, tint(cols[i], .85), line=cols[i], lw=2.5)
    tx(s, 0.55 + i * 2.5, 3.9, 2.2, 0.4, 'Break it with', size=13, bold=True, color=cols[i], align='c')
    tx(s, 0.55 + i * 2.5, 4.3, 2.2, 1.8, brk[i], size=15, align='c', anchor='m')
box(s, 0.5, 6.35, 12.3, 0.7, NAVY)
tx(s, 0.7, 6.35, 11.9, 0.7, 'Presence \u2192 Exposure \u2192 Infection \u2192 Disease \u2192 Death. We act hardest at the last two links.', size=17, color=WHITE, bold=True, anchor='m', align='c')

# ============ 6. PATHOGENESIS ============
s = new('Pathogenesis: how a toxin drains the gut', PURPLE,
        'V. cholerae expresses toxin co-regulated pilus (TCP) and cholera toxin. CtxB binds GM1 ganglioside on enterocytes, CtxA raises cAMP, CFTR secretes chloride, sodium and water follow. Sodium-glucose cotransport is unaffected, which is the basis of ORS (Goldman-Cecil).')
steps = [('Swallowed', 'Vibrios in water or food survive stomach acid.', TEAL),
         ('Colonise', 'Attach to small bowel wall using toxin co-regulated pilus.', BLUE),
         ('Toxin released', 'Cholera toxin: A subunit and five B subunits.', PURPLE),
         ('Binds GM1', 'B subunits lock onto GM1 receptors on enterocytes.', ORANGE),
         ('cAMP surges', 'A subunit locks adenylate cyclase on, cAMP rises.', CORAL),
         ('Rice-water flood', 'Chloride pumped out, Na+ and water follow: massive watery stool.', PINK)]
for i, (t, d, c) in enumerate(steps):
    x = 0.5 + (i % 3) * 4.15; y = 1.5 + (i // 3) * 2.45
    box(s, x, y, 3.8, 2.2, WHITE, line=c, lw=3)
    circle_num(s, x + 0.15, y + 0.15, 0.7, c, str(i + 1), 22)
    tx(s, x + 0.95, y + 0.15, 2.8, 0.7, t, size=19, bold=True, color=c, anchor='m', font='Trebuchet MS')
    tx(s, x + 0.15, y + 0.95, 3.5, 1.2, d, size=15)
    if i % 3 < 2: arrow(s, x + 3.82, y + 0.85, 0.3, 0.45, SUN)
box(s, 0.5, 6.45, 12.3, 0.7, GREEN)
tx(s, 0.7, 6.45, 11.9, 0.7, 'Sodium-glucose co-transport still works, so oral rehydration works even in severe cholera.', size=17, color=WHITE, bold=True, anchor='m', align='c')

# ============ 7. SPECTRUM ============
s = new('Spectrum of illness: the iceberg', ORANGE,
        'CDC: 75% asymptomatic, most of the 25% symptomatic have mild illness; about 2% of infections are severe (cholera gravis) and about 5% moderate. This is roughly 5-10% of symptomatic cases.')
cd = CategoryChartData(); cd.categories = ['Asymptomatic', 'Mild', 'Moderate', 'Severe']
cd.add_series('Share of infections', (75, 18, 5, 2))
gf = s.shapes.add_chart(XL_CHART_TYPE.DOUGHNUT, Inches(0.4), Inches(1.4), Inches(6.2), Inches(5.5), cd)
ch = gf.chart; ch.has_legend = False; ch.has_title = False
pl = ch.plots[0]; pl.has_data_labels = True
dl = pl.data_labels; dl.number_format = '0"%"'; dl.number_format_is_linked = False
dl.font.size = Pt(16); dl.font.bold = True; dl.font.color.rgb = rgb(WHITE)
for i, c in enumerate([TEAL, SUN, ORANGE, CORAL]):
    pt = pl.series[0].points[i]; pt.format.fill.solid(); pt.format.fill.fore_color.rgb = rgb(c)
    pt.format.line.color.rgb = rgb(WHITE)
leg = [('75%', 'Asymptomatic carriers: silent spreaders', TEAL), ('18%', 'Mild diarrhoea', SUN),
       ('5%', 'Moderate: seek care, may not need admission', ORANGE), ('2%', 'Severe cholera gravis: fatal if untreated', CORAL)]
for i, (n, d, c) in enumerate(leg):
    y = 1.5 + i * 1.3
    box(s, 6.9, y, 5.9, 1.1, tint(c, .85), line=c, lw=2.5)
    b = box(s, 6.9, y, 1.5, 1.1, c)
    tx(s, 0, 0, 0, 0, n, size=26, color=WHITE if c != SUN else NAVY, bold=True, align='c', anchor='m', font='Trebuchet MS', shape=b)
    tx(s, 8.5, y, 4.2, 1.1, d, size=16, anchor='m', bold=True)
tx(s, 6.9, 6.7, 5.9, 0.4, 'Biotype El Tor, share of all infections. Severe cases are 5-10% of symptomatic patients.', size=12, color='6B7499')

# ============ 8. CASE DEFINITIONS ============
s = new('Case definitions', GREEN,
        'Use the right definition for the setting: before declaration, the suspected case needs severe dehydration; after declaration, any acute watery diarrhoea qualifies.')
cs = [('SUSPECTED', 'Outbreak not yet declared', 'Any person aged 2 years or older with acute watery diarrhoea and severe dehydration, or dying from acute watery diarrhoea.', TEAL),
      ('SUSPECTED', 'Outbreak declared', 'Any person presenting with, or dying from, acute watery diarrhoea.', ORANGE),
      ('CONFIRMED', 'Laboratory', 'A suspected case with V. cholerae O1 or O139 infection confirmed by culture or PCR.', PURPLE)]
for i, (a, b2, d, c) in enumerate(cs):
    x = 0.5 + i * 4.15
    box(s, x, 1.5, 3.9, 4.3, WHITE, line=c, lw=3)
    hd = box(s, x, 1.5, 3.9, 1.3, c)
    tx(s, 0, 0, 0, 0, [(a, {'size': 24, 'bold': True}), (b2, {'size': 15})], color=WHITE, align='c', anchor='m', font='Trebuchet MS', shape=hd)
    tx(s, x + 0.15, 2.95, 3.6, 2.8, d, size=17)
box(s, 0.5, 6.05, 12.3, 0.9, tint(GREEN, .8), line=GREEN, lw=2.5)
tx(s, 0.7, 6.05, 11.9, 0.9, 'Rapid tests can flag early cases, but confirm by culture or PCR. Never wait for results before starting rehydration.', size=17, bold=True, anchor='m', align='c')

# ============ 9. CLINICAL PRESENTATION ============
s = new('Clinical presentation', CORAL,
        'The symptoms and signs result from rapid loss of fluid and electrolytes. Leg cramps reflect hypokalaemia; vomiting is related to acidosis.')
box(s, 0.5, 1.45, 4.9, 5.0, WHITE, line=CORAL, lw=3)
fit(s, M + 's18_92732991.jpg', 0.6, 1.55, 4.7, 3.55)
tx(s, 0.6, 5.2, 4.7, 1.2, [('"Rice-water" stool', {'size': 20, 'bold': True, 'color': CORAL}), ('Pale, watery, flecked with mucus, little or no odour of blood', {'size': 14})], align='c', font='Calibri')
syms = [('Profuse watery diarrhoea', CORAL), ('Vomiting', ORANGE), ('Leg cramps (low K+)', PURPLE), ('Thirst', BLUE),
        ('Restless or irritable', TEAL), ('Fast heart rate', PINK), ('Low blood pressure', CORAL), ('Dry mouth, sunken eyes', ORANGE),
        ('Poor skin turgor', GREEN), ('Metabolic acidosis', PURPLE)]
for i, (t, c) in enumerate(syms):
    x = 5.7 + (i % 2) * 3.65; y = 1.45 + (i // 2) * 1.0
    b = box(s, x, y, 3.5, 0.85, c, radius=0.5)
    tx(s, 0, 0, 0, 0, t, size=16, color=WHITE, bold=True, align='c', anchor='m', shape=b)
box(s, 5.7, 6.5, 7.15, 0.6, SUN)
tx(s, 5.8, 6.5, 6.95, 0.6, 'Severe disease: shock, renal failure, coma, death', size=17, bold=True, anchor='m', align='c')

# ============ 10. GRAVIS ============
s = new('Cholera gravis: the severe end', CORAL,
        'A patient may produce 8 litres or more of stool in hours and lose over 10% of body weight. Untreated, about 50% of severe cases die; with proper fluid replacement mortality falls below 1%.')
box(s, 0.5, 1.4, 3.3, 5.6, WHITE, line=CORAL, lw=3)
fit(s, M + 's20_3ed0d4f2.png', 0.6, 1.5, 3.1, 5.4)
big = [('>10%', 'of body weight lost within hours', CORAL), ('1 L/hour', 'fluid loss possible in the first 24 hours', ORANGE),
       ('8 L+', 'of stool can be passed in a few hours', PURPLE)]
for i, (n, d, c) in enumerate(big):
    x = 4.1 + i * 2.95
    box(s, x, 1.4, 2.75, 2.5, c)
    tx(s, x, 1.55, 2.75, 1.0, n, size=36, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS')
    tx(s, x + 0.1, 2.6, 2.55, 1.2, d, size=16, color=WHITE, bold=True, align='c')
box(s, 4.1, 4.15, 4.2, 2.85, tint(CORAL, .85), line=CORAL, lw=3)
tx(s, 4.2, 4.2, 4.0, 0.9, '50%', size=48, color=CORAL, bold=True, align='c', font='Trebuchet MS')
tx(s, 4.2, 5.2, 4.0, 1.7, 'of severe cases die if untreated', size=19, bold=True, align='c')
box(s, 8.6, 4.15, 4.2, 2.85, tint(GREEN, .8), line=GREEN, lw=3)
tx(s, 8.7, 4.2, 4.0, 0.9, '<1%', size=48, color=GREEN, bold=True, align='c', font='Trebuchet MS')
tx(s, 8.7, 5.2, 4.0, 1.7, 'die with prompt, proper rehydration', size=19, bold=True, align='c')

# ============ 11. DDX ============
s = new('Differential diagnosis of diarrhoea', BLUE,
        'Table adapted from LaRocque and Pietroni: common pathogens causing diarrhoea in adults in the developing world.')
box(s, 0.5, 1.45, 6.0, 5.0, WHITE, line=TEAL, lw=3)
hd = box(s, 0.5, 1.45, 6.0, 0.7, TEAL)
tx(s, 0, 0, 0, 0, 'Acute WATERY diarrhoea', size=20, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS', shape=hd)
chips = ['ETEC (most common)', 'Vibrio cholerae O1/O139', 'Norovirus (vomiting prominent)', 'Campylobacter', 'Non-typhoidal Salmonella', 'Aeromonas', 'EAEC', 'Enterotoxigenic B. fragilis']
for i, t in enumerate(chips):
    cc = CORAL if i == 1 else tint(TEAL, .75)
    b = box(s, 0.7 + (i % 2) * 2.9, 2.35 + (i // 2) * 1.0, 2.75, 0.85, cc, radius=0.4)
    tx(s, 0, 0, 0, 0, t, size=14, color=WHITE if i == 1 else NAVY, bold=True, align='c', anchor='m', shape=b)
box(s, 6.85, 1.45, 6.0, 5.0, WHITE, line=PURPLE, lw=3)
hd = box(s, 6.85, 1.45, 6.0, 0.7, PURPLE)
tx(s, 0, 0, 0, 0, 'Acute BLOODY diarrhoea', size=20, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS', shape=hd)
chips = ['Shigella (most common)', 'Campylobacter', 'EIEC', 'EHEC', 'Salmonella (rare)', 'Entamoeba histolytica', 'Schistosoma mansoni']
for i, t in enumerate(chips):
    b = box(s, 7.05 + (i % 2) * 2.9, 2.35 + (i // 2) * 1.0, 2.75, 0.85, tint(PURPLE, .75), radius=0.4)
    tx(s, 0, 0, 0, 0, t, size=14, color=NAVY, bold=True, align='c', anchor='m', shape=b)
box(s, 0.5, 6.6, 12.3, 0.5, SUN)
tx(s, 0.7, 6.6, 11.9, 0.5, 'Profuse rice-water stool with rapid dehydration in an outbreak setting: think cholera, treat as cholera.', size=15, bold=True, anchor='m', align='c')

# ============ 12. ASSESS DEHYDRATION ============
s = new('Assess dehydration: look, feel, pinch', TEAL,
        'Examine mental status, eyes, ability to drink, and skin pinch to classify quickly. Treatment follows the classification.')
cols3 = [('1. NO DEHYDRATION', GREEN, ['Awake and alert', 'Normal blood pressure and pulse', 'Normal thirst', 'Eyes not sunken', 'Skin pinch goes back normally'], 'Plan A'),
         ('2. MODERATE (5-10%)', ORANGE, ['Restless, irritable', 'Sunken eyes, dry mouth and tongue', 'Thirsty, drinks eagerly', 'Skin pinch goes back slowly', 'BP normal, pulse normal or fast', 'Infant: fewer tears, sunken fontanelle'], 'Plan B'),
         ('3. SEVERE (>10%)', CORAL, ['Hypovolaemic shock, low BP', 'Weak or absent pulse', 'Little or no urine', 'Skin tenting, very sunken eyes', 'Very dry mouth and tongue', 'Drowsy or unconscious'], 'Plan C')]
for i, (t, c, ls, p) in enumerate(cols3):
    x = 0.5 + i * 4.15
    card(s, x, 1.4, 3.9, 4.7, c, t, ls, tsize=18, bsize=15)
    b = box(s, x + 0.6, 6.25, 2.7, 0.75, c, radius=0.5)
    tx(s, 0, 0, 0, 0, '\u2192 ' + p, size=22, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS', shape=b)

# ============ 13. WHY DIE ============
s = new('Why do people really die?', CORAL,
        'People do not die from cholera itself; they die from severe dehydration. Death definitions: community death occurs before admission to a facility or CTC; facility death occurs after admission regardless of timing.')
box(s, 0.5, 1.4, 12.3, 1.1, NAVY)
tx(s, 0.7, 1.4, 11.9, 1.1, 'People do not die "from cholera". They die because they become severely dehydrated and the body cannot survive without enough water.', size=19, color=WHITE, bold=True, anchor='m', align='c')
lab = ['Cholera', 'Diarrhoea', 'Dehydration', 'Severe dehydration', 'DEATH']
cc = [TEAL, BLUE, ORANGE, PURPLE, CORAL]
for i in range(5):
    chev(s, 0.4 + i * 2.5, 2.75, 2.65, 1.05, cc[i], lab[i], size=15, first=(i == 0))
card(s, 0.5, 4.1, 4.0, 2.95, TEAL, 'Community death', ['Suspected or confirmed case', 'Dies in the community or on the way', 'Before admission to facility or CTC'], bsize=14, tsize=17)
card(s, 4.65, 4.1, 4.0, 2.95, PURPLE, 'Facility death', ['Suspected or confirmed case', 'Dies after admission to a health facility or CTC', 'Regardless of time since admission'], bsize=14, tsize=17)
box(s, 8.9, 4.1, 3.9, 2.95, WHITE, line=CORAL, lw=3)
fit(s, G('dehyd'), 9.0, 4.2, 3.7, 2.75)

# ============ 14. TRIAGE ============
s = new('Triage and rapid assessment', BLUE,
        'Use the ABCD approach: assess and initiate management of emergency signs before moving on. Screen at the door so severe cases are treated first.')
box(s, 0.5, 1.4, 7.4, 3.6, WHITE, line=BLUE, lw=3)
fit(s, M + 's29_188ba4de.png', 0.6, 1.5, 7.2, 3.4)
card(s, 8.2, 1.4, 4.6, 3.6, CORAL, 'Emergency signs: act now', ['Airway and breathing: obstruction, distress', 'Circulation: weak pulse, low BP, cold hands, tenting skin', 'Disability: drowsy, convulsing, unconscious', 'Treat first, take history after'], bsize=14, tsize=17)
box(s, 0.5, 5.2, 12.3, 1.85, tint(SUN, .6), line=SUN, lw=3)
tx(s, 0.7, 5.25, 11.9, 0.45, 'Key history for acute watery diarrhoea', size=18, bold=True, font='Trebuchet MS')
hist = ['Onset and number of stools', 'Vomiting', 'Urine output', 'Sick contacts', 'Water and food source', 'Pregnancy', 'Other illness and drugs']
for i, t in enumerate(hist):
    b = box(s, 0.7 + i * 1.7, 5.85, 1.6, 1.0, [TEAL, ORANGE, BLUE, PURPLE, GREEN, PINK, CORAL][i], radius=0.3)
    tx(s, 0, 0, 0, 0, t, size=12, color=WHITE, bold=True, align='c', anchor='m', shape=b, margin=0.04)

# ============ 15. PLANS OVERVIEW ============
s = new('Treat by dehydration status: Plans A, B, C', PURPLE,
        'Patients with no dehydration receive ORS after each loose stool until diarrhoea stops. Moderate: ORS by weight and age. Severe: IV fluid rapidly until BP normal.')
plans = [('A', 'No dehydration', GREEN, ['ORS after each loose stool', 'Treat at home or in the community', 'Teach danger signs', 'Return at once if worse']),
         ('B', 'Moderate dehydration', ORANGE, ['ORS by weight and age over 4 hours', 'Check every hour for the first 2 hours', 'Repeat ORS 10 minutes after vomiting', 'Reassess at 4 hours, then re-classify']),
         ('C', 'Severe dehydration', CORAL, ['IV Ringer\'s lactate, fast', 'Until BP is normal (3-6 hours)', 'Add ORS if able to drink', 'Admit to CTC / CTU'])]
for i, (l, t, c, ls) in enumerate(plans):
    x = 0.5 + i * 4.15
    box(s, x, 1.5, 3.9, 5.4, WHITE, line=c, lw=3)
    box(s, x, 1.5, 3.9, 2.0, c)
    circle_num(s, x + 1.25, 1.65, 1.4, WHITE, '', 10)
    tx(s, x + 1.25, 1.65, 1.4, 1.4, l, size=56, color=c, bold=True, align='c', anchor='m', font='Trebuchet MS', margin=0)
    tx(s, x + 0.1, 3.05, 3.7, 0.45, t, size=17, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS')
    tx(s, x + 0.15, 3.7, 3.6, 3.1, ['\u2022  ' + z for z in ls], size=16, spacing=8)

# ============ 16. ORS ============
s = new('ORS: the lifesaving drink', TEAL,
        'WHO ORS composition. The deck lists standard ORS (90/20/80/30, glucose 111 mmol/L). The current reduced-osmolarity WHO formula is 75/20/65, citrate 10, glucose 75 mmol/L, 245 mOsm/L. Zinc is given to children with diarrhoea.')
box(s, 0.5, 1.4, 4.3, 3.7, WHITE, line=TEAL, lw=3)
fit(s, G('doc'), 0.6, 1.5, 4.1, 3.5)
rows = [['mmol/L', 'Na+', 'K+', 'Cl-', 'Base', 'Glucose'],
        ['Standard WHO ORS', '90', '20', '80', '30 (HCO3)', '111'],
        ['Reduced osmolarity ORS', '75', '20', '65', '10 (citrate)', '75']]
table(s, 5.1, 1.5, [2.4, 0.9, 0.9, 0.9, 1.4, 1.2], rows, TEAL, size=15, rowh=0.62)
tx(s, 5.1, 3.5, 7.7, 0.4, 'Reduced osmolarity: 245 mOsm/L, recommended by WHO for routine use.', size=13, color='6B7499')
pts = [('80-90%', 'of patients can be treated with ORS alone', GREEN), ('Switch early', 'patients on IV move to ORS as soon as possible', BLUE), ('Be proactive', 'raise ORS volume gradually while IV is tapered', ORANGE)]
for i, (a, d, c) in enumerate(pts):
    x = 5.1 + i * 2.6
    box(s, x, 4.0, 2.45, 1.1, c)
    tx(s, x, 4.0, 2.45, 0.5, a, size=18, color=WHITE, bold=True, align='c', anchor='m', font='Trebuchet MS')
    tx(s, x + 0.05, 4.5, 2.35, 0.6, d, size=12, color=WHITE, align='c')
box(s, 0.5, 5.35, 12.3, 1.7, tint(TEAL, .85), line=TEAL, lw=3)
tx(s, 0.7, 5.4, 11.9, 1.6, ['Why it works: glucose pulls sodium and water across the gut wall, even when cholera toxin is active.',
                          'Practical: one sachet per litre of clean water, sip often, give the cup within reach, sit the patient up. In children add zinc (the Kit ya Moyo packs ORS with zinc).'], size=16, spacing=6, anchor='m')

# ============ 17. CHARTS ============
s = new('Quick-reference charts: Plans A, B and C', BLUE,
        'Charts are from the source deck. Plan A and B dosing is by age and weight; Plan C shows the IV schedule.')
box(s, 0.4, 1.35, 4.9, 5.7, WHITE, line=GREEN, lw=3)
fit(s, M + 's22_d95ac0fe.png', 0.5, 1.45, 4.7, 5.5)
box(s, 5.5, 1.35, 4.9, 5.7, WHITE, line=CORAL, lw=3)
fit(s, M + 's24_f5d1c5db.png', 5.6, 1.45, 4.7, 5.5)
card(s, 10.6, 1.35, 2.35, 5.7, PURPLE, 'Tips', ['Weigh the patient if possible', 'Use age if weight unknown', 'Zinc for children', 'Reassess after each phase'], bsize=14, tsize=18)

# ============ 18. PLAN C ============
s = new('Plan C: IV rehydration for severe cases', CORAL,
        'IV treatment should be rapid through large-bore catheters until BP is normal. Over 1 year: 30 mL/kg in 30 minutes then 70 mL/kg in 2.5 hours. Under 1 year: 30 mL/kg in the first hour then 70 mL/kg in 5 hours. 200 mL/kg or more may be needed in 24 hours.')
tx(s, 0.5, 1.35, 7.5, 0.45, 'Ringer\'s lactate: 100 mL/kg in total', size=20, bold=True, font='Trebuchet MS')
def bars(y, label, a, b2):
    tx(s, 0.5, y, 7.5, 0.4, label, size=15, bold=True)
    box(s, 0.5, y + 0.45, 7.5 * .3, 0.9, CORAL)
    box(s, 0.5 + 7.5 * .3, y + 0.45, 7.5 * .7, 0.9, TEAL)
    tx(s, 0.5, y + 0.45, 7.5 * .3, 0.9, a, size=15, color=WHITE, bold=True, align='c', anchor='m')
    tx(s, 0.5 + 7.5 * .3, y + 0.45, 7.5 * .7, 0.9, b2, size=15, color=WHITE, bold=True, align='c', anchor='m')
bars(1.9, 'Age over 1 year', '30 mL/kg in 30 min', '70 mL/kg in 2.5 hours')
bars(3.55, 'Age under 1 year', '30 mL/kg in 1 hour', '70 mL/kg in 5 hours')
box(s, 0.5, 5.35, 7.5, 1.65, SUN)
tx(s, 0.6, 5.35, 7.3, 1.65, [('Adults: 1 litre in the first 15 minutes', {'size': 19, 'bold': True}),
                              ('Keep going until blood pressure is normal (3-6 hours). Up to 200 mL/kg or more may be needed in the first 24 hours.', {'size': 15})], anchor='m', spacing=5)
card(s, 8.3, 1.35, 4.5, 5.65, PURPLE, 'IV checklist', ['Ringer\'s lactate is best; saline works but is less effective', 'D5W is ineffective (only if malnourished)', 'Two large-bore lines (16G or 18G) if needed', 'Hang the bag high, new IV set for every patient', 'Give ORS 5 mL/kg/hour alongside if able to drink', 'No oral or NG route if shocked or unconscious'], bsize=14, tsize=19)

# ============ 19. MONITORING ============
s = new('Monitoring and signs of rehydration', GREEN,
        'Record input and output. Adequate rehydration: skin returns normally on pinch, thirst gone, urine passed, strong pulse.')
box(s, 0.5, 1.4, 3.3, 5.6, WHITE, line=GREEN, lw=3)
fit(s, M + 's30_6c7121fe.png', 0.6, 1.5, 3.1, 5.4)
card(s, 4.1, 1.4, 4.2, 5.6, BLUE, 'Chart every patient', ['INPUT: litres of IV fluid and cups of ORS', 'Mark the volume per hour on each bag', 'Keep cup and ORS within reach; sit up to drink', 'OUTPUT: volume and type of stool, vomit', 'OUTPUT: is urine being passed?'], bsize=15, tsize=19)
tx(s, 8.6, 1.4, 4.2, 0.5, 'Adequately rehydrated when...', size=19, bold=True, font='Trebuchet MS', color=GREEN)
sg = ['Skin pinch goes back normally', 'Thirst has gone', 'Urine has been passed', 'Pulse is strong']
for i, t in enumerate(sg):
    y = 2.05 + i * 1.2
    circle_num(s, 8.6, y, 0.85, GREEN, '\u2713', 28)
    b = box(s, 9.6, y, 3.2, 0.85, tint(GREEN, .8), line=GREEN, lw=2, radius=0.3)
    tx(
Editing File

~/cholera/build.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/cholera/build.py'
Running Command

cd /tmp/workspace/cholera && python build.py 2>&1 | tail -40

Running Command

cd /tmp/workspace/cholera && python - <<'EOF' p='build.py' t=open(p).read() t=t.replace("Inches(rowh * len(rows)))","Inches(sum(rowh) if isinstance(rowh, list) else rowh * len(rows)))") open(p,'w').write(t) EOF python build.py 2>&1 | tail -40

Running Command

cd /tmp/workspace/cholera && python - <<'EOF' p='build.py' t=open(p).read() t=t.replace(" if shape is None:\n shape = s.shapes.add_textbox"," if shape is not None and w == 0:\n w = shape.width / 914400; h = shape.height / 914400\n if shape is None:\n shape = s.shapes.add_textbox",1) open(p,'w').write(t) EOF python build.py 2>&1 | tail -40

Running Command

cd /tmp/workspace/cholera && python - <<'EOF' p='build.py' t=open(p).read() reps=[("tx(s, 0.7, 4.7, 6.0, 0.6, 'Clinical meeting | Rehydrate fast, save lives', size=20","tx(s, 0.7, 4.7, 6.0, 0.8, 'Clinical meeting | Rehydrate fast, save lives', size=18"), ("tx(s, 6.9, 6.7, 5.9, 0.4, 'Biotype El Tor, share of all infections. Severe cases are 5-10% of symptomatic patients.', size=12","tx(s, 6.9, 6.6, 5.9, 0.55, 'Biotype El Tor, share of all infections. Severe cases are 5-10% of symptomatic patients.', size=12"), ("rehydration with rapid dehydration in an outbreak setting: think cholera, treat as cholera.', size=15","rehydration with rapid dehydration in an outbreak setting: think cholera, treat as cholera.', size=14"), ("'Adequately rehydrated when...', size=19","'Adequately rehydrated when...', size=17")] for a,b in reps: if a not in t: print('missing',a[:40]) t=t.replace(a,b) t=t.replace("Profuse rice-water stool with rapid dehydration in an outbreak setting: think cholera, treat as cholera.', size=15","Profuse rice-water stool with rapid dehydration in an outbreak setting: think cholera, treat as cholera.', size=14") open(p,'w').write(t) EOF python build.py 2>&1 | tail; ls -la Cholera_Outbreak_Clinical_Meeting.pptx python - <<'EOF' from pptx import Presentation p=Presentation('/tmp/workspace/cholera/Cholera_Outbreak_Clinical_Meeting.pptx') for i,s in enumerate(p.slides,1): t=[sh.text_frame.text for sh in s.shapes if sh.has_text_frame and sh.text_frame.text.strip()] print(i,t[0][:50] if t else '') EOF

I've built a 25-slide cholera deck for your clinical meeting. I couldn't render it to images here, so I haven't seen how it looks. Please flick through it before the meeting, especially the denser slides (17 to 24), for any text that runs over its box.

Cholera Outbreak Clinical Meeting

Presentation · PPTX

Design: bright teal, coral, sunny yellow and purple, with colour-coded cards, chevron flows and a native doughnut chart. Four cartoon illustrations (the bacterium villain, the doctor handing a child ORS, hand washing and clean water, and a dehydrated patient) are AI-generated. Speaker notes are on most slides.
Flow of the 25 slides:
  1. Title
  2. Outbreak picture
  3. Key facts
  4. The organism Vibrio cholerae
  5. Breaking the chain of death
  6. Pathogenesis
  7. Spectrum of illness
  8. Case definitions
  9. Clinical presentation
  10. Cholera gravis
  11. Differential diagnosis
  12. Dehydration assessment
  13. Why people die, with community and facility death definitions
  14. Triage and the ABCD approach
  15. Plans A, B and C overview
  16. ORS
  17. Quick-reference charts
  18. Plan C IV fluids
  19. Monitoring and signs of rehydration
  20. Complications
  21. Antibiotics
  22. Referral decision tree
  23. Discharge criteria
  24. Prevention and control
  25. Take-home messages and questions
Images taken from your deck: the rice-water stool photo, the cholera gravis patient, the Plan A/B and Plan C charts, the ABCD emergency signs graphic, the mother-and-child ORS photos, the Lusaka resistance pie charts and the question-mark image.
Content I added beyond your deck. Please check these:
  • Slide 2 numbers: these come from a WHO African Region risk assessment. It reports 160,799 cases and 2,466 deaths, a 1.53% case fatality ratio, across 19 countries, to 20 September 2026. I read these from a search snippet, not the full document. The yellow box on that slide is a placeholder for your local cases, deaths and hotspots.
  • Slide 16 ORS table: your deck gives the older standard WHO ORS composition. I added the current reduced-osmolarity formula from memory, not from a source I checked. Please confirm those figures.
  • Slide 21: the children's azithromycin dose (20 mg/kg single dose, maximum 1 g) is from my memory of GTFCC guidance. It is not in your deck, so please verify it. The adult and pregnancy regimens are from your deck.
  • Slide 24 chlorine strengths: the figures (0.05% for hands, 0.2% for surfaces, 2% for stool, vomit and bodies) are also from memory of GTFCC guidance.
  • Slide 24 vaccine: the vaccine data (20 million preventive doses allocated in February 2026, record reactive use in 2025) are from the WHO cholera fact sheet.
  • Slide 24 notes: they point to two recent systematic reviews on killed whole-cell vaccines, a Cochrane review (PMID 38197546) and a Lancet Global Health review (PMID 40580988). I did not read their full text, so the slide does not state their conclusions.
  • Textbook support: I checked the fluid-first approach and the doxycycline 300 mg single-dose regimen against Goldman-Cecil and Park's textbook.
Slides I couldn't read from your deck: several of your slides (testing methods, the identification slide, the admission criteria) hold images or graphics that I couldn't read. I wrote slide 8 (testing note) and slide 23 (discharge) from the text I could extract. Slide 14's history list is my own addition, so check them against your originals.
This is a shared conversation. Sign in to Orris to start your own chat.