PowerPoint presentation on DKA with focus on management for postgraduate internal medicine students use a light colored theme for the design
mkdir -p /tmp/workspace/dka-presentation && ls /tmp/workspace/
~/dka-presentation/build_dka.py
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 pptx.util import Inches, Pt
from io import BytesIO
# ─── COLOUR PALETTE (light theme) ───────────────────────────────────────────
C_BG = RGBColor(0xF4, 0xF7, 0xFB) # very pale blue-grey background
C_HEADER_BG = RGBColor(0x1A, 0x57, 0x9E) # deep steel-blue header band
C_ACCENT = RGBColor(0x2E, 0x86, 0xC1) # mid-blue accent
C_ACCENT2 = RGBColor(0xE8, 0xF4, 0xFD) # pale blue fill for boxes
C_TEXT_DARK = RGBColor(0x1A, 0x25, 0x3A) # near-black text
C_TEXT_WHITE= RGBColor(0xFF, 0xFF, 0xFF) # white
C_DIVIDER = RGBColor(0x2E, 0x86, 0xC1) # blue divider line
C_BOX_ORANGE= RGBColor(0xFF, 0xA5, 0x00) # amber accent for warnings
C_BOX_RED = RGBColor(0xE7, 0x4C, 0x3C) # red for danger/severe
C_BOX_GREEN = RGBColor(0x27, 0xAE, 0x60) # green for resolution criteria
C_LIGHT_GREY= RGBColor(0xEC, 0xF0, 0xF1) # light grey for table alt rows
C_TABLE_HEAD= RGBColor(0x1A, 0x57, 0x9E) # table header = header blue
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
blank = prs.slide_layouts[6]
# ─── HELPERS ────────────────────────────────────────────────────────────────
def add_rect(slide, left, top, width, height, fill_color=None, line_color=None, line_width_pt=0):
from pptx.util import Pt as _Pt
shape = slide.shapes.add_shape(
1, # MSO_SHAPE_TYPE.RECTANGLE
Inches(left), Inches(top), Inches(width), Inches(height)
)
fill = shape.fill
if fill_color:
fill.solid()
fill.fore_color.rgb = fill_color
else:
fill.background()
line = shape.line
if line_color:
line.color.rgb = line_color
line.width = Pt(line_width_pt)
else:
line.fill.background()
return shape
def add_text(slide, text, left, top, width, height,
font_name="Calibri", font_size=14, bold=False, italic=False,
color=C_TEXT_DARK, align=PP_ALIGN.LEFT, v_anchor=MSO_ANCHOR.TOP,
word_wrap=True, margin_l=0.06, margin_t=0.04):
tb = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
tf = tb.text_frame
tf.word_wrap = word_wrap
tf.vertical_anchor = v_anchor
tf.margin_left = Inches(margin_l)
tf.margin_right = Inches(0.04)
tf.margin_top = Inches(margin_t)
tf.margin_bottom= Inches(0.02)
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_text(slide, items, left, top, width, height,
font_name="Calibri", font_size=13, color=C_TEXT_DARK,
bold_first=False, line_spacing_pt=None):
"""items: list of (indent_level, text) or plain strings."""
tb = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
tf = tb.text_frame
tf.word_wrap = True
tf.margin_left = Inches(0.08)
tf.margin_right = Inches(0.04)
tf.margin_top = Inches(0.04)
tf.margin_bottom= Inches(0.02)
from pptx.util import Pt as _Pt
from pptx.oxml.ns import qn
from lxml import etree
first = True
for item in items:
if isinstance(item, str):
lvl, text = 0, item
else:
lvl, text = item
if first:
p = tf.paragraphs[0]
first = False
else:
p = tf.add_paragraph()
p.level = lvl
if line_spacing_pt:
p.line_spacing = _Pt(line_spacing_pt)
# bullet glyph
pPr = p._pPr if p._pPr is not None else p._p.get_or_add_pPr()
buChar = etree.SubElement(pPr, qn('a:buChar'))
buChar.set('char', '•' if lvl == 0 else '–')
r = p.add_run()
r.text = text
r.font.name = font_name
r.font.size = _Pt(font_size - lvl * 1)
r.font.bold = bold_first and (text == items[0] if isinstance(items[0], str) else False)
r.font.color.rgb = color
return tb
def slide_background(slide, color=C_BG):
bg = slide.background
fill = bg.fill
fill.solid()
fill.fore_color.rgb = color
def add_header_band(slide, title, subtitle=None):
"""Blue header band at top."""
add_rect(slide, 0, 0, 13.333, 1.1, fill_color=C_HEADER_BG)
# top accent stripe
add_rect(slide, 0, 0, 13.333, 0.07, fill_color=C_ACCENT)
add_text(slide, title, 0.35, 0.05, 12.5, 0.65,
font_size=28, bold=True, color=C_TEXT_WHITE,
align=PP_ALIGN.LEFT, v_anchor=MSO_ANCHOR.MIDDLE)
if subtitle:
add_text(slide, subtitle, 0.35, 0.65, 12.5, 0.4,
font_size=14, italic=True, color=RGBColor(0xBE, 0xD9, 0xF5),
align=PP_ALIGN.LEFT)
def add_section_label(slide, text, left, top, width=3.5, color=C_ACCENT):
add_rect(slide, left, top, width, 0.32, fill_color=color)
add_text(slide, text, left+0.08, top, width-0.1, 0.32,
font_size=11, bold=True, color=C_TEXT_WHITE,
align=PP_ALIGN.LEFT, v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.01)
def add_info_box(slide, title, items, left, top, width, height,
title_color=C_ACCENT, box_color=C_ACCENT2, border_color=C_ACCENT,
font_size=12):
add_rect(slide, left, top, width, height,
fill_color=box_color, line_color=border_color, line_width_pt=1.2)
add_rect(slide, left, top, width, 0.3, fill_color=title_color)
add_text(slide, title, left+0.1, top, width-0.15, 0.3,
font_size=11, bold=True, color=C_TEXT_WHITE,
v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.01)
add_bullet_text(slide, items, left+0.08, top+0.33, width-0.2, height-0.38,
font_size=font_size, color=C_TEXT_DARK)
def add_page_number(slide, n, total):
add_text(slide, f"{n} / {total}", 12.5, 7.2, 0.8, 0.25,
font_size=9, color=RGBColor(0x9B, 0xA0, 0xAA), align=PP_ALIGN.RIGHT)
# ─── SLIDE BUILDER ──────────────────────────────────────────────────────────
TOTAL = 16 # will update
# ── SLIDE 1 Title ────────────────────────────────────────────────────────
def slide_title(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
# big blue panel left
add_rect(slide, 0, 0, 6.0, 7.5, fill_color=C_HEADER_BG)
add_rect(slide, 0, 0, 6.0, 0.12, fill_color=C_BOX_ORANGE)
add_rect(slide, 0, 7.38, 6.0, 0.12, fill_color=C_BOX_ORANGE)
add_text(slide, "DIABETIC\nKETOACIDOSIS", 0.3, 1.2, 5.4, 3.0,
font_size=44, bold=True, color=C_TEXT_WHITE,
align=PP_ALIGN.LEFT, v_anchor=MSO_ANCHOR.MIDDLE)
add_text(slide, "Pathophysiology, Diagnosis & Management",
0.3, 4.0, 5.4, 0.8,
font_size=18, italic=True, color=RGBColor(0xBE, 0xD9, 0xF5),
align=PP_ALIGN.LEFT)
add_text(slide, "Postgraduate Internal Medicine | August 2026",
0.3, 4.9, 5.4, 0.5,
font_size=12, color=RGBColor(0x90, 0xB8, 0xD8))
# right side
add_text(slide, "Key Focus Areas", 6.5, 1.2, 6.5, 0.4,
font_size=18, bold=True, color=C_ACCENT)
topics = [
"Pathophysiology of DKA",
"Diagnostic criteria & severity classification",
"Precipitating factors",
"Fluid resuscitation protocols",
"Insulin therapy",
"Electrolyte management (K⁺, phosphate, bicarbonate)",
"Monitoring & endpoints of treatment",
"Complications & prevention",
"Special scenarios (SGLT-2i, pregnancy, euglycaemic DKA)",
]
add_bullet_text(slide, topics, 6.5, 1.7, 6.5, 5.5,
font_size=13.5, color=C_TEXT_DARK)
add_page_number(slide, 1, TOTAL)
# ── SLIDE 2 Overview / Epidemiology ─────────────────────────────────────
def slide_overview(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Overview & Epidemiology")
# 3 stat boxes
boxes = [
("~30%", "of T1DM patients experience\nDKA at some point"),
("~0.4%", "mortality in experienced\ncentres (up to 5–10% globally)"),
("3–5 L", "average fluid deficit\nat presentation"),
]
for i, (stat, desc) in enumerate(boxes):
lft = 0.4 + i * 4.3
add_rect(slide, lft, 1.25, 3.8, 1.5, fill_color=C_ACCENT2, line_color=C_ACCENT, line_width_pt=1.5)
add_text(slide, stat, lft, 1.35, 3.8, 0.7,
font_size=34, bold=True, color=C_ACCENT, align=PP_ALIGN.CENTER)
add_text(slide, desc, lft, 2.0, 3.8, 0.65,
font_size=12, color=C_TEXT_DARK, align=PP_ALIGN.CENTER)
# definition box
add_rect(slide, 0.4, 3.0, 12.5, 0.95, fill_color=RGBColor(0xFF,0xF3,0xCD), line_color=C_BOX_ORANGE, line_width_pt=1.5)
add_text(slide, "Definition: DKA is a life-threatening metabolic emergency characterised by the triad of hyperglycaemia (glucose >11 mmol/L), "
"ketonaemia (β-hydroxybutyrate >3.0 mmol/L), and metabolic acidosis (pH <7.3, HCO₃ <15 mmol/L) resulting from absolute or relative insulin deficiency.",
0.5, 3.05, 12.2, 0.85, font_size=12.5, color=C_TEXT_DARK)
# key facts
add_section_label(slide, "EPIDEMIOLOGY", 0.4, 4.1)
pts = [
"More common in T1DM but occurs in T2DM (~30% of episodes in some series)",
"Incidence of DKA is rising worldwide; reasons unclear",
"Leading cause of death in young patients with T1DM",
"DKA at T1DM diagnosis is common in children & adolescents",
"SGLT-2 inhibitor-associated euglycaemic DKA increasingly recognised",
]
add_bullet_text(slide, pts, 0.4, 4.5, 12.5, 2.7, font_size=12.5)
add_page_number(slide, 2, TOTAL)
# ── SLIDE 3 Pathophysiology ──────────────────────────────────────────────
def slide_patho(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Pathophysiology")
# central box
add_rect(slide, 4.8, 1.3, 3.7, 0.65, fill_color=C_BOX_RED)
add_text(slide, "↓ INSULIN + ↑ COUNTER-REGULATORY HORMONES\n(glucagon, cortisol, catecholamines, GH)",
4.82, 1.32, 3.66, 0.62,
font_size=10.5, bold=True, color=C_TEXT_WHITE, align=PP_ALIGN.CENTER)
# Three consequence columns
cols = [
("HYPERGLYCAEMIA", C_ACCENT, [
"↑ Glycogenolysis",
"↑ Gluconeogenesis",
"↓ Peripheral glucose uptake",
"Osmotic diuresis → dehydration",
"Electrolyte loss (Na⁺, K⁺, PO₄³⁻, Mg²⁺)",
]),
("KETOGENESIS / ACIDOSIS", RGBColor(0xD3, 0x54, 0x00), [
"↑ Lipolysis → ↑ Free fatty acids",
"Hepatic β-oxidation → ketone bodies",
"Acetoacetate & β-hydroxybutyrate",
"Anion-gap metabolic acidosis",
"Kussmaul breathing (compensation)",
]),
("DEHYDRATION / ELECTROLYTES", RGBColor(0x14, 0x75, 0x5E), [
"Total body K⁺ depleted (shift out with acidosis)",
"Total body phosphate depleted",
"Serum K⁺ may appear normal/high",
"Na⁺ often low (dilutional)",
"Severe fluid deficit: 3–5 L",
]),
]
for i, (title, col, pts) in enumerate(cols):
lft = 0.35 + i * 4.32
add_rect(slide, lft, 2.1, 4.0, 0.38, fill_color=col)
add_text(slide, title, lft+0.08, 2.1, 3.84, 0.38,
font_size=11, bold=True, color=C_TEXT_WHITE,
v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
add_rect(slide, lft, 2.48, 4.0, 2.8, fill_color=C_ACCENT2, line_color=col, line_width_pt=1)
add_bullet_text(slide, pts, lft+0.1, 2.52, 3.8, 2.7, font_size=12.5, color=C_TEXT_DARK)
# bottom note
add_rect(slide, 0.35, 5.42, 12.6, 0.45, fill_color=RGBColor(0xFD,0xED,0xEC), line_color=C_BOX_RED, line_width_pt=1)
add_text(slide, "Key insight: Serum K⁺ at presentation may be NORMAL or HIGH despite severe total body K⁺ depletion — insulin therapy will drive K⁺ intracellularly and can precipitate life-threatening hypokalaemia.",
0.45, 5.44, 12.4, 0.42, font_size=11.5, bold=False, color=C_BOX_RED)
add_page_number(slide, 3, TOTAL)
# ── SLIDE 4 Precipitating Factors ────────────────────────────────────────
def slide_precip(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Precipitating Factors — The '6 I's'")
cats = [
("Infection", C_BOX_RED,
["Pneumonia, UTI, sepsis", "Most common precipitant (~40%)", "Fever may be absent in DKA"]),
("Insulin omission", C_ACCENT,
["Non-compliance with insulin", "Pump failure / infusion set problem", "Deliberate omission (diabulimia)"]),
("Ischaemia / Infarction", RGBColor(0x84, 0x27, 0x93),
["Myocardial infarction", "Cerebrovascular event", "Mesenteric ischaemia"]),
("Intoxication / Drugs", RGBColor(0xD3, 0x54, 0x00),
["Cocaine, alcohol", "Corticosteroids", "Atypical antipsychotics, SGLT-2i"]),
("New-onset T1DM", RGBColor(0x14, 0x75, 0x5E),
["DKA as first presentation", "Esp. in children & young adults", "HbA1c normal/slightly elevated"]),
("Other / Pregnancy", RGBColor(0x6C, 0x35, 0x83),
["Pancreatitis", "Trauma, surgery, stress", "Pregnancy (T1DM & gestational)"]),
]
for i, (title, col, pts) in enumerate(cats):
row, c = divmod(i, 3)
lft = 0.35 + c * 4.32
top = 1.25 + row * 2.85
add_rect(slide, lft, top, 4.0, 0.38, fill_color=col)
add_text(slide, title, lft+0.08, top, 3.84, 0.38,
font_size=12, bold=True, color=C_TEXT_WHITE, v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
add_rect(slide, lft, top+0.38, 4.0, 2.1, fill_color=C_ACCENT2, line_color=col, line_width_pt=1)
add_bullet_text(slide, pts, lft+0.1, top+0.42, 3.8, 2.0, font_size=12.5)
add_page_number(slide, 4, TOTAL)
# ── SLIDE 5 Clinical Features ───────────────────────────────────────────
def slide_clinical(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Clinical Features")
# left: symptoms
add_info_box(slide, "SYMPTOMS", [
"Polyuria, polydipsia",
"Nausea, vomiting",
"Abdominal pain (may mimic acute abdomen)",
"Weakness, fatigue",
"Altered consciousness (severe DKA)",
], 0.35, 1.25, 4.0, 3.5)
# mid: signs
add_info_box(slide, "PHYSICAL SIGNS", [
"Tachycardia",
"Hypotension / dehydration",
"Kussmaul respirations (deep, rapid)",
"Fruity / acetone breath",
"Abdominal tenderness",
"Reduced consciousness / coma",
"Signs of precipitating illness",
], 4.7, 1.25, 4.0, 3.5)
# right: investigations
add_info_box(slide, "IMMEDIATE INVESTIGATIONS", [
"Blood glucose (fingerprick + lab)",
"Serum/blood ketones (β-OHB preferred)",
"U&E, creatinine, osmolality",
"ABG / VBG (pH, HCO₃, pCO₂)",
"FBC, CRP, blood cultures",
"ECG (peaked T-waves if hyperkalaemia)",
"CXR, urine dipstick & MSU",
], 9.05, 1.25, 4.0, 3.5)
# bottom anion-gap formula
add_rect(slide, 0.35, 4.9, 12.6, 0.7, fill_color=C_ACCENT2, line_color=C_ACCENT, line_width_pt=1.2)
add_text(slide, "Anion Gap = Na⁺ – (Cl⁻ + HCO₃⁻) Normal: 8–12 mEq/L DKA: typically >16 mEq/L (elevated AG metabolic acidosis)",
0.5, 4.92, 12.3, 0.66, font_size=13, bold=False, color=C_TEXT_DARK, align=PP_ALIGN.CENTER)
# corrected Na formula
add_rect(slide, 0.35, 5.68, 12.6, 0.55, fill_color=RGBColor(0xFF,0xF3,0xCD), line_color=C_BOX_ORANGE, line_width_pt=1)
add_text(slide, "Corrected Na⁺ = Measured Na⁺ + 2.4 × [(Glucose mg/dL – 100) / 100] | Effective Osmolality = 2×Na⁺ + Glucose/18",
0.5, 5.7, 12.3, 0.52, font_size=12, color=C_TEXT_DARK, align=PP_ALIGN.CENTER)
add_page_number(slide, 5, TOTAL)
# ── SLIDE 6 Severity Classification ─────────────────────────────────────
def slide_severity(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Severity Classification of DKA")
# table
headers = ["Parameter", "MILD", "MODERATE", "SEVERE"]
rows = [
["Blood glucose", ">250 mg/dL (>13.9 mmol/L)", ">250 mg/dL", ">250 mg/dL"],
["Arterial pH", "7.25 – 7.30", "7.00 – 7.24", "< 7.00"],
["Serum HCO₃", "15 – 18 mEq/L", "10 – 14 mEq/L", "< 10 mEq/L"],
["Urine/serum ketones", "Positive", "Positive", "Positive"],
["β-Hydroxybutyrate", "> 3.0 mmol/L", "> 3.0 mmol/L", "> 3.0 mmol/L"],
["Anion gap", "> 10", "> 12", "> 12"],
["Mental status", "Alert", "Alert / drowsy", "Stupor / coma"],
]
col_widths = [2.6, 2.8, 2.8, 2.8]
row_height = 0.52
tbl_left = 0.55
tbl_top = 1.25
header_colors = [C_HEADER_BG, C_ACCENT, RGBColor(0xD3,0x54,0x00), C_BOX_RED]
# header row
for j, (hdr, w, col) in enumerate(zip(headers, col_widths, header_colors)):
left = tbl_left + sum(col_widths[:j])
add_rect(slide, left, tbl_top, w, row_height, fill_color=col)
add_text(slide, hdr, left+0.05, tbl_top, w-0.05, row_height,
font_size=12, bold=True, color=C_TEXT_WHITE,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
# data rows
for i, row in enumerate(rows):
row_top = tbl_top + (i+1) * row_height
bg = C_LIGHT_GREY if i % 2 == 0 else C_TEXT_WHITE
for j, (cell, w) in enumerate(zip(row, col_widths)):
left = tbl_left + sum(col_widths[:j])
add_rect(slide, left, row_top, w, row_height,
fill_color=bg, line_color=RGBColor(0xCC,0xDD,0xEE), line_width_pt=0.5)
bold = j == 0
add_text(slide, cell, left+0.05, row_top, w-0.05, row_height,
font_size=11.5, bold=bold, color=C_TEXT_DARK,
align=PP_ALIGN.CENTER if j > 0 else PP_ALIGN.LEFT,
v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
# note
add_rect(slide, 0.55, 5.05, 12.4, 0.55, fill_color=RGBColor(0xFD,0xED,0xEC), line_color=C_BOX_RED, line_width_pt=1)
add_text(slide, "Note: ADA/Endocrine Society criteria. DKA + HHS may coexist (up to one-third of patients). "
"Euglycaemic DKA (SGLT-2i): glucose <250 mg/dL with pH <7.3 and ketonaemia.",
0.65, 5.07, 12.2, 0.52, font_size=11.5, color=C_BOX_RED)
add_page_number(slide, 6, TOTAL)
# ── SLIDE 7 Management Overview ─────────────────────────────────────────
def slide_mgmt_overview(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Management Overview — The 5 Pillars")
pillars = [
("1\nFLUIDS", C_ACCENT,
"IV fluid resuscitation\nRestore circulating volume\nCorrect dehydration over 24–48 h"),
("2\nINSULIN", RGBColor(0x14, 0x75, 0x5E),
"IV regular insulin infusion\n0.1 U/kg/h (after K⁺ ≥3.5 mmol/L)\nStop ketogenesis"),
("3\nPOTASSIUM", RGBColor(0xD3, 0x54, 0x00),
"Replace K⁺ before starting insulin\nTarget 4.0–5.0 mmol/L\nContinuous monitoring"),
("4\nMONITOR", RGBColor(0x84, 0x27, 0x93),
"Hourly glucose\n1–2 hourly ketones & VBG\nFluid balance, ECG"),
("5\nPRECIPITANT", RGBColor(0x6C, 0x35, 0x83),
"Identify & treat trigger\nAntibiotics if infection\nHold SGLT-2i; review insulin regimen"),
]
for i, (label, col, desc) in enumerate(pillars):
lft = 0.35 + i * 2.58
# circle-like square
add_rect(slide, lft, 1.3, 2.35, 1.05, fill_color=col)
add_text(slide, label, lft, 1.3, 2.35, 1.05,
font_size=18, bold=True, color=C_TEXT_WHITE,
align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
add_rect(slide, lft, 2.35, 2.35, 3.5, fill_color=C_ACCENT2, line_color=col, line_width_pt=1.2)
add_text(slide, desc, lft+0.1, 2.5, 2.2, 3.2,
font_size=12.5, color=C_TEXT_DARK, v_anchor=MSO_ANCHOR.TOP)
add_rect(slide, 0.35, 6.0, 12.6, 0.5, fill_color=RGBColor(0xFF,0xF3,0xCD), line_color=C_BOX_ORANGE, line_width_pt=1)
add_text(slide, "GOLDEN RULE: Do NOT start insulin if K⁺ < 3.3 mmol/L. Replete potassium first to avoid fatal arrhythmia.",
0.5, 6.02, 12.3, 0.48, font_size=13, bold=True, color=RGBColor(0x7D,0x3C,0x00), align=PP_ALIGN.CENTER)
add_page_number(slide, 7, TOTAL)
# ── SLIDE 8 Fluid Therapy ───────────────────────────────────────────────
def slide_fluids(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Fluid Resuscitation")
add_info_box(slide, "INITIAL RESUSCITATION (1st hour)", [
"If haemodynamic shock: NS 0.9% or Ringer's Lactate bolus — as fast as possible",
"If no shock: NS 0.9% 1 L over 1st hour",
"Bolus 20 mL/kg in children",
"Ringer's Lactate associated with faster DKA resolution & less hyperchloraemia",
], 0.35, 1.25, 6.0, 2.6, font_size=12.5)
add_info_box(slide, "SUBSEQUENT FLUIDS (hours 2–24)", [
"After 1st hour: switch to 0.45% NaCl at 150–500 mL/h depending on fluid status",
"Correct total deficit (~3–5 L) over 24–48 h",
"Switch to 5% dextrose + 0.45% NaCl when glucose reaches 200–250 mg/dL",
"Continue insulin infusion even after glucose falls (to clear ketones)",
], 6.7, 1.25, 6.3, 2.6, font_size=12.5)
add_info_box(slide, "SPECIAL CONSIDERATIONS", [
"Elderly / cardiac disease: cautious fluid replacement; monitor for pulmonary oedema",
"Children: avoid rapid large fluid boluses — risk of cerebral oedema",
"Aim urine output 0.5–1 mL/kg/h",
"Avoid large volumes of 0.9% NaCl — hyperchloraemic acidosis may worsen apparent acidosis",
], 0.35, 4.05, 6.0, 2.8, font_size=12.5, title_color=RGBColor(0x14, 0x75, 0x5E), border_color=RGBColor(0x14, 0x75, 0x5E))
add_info_box(slide, "ENDPOINTS OF FLUID THERAPY", [
"Haemodynamic stability (HR, BP normalised)",
"Urine output >0.5 mL/kg/h",
"Clinical signs of dehydration resolving",
"Transition to oral intake when tolerating",
], 6.7, 4.05, 6.3, 2.8, font_size=12.5, title_color=RGBColor(0xD3, 0x54, 0x00), border_color=RGBColor(0xD3, 0x54, 0x00))
add_page_number(slide, 8, TOTAL)
# ── SLIDE 9 Insulin Therapy ─────────────────────────────────────────────
def slide_insulin(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Insulin Therapy")
add_info_box(slide, "STARTING INSULIN", [
"Check K⁺ BEFORE starting insulin",
"If K⁺ < 3.3 mmol/L: DO NOT start insulin — replete K⁺ first",
"If K⁺ ≥ 3.3 mmol/L: start insulin infusion",
"IV regular insulin bolus: 0.1 U/kg then infusion 0.1 U/kg/h",
"Alternative: no bolus + infusion 0.14 U/kg/h (ADA 2023)",
], 0.35, 1.25, 6.0, 3.2, font_size=12.5)
add_info_box(slide, "ADJUSTING THE INFUSION", [
"Target glucose fall: 50–75 mg/dL (2.8–4.2 mmol/L) per hour",
"If glucose falls <50 mg/dL/h in first hour: double insulin rate",
"When glucose reaches 200–250 mg/dL: add 5% dextrose to IV fluids",
"Reduce insulin infusion to 0.02–0.05 U/kg/h once glucose <200 mg/dL",
"Do NOT stop insulin until ketones cleared (pH >7.3, HCO₃ >18, AG normal)",
], 6.7, 1.25, 6.3, 3.2, font_size=12.5)
add_info_box(slide, "TRANSITION TO SUBCUTANEOUS INSULIN", [
"Switch to SC insulin when: pH >7.3, HCO₃ >18 mmol/L, AG normalised, patient tolerating orally",
"Overlap SC long-acting insulin by 2–4 h before stopping IV infusion",
"Restart usual SC insulin regimen (or initiate for new T1DM)",
"Risk of rebound ketosis if IV insulin stopped prematurely",
], 0.35, 4.6, 12.6, 2.7, font_size=12.5,
title_color=RGBColor(0x14, 0x75, 0x5E), border_color=RGBColor(0x14, 0x75, 0x5E))
add_page_number(slide, 9, TOTAL)
# ── SLIDE 10 Potassium & Electrolytes ───────────────────────────────────
def slide_electrolytes(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Electrolyte Management")
# Potassium table
add_rect(slide, 0.35, 1.25, 5.8, 0.35, fill_color=C_HEADER_BG)
add_text(slide, "POTASSIUM REPLACEMENT PROTOCOL (ADA)", 0.45, 1.25, 5.6, 0.35,
font_size=11, bold=True, color=C_TEXT_WHITE, v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
k_rows = [
("K⁺ < 3.3 mmol/L", "HOLD INSULIN — Replace K⁺ 40 mEq/h IV. Recheck hourly until K⁺ ≥ 3.3", C_BOX_RED),
("K⁺ 3.3 – 5.5 mmol/L", "Start insulin + add 20–40 mEq KCl per litre of IV fluid. Target K⁺ 4–5 mmol/L", C_BOX_ORANGE),
("K⁺ > 5.5 mmol/L", "Start insulin but NO potassium supplementation. Recheck K⁺ every 2 hours", RGBColor(0x14, 0x75, 0x5E)),
]
for i, (label, action, col) in enumerate(k_rows):
top = 1.6 + i * 0.65
add_rect(slide, 0.35, top, 2.1, 0.6, fill_color=col)
add_text(slide, label, 0.4, top, 2.0, 0.6, font_size=11, bold=True, color=C_TEXT_WHITE,
v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
add_rect(slide, 2.45, top, 3.7, 0.6, fill_color=C_ACCENT2, line_color=col, line_width_pt=1)
add_text(slide, action, 2.5, top, 3.6, 0.6, font_size=10.5, color=C_TEXT_DARK,
v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
# Phosphate
add_info_box(slide, "PHOSPHATE", [
"Severe hypophosphataemia (<1.0 mg/dL): replace with potassium phosphate",
"Routine replacement NOT recommended (no outcome benefit demonstrated)",
"May worsen hypocalcaemia if given aggressively",
], 6.5, 1.25, 6.5, 2.0, font_size=12, title_color=RGBColor(0xD3, 0x54, 0x00), border_color=RGBColor(0xD3, 0x54, 0x00))
# Bicarbonate
add_info_box(slide, "BICARBONATE — GENERALLY NOT RECOMMENDED", [
"No RCT evidence of benefit; may paradoxically worsen CNS acidosis",
"Consider ONLY if: pH < 6.9 or haemodynamic instability despite resuscitation",
"If given: 100 mEq NaHCO₃ over 2 h with 20 mEq KCl; recheck pH after",
], 6.5, 3.4, 6.5, 2.0, font_size=12, title_color=C_BOX_RED, border_color=C_BOX_RED)
# Magnesium / other
add_info_box(slide, "MAGNESIUM & SODIUM", [
"Mg²⁺ depletion common — replace if symptomatic or <0.6 mmol/L",
"Sodium: monitor corrected Na⁺; hypernatraemia may indicate excessive free water loss",
"Chloride: avoid hyperchloraemia with normal saline; consider balanced crystalloid",
], 0.35, 3.65, 5.8, 2.35, font_size=12)
add_page_number(slide, 10, TOTAL)
# ── SLIDE 11 Monitoring & Targets ───────────────────────────────────────
def slide_monitoring(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Monitoring & Treatment Targets")
# monitoring frequency table
add_rect(slide, 0.35, 1.25, 7.5, 0.38, fill_color=C_HEADER_BG)
add_text(slide, "MONITORING FREQUENCY", 0.45, 1.25, 7.3, 0.38,
font_size=12, bold=True, color=C_TEXT_WHITE, v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
mon_rows = [
("Blood glucose", "Every 1 hour"),
("Blood/urine ketones (β-OHB preferred)", "Every 1–2 hours"),
("VBG (pH, HCO₃, K⁺)", "Every 2 hours initially"),
("Serum electrolytes (K⁺, Na⁺, Cl⁻)", "Every 2–4 hours"),
("Fluid balance (input/output)", "Hourly"),
("ECG", "On admission; repeat if K⁺ abnormal"),
("Vital signs (BP, HR, RR, SpO₂, GCS)", "Every 30–60 minutes"),
]
for i, (test, freq) in enumerate(mon_rows):
top = 1.63 + i * 0.5
bg = C_LIGHT_GREY if i % 2 == 0 else C_TEXT_WHITE
add_rect(slide, 0.35, top, 4.8, 0.5, fill_color=bg, line_color=RGBColor(0xCC,0xDD,0xEE), line_width_pt=0.5)
add_rect(slide, 5.15, top, 2.7, 0.5, fill_color=bg, line_color=RGBColor(0xCC,0xDD,0xEE), line_width_pt=0.5)
add_text(slide, test, 0.45, top, 4.65, 0.5, font_size=11.5, color=C_TEXT_DARK, v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
add_text(slide, freq, 5.2, top, 2.6, 0.5, font_size=11.5, color=C_TEXT_DARK, v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
# resolution criteria
add_info_box(slide, "RESOLUTION CRITERIA (all 3 must be met)", [
"Blood glucose < 200 mg/dL (11.1 mmol/L)",
"Serum HCO₃ ≥ 18 mEq/L",
"Venous pH > 7.3",
"Anion gap normalised (≤12 mEq/L)",
"Serum/blood ketones clearing (β-OHB < 0.5 mmol/L)",
], 8.3, 1.25, 4.7, 3.6, title_color=C_BOX_GREEN, border_color=C_BOX_GREEN, font_size=12.5)
add_info_box(slide, "IMPORTANT PITFALLS", [
"Pseudonormoglycaemia in SGLT-2i DKA",
"Bicarbonate lag behind pH during resolution",
"Premature insulin cessation → rebound ketosis",
"Overlooking concurrent illness (MI, sepsis)",
], 8.3, 5.0, 4.7, 2.0, title_color=C_BOX_RED, border_color=C_BOX_RED, font_size=12.5)
add_page_number(slide, 11, TOTAL)
# ── SLIDE 12 Complications ──────────────────────────────────────────────
def slide_complications(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Complications of DKA & Its Treatment")
comp = [
("Cerebral Oedema", C_BOX_RED, [
"Most feared complication — especially in children",
"Risk: rapid fluid shifts, excess hypotonic fluid, insulin-induced glucose fall",
"Features: headache, altered consciousness, papilloedema, bradycardia",
"Treatment: mannitol 0.5–1 g/kg IV or hypertonic saline; reduce fluids",
]),
("Hypokalaemia", RGBColor(0xD3, 0x54, 0x00), [
"Common after insulin + fluid therapy",
"Can cause fatal ventricular arrhythmias",
"Prevention: K⁺ replacement protocol (see slide 10)",
"ECG monitoring essential",
]),
("Hypoglycaemia", C_ACCENT, [
"From over-aggressive insulin without dextrose",
"Prevent by adding dextrose when glucose <200 mg/dL",
"Do not stop insulin — reduce rate; continue dextrose",
]),
("Aspiration Pneumonia", RGBColor(0x6C, 0x35, 0x83), [
"In obtunded patients with vomiting",
"Insert NGT if altered consciousness",
"Nurse at 30–45° head elevation",
]),
("Acute Kidney Injury", RGBColor(0x14, 0x75, 0x5E), [
"Pre-renal from severe dehydration",
"Usually resolves with fluid resuscitation",
"Monitor creatinine, urine output",
]),
("Thrombosis / Rhabdomyolysis", RGBColor(0x84, 0x27, 0x93), [
"DVT/PE risk increased in DKA",
"Consider prophylactic LMWH in admitted patients",
"Rhabdomyolysis: check CK; aggressive fluids",
]),
]
for i, (title, col, pts) in enumerate(comp):
row, c = divmod(i, 3)
lft = 0.35 + c * 4.32
top = 1.25 + row * 2.8
add_rect(slide, lft, top, 4.0, 0.38, fill_color=col)
add_text(slide, title, lft+0.08, top, 3.84, 0.38,
font_size=11, bold=True, color=C_TEXT_WHITE, v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
add_rect(slide, lft, top+0.38, 4.0, 2.1, fill_color=C_ACCENT2, line_color=col, line_width_pt=1)
add_bullet_text(slide, pts, lft+0.1, top+0.42, 3.8, 2.0, font_size=11.5)
add_page_number(slide, 12, TOTAL)
# ── SLIDE 13 Special Scenarios ──────────────────────────────────────────
def slide_special(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Special Scenarios")
add_info_box(slide, "EUGLYCAEMIC DKA (SGLT-2 INHIBITOR ASSOCIATED)", [
"Blood glucose often 100–200 mg/dL — easily missed!",
"Mechanism: glucosuria masking hyperglycaemia + altered ketone metabolism",
"Manage like standard DKA: fluids, insulin, electrolytes",
"Start dextrose early to maintain glucose while clearing ketones",
"Stop SGLT-2 inhibitor; do NOT restart until DKA fully resolved",
"Avoid perioperative SGLT-2i — withold 3–4 days before elective surgery",
], 0.35, 1.25, 12.6, 2.5, font_size=12.5, title_color=RGBColor(0x14, 0x75, 0x5E), border_color=RGBColor(0x14, 0x75, 0x5E))
add_info_box(slide, "DKA IN PREGNANCY", [
"Can occur at lower glucose levels (~200 mg/dL) — accelerated starvation ketosis",
"Fetal mortality high if untreated — urgent management",
"Larger fluid volumes may be needed; monitor fetal heart rate",
"Insulin requirements change rapidly — involve obstetric & endocrine teams",
], 0.35, 3.9, 6.0, 2.8, font_size=12.5, title_color=RGBColor(0x84, 0x27, 0x93), border_color=RGBColor(0x84, 0x27, 0x93))
add_info_box(slide, "KETOSIS-PRONE (ATYPICAL) DKA (TYPE 1.5 / FLATBUSH)", [
"Obese adults, often Hispanic or African descent",
"Presents as classic DKA with T2DM phenotype",
"After DKA treatment: insulin secretory capacity recovers",
"Many can be managed long-term with OHA; not lifelong insulin dependent",
"HbA1c often markedly elevated at presentation",
], 6.7, 3.9, 6.3, 2.8, font_size=12.5, title_color=RGBColor(0xD3, 0x54, 0x00), border_color=RGBColor(0xD3, 0x54, 0x00))
add_page_number(slide, 13, TOTAL)
# ── SLIDE 14 DKA vs HHS ─────────────────────────────────────────────────
def slide_dka_hhs(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "DKA vs Hyperglycaemic Hyperosmolar State (HHS)")
headers = ["Feature", "DKA", "HHS", "Euglycaemic DKA"]
rows = [
["Typical patient", "T1DM, young", "T2DM, elderly", "T2DM on SGLT-2i"],
["Blood glucose", "11–33 mmol/L", "33–66 mmol/L", "5.5–13.9 mmol/L"],
["Serum ketones", "+++", "+/–", "+++"],
["pH", "< 7.3", "> 7.3", "< 7.3"],
["HCO₃", "< 18 mEq/L", "> 18 mEq/L", "< 18 mEq/L"],
["Osmolality", "> 300 mOsm/kg", "> 320 mOsm/kg", "Normal"],
["Fluid deficit", "3–5 L", "8–10 L", "2–4 L"],
["Onset", "Hours (24h)", "Days–weeks", "Variable"],
["Mortality", "< 1% (expert centre)", "5–20%", "< 1%"],
]
col_widths = [2.5, 2.8, 2.8, 2.8]
row_h = 0.5
tbl_left = 0.55
tbl_top = 1.28
hdr_cols = [C_HEADER_BG, C_ACCENT, RGBColor(0xD3,0x54,0x00), RGBColor(0x14,0x75,0x5E)]
for j, (h, w, col) in enumerate(zip(headers, col_widths, hdr_cols)):
left = tbl_left + sum(col_widths[:j])
add_rect(slide, left, tbl_top, w, row_h, fill_color=col)
add_text(slide, h, left+0.05, tbl_top, w-0.05, row_h,
font_size=12, bold=True, color=C_TEXT_WHITE, align=PP_ALIGN.CENTER,
v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
for i, row in enumerate(rows):
top = tbl_top + (i+1) * row_h
bg = C_LIGHT_GREY if i % 2 == 0 else C_TEXT_WHITE
for j, (cell, w) in enumerate(zip(row, col_widths)):
left = tbl_left + sum(col_widths[:j])
add_rect(slide, left, top, w, row_h, fill_color=bg,
line_color=RGBColor(0xCC,0xDD,0xEE), line_width_pt=0.5)
add_text(slide, cell, left+0.05, top, w-0.05, row_h,
font_size=11, bold=(j==0), color=C_TEXT_DARK,
align=PP_ALIGN.CENTER if j>0 else PP_ALIGN.LEFT,
v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.02)
add_rect(slide, 0.55, 5.95, 12.4, 0.55, fill_color=RGBColor(0xFF,0xF3,0xCD), line_color=C_BOX_ORANGE, line_width_pt=1)
add_text(slide, "Up to one-third of patients have overlapping features of BOTH DKA and HHS. Treat the dominant picture and reassess continuously.",
0.65, 5.97, 12.2, 0.52, font_size=12, color=RGBColor(0x7D,0x3C,0x00))
add_page_number(slide, 14, TOTAL)
# ── SLIDE 15 Prevention & Sick-Day Rules ────────────────────────────────
def slide_prevention(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Prevention & Sick-Day Management")
add_info_box(slide, "SICK-DAY RULES FOR PATIENTS WITH T1DM", [
"NEVER stop insulin during illness even if not eating",
"Monitor blood glucose every 2–4 hours",
"Check blood/urine ketones if glucose >13.9 mmol/L",
"Maintain hydration — small frequent sips; avoid sugary drinks if glucose high",
"Seek urgent medical review if: vomiting, ketones positive, glucose uncontrolled, confusion",
"Carry glucagon & wear medical ID at all times",
], 0.35, 1.25, 6.0, 4.0, font_size=12.5)
add_info_box(slide, "CLINICAL PREVENTION STRATEGIES", [
"Structured diabetes education programmes (DAFNE etc.)",
"Continuous glucose monitoring (CGM) with alarms",
"Insulin pump — consider HCL (hybrid closed loop) systems",
"Optimise HbA1c to reduce chronic complications without hypoglycaemia",
"Review precipitants after each DKA episode",
"Screen and treat infections promptly",
"Address diabulimia / psychological barriers to insulin use",
], 6.7, 1.25, 6.3, 4.0, font_size=12.5)
add_rect(slide, 0.35, 5.5, 12.6, 0.85, fill_color=RGBColor(0xFD,0xED,0xEC), line_color=C_BOX_RED, line_width_pt=1)
add_text(slide, "POST-DKA DISCHARGE: Review insulin regimen. Arrange early diabetes educator review. "
"Psychosocial assessment if recurrent DKA. "
"A single episode of DKA is associated with increased long-term mortality and microvascular risk — "
"reinforce importance of adherence.",
0.5, 5.52, 12.3, 0.82, font_size=12, color=C_TEXT_DARK)
add_page_number(slide, 15, TOTAL)
# ── SLIDE 16 Summary Flowchart ──────────────────────────────────────────
def slide_summary(prs):
slide = prs.slides.add_slide(blank)
slide_background(slide)
add_header_band(slide, "Clinical Management Flowchart — Quick Reference")
steps = [
("STEP 1\n(0 min)", C_BOX_RED,
"RESUSCITATION: Airway, Breathing, Circulation | Large-bore IV access x2 | O₂ if SpO₂ <94%\nBlood glucose, ketones, VBG, U&E, FBC, CRP, blood cultures | Catheter & fluid balance chart"),
("STEP 2\n(0–60 min)", C_ACCENT,
"FLUIDS: NS 0.9% (or Ringer's) 1 L over 1 hour | Assess haemodynamics"),
("STEP 3\n(0–60 min)", RGBColor(0xD3, 0x54, 0x00),
"CHECK K⁺: If K⁺ < 3.3 → replace K⁺, hold insulin | If K⁺ ≥ 3.3 → start insulin infusion 0.1 U/kg/h"),
("STEP 4\n(1–6 h)", RGBColor(0x14, 0x75, 0x5E),
"MAINTAIN: Continue fluids (0.45% NaCl) | Add K⁺ 20–40 mEq/L to fluids | Hourly glucose; 2-hourly VBG\nWhen glucose 200–250: add 5% dextrose | Reduce insulin to 0.02–0.05 U/kg/h"),
("STEP 5\n(6–24 h)", RGBColor(0x6C, 0x35, 0x83),
"TREAT PRECIPITANT: Antibiotics if infection | Stop SGLT-2i | ECG / troponin if suspected ACS"),
("STEP 6\n(Resolution)", C_BOX_GREEN,
"TRANSITION: pH >7.3, HCO₃ >18, AG normal → switch to SC insulin (overlap 2–4 h)\nStart oral intake | Diabetes education before discharge | Follow-up plan"),
]
for i, (label, col, desc) in enumerate(steps):
top = 1.25 + i * 1.0
add_rect(slide, 0.35, top, 1.5, 0.85, fill_color=col)
add_text(slide, label, 0.35, top, 1.5, 0.85, font_size=11, bold=True,
color=C_TEXT_WHITE, align=PP_ALIGN.CENTER, v_anchor=MSO_ANCHOR.MIDDLE)
add_rect(slide, 1.85, top, 11.1, 0.85, fill_color=C_ACCENT2, line_color=col, line_width_pt=1)
add_text(slide, desc, 1.95, top, 10.9, 0.85, font_size=11.5, color=C_TEXT_DARK,
v_anchor=MSO_ANCHOR.MIDDLE, margin_t=0.04)
add_page_number(slide, 16, TOTAL)
# ─── BUILD ALL SLIDES ───────────────────────────────────────────────────────
slide_title(prs)
slide_overview(prs)
slide_patho(prs)
slide_precip(prs)
slide_clinical(prs)
slide_severity(prs)
slide_mgmt_overview(prs)
slide_fluids(prs)
slide_insulin(prs)
slide_electrolytes(prs)
slide_monitoring(prs)
slide_complications(prs)
slide_special(prs)
slide_dka_hhs(prs)
slide_prevention(prs)
slide_summary(prs)
out_path = "/tmp/workspace/dka-presentation/DKA_Management_PG_IM.pptx"
prs.save(out_path)
print(f"Saved: {out_path}")
print(f"Slides: {len(prs.slides)}")
cd /tmp/workspace/dka-presentation && python build_dka.py 2>&1
ls -lh /tmp/workspace/dka-presentation/DKA_Management_PG_IM.pptx
DKA Management PG IM
Presentation · PPTX
| Slide | Title |
|---|---|
| 1 | Title slide with key focus areas |
| 2 | Overview & Epidemiology (stat boxes + definition) |
| 3 | Pathophysiology (3-column: hyperglycaemia / ketogenesis / dehydration) |
| 4 | Precipitating Factors - the "6 I's" |
| 5 | Clinical Features - symptoms, signs & immediate investigations |
| 6 | Severity Classification table (Mild / Moderate / Severe — ADA criteria) |
| 7 | Management Overview - The 5 Pillars |
| 8 | Fluid Resuscitation (initial, subsequent, special considerations) |
| 9 | Insulin Therapy (starting, adjusting, transition to SC) |
| 10 | Electrolyte Management - K⁺ protocol table, phosphate, bicarbonate |
| 11 | Monitoring frequency table & Resolution Criteria |
| 12 | Complications of DKA & Treatment (6-box layout) |
| 13 | Special Scenarios (euglycaemic DKA/SGLT-2i, pregnancy, ketosis-prone) |
| 14 | DKA vs HHS comparison table |
| 15 | Prevention & Sick-Day Rules |
| 16 | Clinical Management Flowchart - step-by-step quick reference |