Explain me about the latest guidelines on management of diabetic ketoacidosis.

Reading File
Finding Sources
Searching PubMed

"diabetic ketoacidosis" AND management

Searching the Web

diabetic ketoacidosis management guidelines 2024 2025 ADA

Reading File
Reading File
Reading Article

PMID: 40032308

Reading Web Page

https://emottawablog.com/2026/01/insulin-on-the-run-manageme…

Reading File
Reading File
Reading Article

PMID: 39090718

I now have comprehensive data from the ADA 2024 consensus, ADA Standards of Care 2025, textbooks (Goldman-Cecil, Rosen's EM), and recent meta-analysis. Let me compose the full answer.

Management of Diabetic Ketoacidosis (DKA): Latest Guidelines

The current gold standard is the ADA/EASD/JBDS 2024 Joint Consensus Report ("Management of Hyperglycemic Crises"), which updated the previous 2009 guidelines and was published in Diabetes Care (June 2024). The ADA Standards of Care 2025 further reinforced several key updates. Here is a structured summary:

1. Diagnostic Criteria

The 2024 consensus revised and standardized DKA diagnostic criteria:
FeatureDiagnostic Threshold
Blood glucose>11 mmol/L (>200 mg/dL) OR known diabetes
Serum/blood ketones≥3.0 mmol/L OR urine ketones ≥2+
Venous/arterial pH<7.3 OR serum bicarbonate <18 mmol/L
Key update: Blood beta-hydroxybutyrate (β-OHB) measurement is now preferred over urine dipstick for both diagnosis and monitoring of resolution, as it is more accurate and less subject to interference.
Severity classification (updated 2024):
SeveritypHSerum HCO₃β-OHB
Mild7.25-7.3015-18 mEq/L3-6 mmol/L
Moderate7.00-7.2410-14 mEq/L6-10 mmol/L
Severe<7.00<10 mEq/L>10 mmol/L

2. Initial Assessment

  • ABCs: airway, breathing, circulation; IV access
  • Capillary blood glucose + blood/urine ketones
  • Venous blood gas, serum electrolytes, BUN/creatinine, osmolality, CBC, LFTs
  • ECG (detect arrhythmias from K+ shifts), chest X-ray
  • Identify and treat the precipitating cause - the most common are infection, insulin non-adherence/omission, new-onset T1DM, and acute coronary syndrome. SGLT2 inhibitors are a now-recognized drug trigger (euglycemic DKA)
  • Urinary catheter if oliguric or comatose

3. Fluid Resuscitation

Fluid replacement is the single most impactful initial intervention.
Initial fluid (first 1 hour):
  • 0.9% sodium chloride (normal saline) remains the default first choice
  • Adults: 1000 mL over the first hour (or 10-20 mL/kg bolus in children or if hemodynamically unstable, repeated until BP stabilizes)
Subsequent fluids:
  • 2024 guidelines acknowledge growing evidence that balanced crystalloids (e.g., Ringer's Lactate or Hartmann's solution) may reduce hyperchloremic acidosis compared to large volumes of 0.9% NaCl. A 2024 systematic review supports their use and they are now offered as an acceptable alternative after initial resuscitation
  • Rate: typically 250-500 mL/hour after the first liter, adjusted by clinical response (urine output, hemodynamics)
  • Switch to Dextrose 5-10% + 0.45% NaCl once blood glucose falls below 250 mg/dL (14 mmol/L) to allow continued insulin infusion without causing hypoglycemia

4. Insulin Therapy

IV Insulin (standard approach)

  • Do not start insulin if K+ <3.3 mEq/L - correct potassium first
  • Fixed-rate IV infusion: 0.1 units/kg/hour of regular insulin (no bolus needed in most cases; an optional 0.1 unit/kg bolus may be given only if there is anticipated delay)
  • Target blood glucose reduction: 2-3 mmol/L/hour (36-54 mg/dL/hour)
  • When glucose <250 mg/dL: reduce insulin to 0.05 units/kg/hour and add dextrose to IV fluids; titrate to maintain glucose 140-200 mg/dL until DKA resolves

Subcutaneous Insulin (new 2024/2025 recommendation)

  • A major update: SC rapid-acting insulin analogues (e.g., lispro, aspart) are now endorsed as an alternative to IV insulin for mild-to-moderate DKA in hemodynamically stable, alert, non-vomiting patients
  • A 2024 systematic review and meta-analysis (Alnuaimi et al., BMC Endocr Disord 2024, PMID 39090718) confirmed no significant difference in time to DKA resolution, hypoglycemia rates, or mortality between SC and IV insulin (6 RCTs + 4 observational studies, n=8,689)
  • SC protocols may allow management in step-down units rather than ICU, reducing costs

Basal Insulin with IV infusion

  • ADA 2025 recommends continuing home basal insulin (or adding basal insulin) alongside IV infusion to prevent rebound hyperglycemia at transition - without increased hypoglycemia risk (JBDS has endorsed this since 2013)

Transition to subcutaneous insulin:

  • Start SC insulin 1-2 hours before stopping IV infusion to avoid rebound hyperglycemia
  • Patient must be able to eat, DKA must be resolved

5. Potassium Replacement

Potassium derangement is common and life-threatening. Total body K+ is almost always depleted (average deficit 3-5 mEq/kg) despite often-normal or high initial serum levels due to acidosis-driven extracellular shift.
Serum K+Action
<3.3 mEq/LHold insulin; replace K+ at 40 mEq/hour IV until K+ ≥3.3, then start insulin
3.3-5.3 mEq/LReplace K+ at 20-40 mEq/L in IV fluids; target 4-5 mEq/L
>5.3 mEq/LHold K+; check frequently; ECG monitoring; K+ will fall with insulin
  • Goldman-Cecil Medicine emphasizes that "large total-body deficits of potassium invariably accompany the osmotic diuresis and become readily apparent during treatment" - Goldman-Cecil Medicine, p. 2484

6. Phosphate, Magnesium, and Bicarbonate

Phosphate:
  • Routine phosphate replacement is not recommended (no clinical benefit in trials)
  • Replace only if serum phosphate <1 mg/dL or in patients with cardiac dysfunction, hemolytic anemia, or respiratory depression
Magnesium:
  • Replace if symptomatic or serum Mg <1.2 mg/dL: 1-2 g MgSO₄ IV - Rosen's Emergency Medicine
Bicarbonate:
  • Not recommended in most cases, even with severe acidosis
  • 2024 consensus: consider only if pH <6.9 (severe) - use 100 mEq NaHCO₃ in 400 mL sterile water + 20 mEq KCl over 2 hours, and reassess
  • Risk: paradoxical CNS acidosis, hypokalemia, worsened cellular oxygenation, delayed ketone clearance

7. Monitoring

  • Blood glucose: every 1-2 hours initially
  • Electrolytes, venous pH, BUN/Cr: every 2-4 hours
  • Blood β-OHB (preferred): every 2-4 hours for resolution tracking
  • Urine output: continuous
  • Cardiac monitor: continuous (arrhythmia from K+ shifts)
  • Maintain meticulous flow sheets - Rosen's Emergency Medicine, p. 2544

8. Criteria for DKA Resolution

All four criteria must be met simultaneously:
  1. Blood glucose <200 mg/dL (11.1 mmol/L)
  2. Serum bicarbonate ≥18 mEq/L
  3. Venous pH >7.3
  4. Anion gap ≤12 mEq/L OR blood β-OHB <0.6 mmol/L (new 2024 preferred criterion)
  • Never stop insulin when glucose normalizes if acidosis persists - add dextrose to maintain glucose while continuing insulin

9. Special Considerations

SGLT2 inhibitor-associated (Euglycemic DKA)

  • Blood glucose may be normal or only mildly elevated (<200 mg/dL), making diagnosis easily missed
  • High clinical suspicion in patients on SGLT2 inhibitors (empagliflozin, dapagliflozin, canagliflozin) with anion gap acidosis
  • Management is the same but glucose threshold for dextrose addition is lowered (start D5W with insulin from the outset to prevent hypoglycemia)
  • The 2024 consensus and ADA 2025 do not yet offer specific euDKA protocols; current evidence gaps are noted in a 2025 review

DKA in Pregnancy

  • More aggressive monitoring; target glucose 100-140 mg/dL (lower threshold)
  • Fetal monitoring; can occur at lower glucose levels
  • Bicarbonate use is particularly controversial in pregnancy (crosses placenta)
  • IV fluids and insulin management as for non-pregnant, with lower glucose targets

Pediatric DKA

  • Fluid resuscitation should be cautious - do not give rapid large boluses (risk of cerebral edema)
  • Cerebral edema is the leading cause of DKA mortality in children; treat with mannitol 0.5-1 g/kg IV or hypertonic saline if suspected
  • Typical fluid deficit: 70-120 mL/kg depending on weight (Rosen's EM, Table 115.3)

10. Discharge and Prevention

  • Identify outpatient diabetes care provider before discharge
  • Education: sick-day rules, never stop insulin when ill, recognize early DKA signs, when to call/come to ED
  • Address modifiable precipitants (adherence, access to insulin, psychosocial factors)
  • Consider structured follow-up within 1-2 weeks

Summary of Key 2024-2025 Updates vs. Previous Guidelines

TopicOld approachNew 2024/2025
Preferred ketone monitoringUrine dipstickBlood β-OHB preferred
IV fluidsNormal saline throughoutBalanced crystalloids acceptable after initial resuscitation
Insulin routeIV onlySC insulin valid for mild-moderate DKA
Basal insulinHold home insulinContinue/add basal with IV infusion
DKA resolution markerAnion gap/HCO₃/pH+ Blood β-OHB <0.6 mmol/L
SGLT2-DKA awarenessLimitedExplicitly flagged; euDKA recognition required

Key references:

Capillary blood glucose + blood/urine ketones Venous blood gas, serum electrolytes, BUN/creatinine, osmolality, CBC, LFTs ECG (detect arrhythmias from K+ shifts), chest X-ray Identify and treat the precipitating cause - the most common are infection, insulin non-adherence/omission, new-onset T1DM, and acute coronary syndrome. SGLT2 inhibitors are a now-recognized drug trigger (euglycemic DKA) Urinary catheter if oliguric or comatose explain in detail why these tests are done. what is the pathophysiology concept of doing these tests

Finding Sources
Finding Sources
Finding Sources
Searching the Web

DKA initial investigations pathophysiology rationale VBG electrolytes osmolality ECG

Reading File
Reading File
Finding Sources
Finding Sources
I now have all the pathophysiologic detail needed. Here is the full deep explanation:

Why Each Investigation is Done in DKA - The Pathophysiologic Rationale

The key to understanding DKA investigations is knowing the core metabolic disaster happening simultaneously:
Insulin deficiency + counter-regulatory hormone excess → hyperglycemia + uncontrolled lipolysis → ketogenesis → metabolic acidosis + osmotic diuresis → dehydration + electrolyte depletion
Every test targets a specific arm of this cascade.

1. Capillary Blood Glucose

What it tells you

The plasma glucose level - the first and most immediate confirmation of the "D" in DKA.

Pathophysiology concept

Insulin's primary job is to open the GLUT4 transporter on muscle and fat cells, allowing glucose to enter. Without insulin:
  • Glucose cannot enter cells - it piles up in blood (hyperglycemia)
  • Simultaneously, glucagon rises unopposed - it activates glycogenolysis (liver breaks down glycogen) and gluconeogenesis (amino acids and glycerol are converted to more glucose in the liver)
  • Both mechanisms amplify hyperglycemia from both sides
The result: blood glucose can reach 300-800 mg/dL (and sometimes >1000 mg/dL). The cells are simultaneously flooded outside and starving inside - often described as "starvation in the midst of plenty."

Why do it at bedside (capillary, not lab)?

  • It is instant - you do not wait for the formal lab. You can begin fluids immediately
  • In DKA, glucose >250 mg/dL with symptoms is enough to start the protocol before the formal workup is complete
  • Serial capillary glucose monitoring (every 1-2 hours) then tracks treatment response in real time

2. Blood/Urine Ketones

What it tells you

Confirms the "K" in DKA - ketosis. Blood β-hydroxybutyrate (β-OHB) is the preferred test; urine ketone dipstick is the backup.

Pathophysiology concept

When cells cannot use glucose, the body's starvation response activates:
  1. Lipolysis: Insulin normally suppresses hormone-sensitive lipase in adipose tissue. Without insulin, this lipase is fully active - it breaks triglycerides down into free fatty acids (FFAs) and glycerol
  2. Ketogenesis in the liver: FFAs flood the liver. The liver's mitochondria can only partially oxidize FFAs (because oxaloacetate is diverted to gluconeogenesis). The leftover fragments are condensed into ketone bodies: acetoacetate, β-hydroxybutyrate (β-OHB), and acetone
  3. β-OHB and acetoacetate are organic acids - each one consumes one bicarbonate molecule as a buffer when it dissociates. This is what causes the metabolic acidosis
  4. Acetone is volatile - it is exhaled, producing the classic fruity breath
Why blood β-OHB is preferred over urine ketones:
  • Urine dipstick (nitroprusside reagent) detects only acetoacetate and acetone - NOT β-OHB, which is actually the predominant (75-80%) ketone in DKA. You can have severe DKA with a misleadingly weak urine ketone result
  • Blood β-OHB directly measures the dominant ketone, gives severity, and is used for resolution criteria (target <0.6 mmol/L) - Tintinalli's EM

3. Venous Blood Gas (VBG)

What it tells you

  • pH (acid-base status)
  • Bicarbonate (HCO₃⁻)
  • pCO₂ (degree of respiratory compensation)
  • Potassium (K⁺) - the most critical electrolyte for immediate management

Why venous rather than arterial?

VBG is now standard per ADA/EASD 2024 and JBDS guidelines. Studies show venous pH is only ~0.03 lower than arterial - sufficient agreement for clinical decisions, far less painful, no arterial puncture risk. BMJ Best Practice confirms this.

Pathophysiology concept

pH / Acidosis: Each ketone molecule (β-OHB, acetoacetate) is a weak organic acid. When it dissociates in blood, it releases an H⁺ ion that is buffered by HCO₃⁻:
H⁺ + HCO₃⁻ → H₂CO₃ → H₂O + CO₂
Bicarbonate is consumed and pH falls. This is a high anion gap metabolic acidosis - the "missing" bicarbonate is replaced by the negatively charged ketone anions (unmeasured anions).
Anion gap = Na⁺ - (Cl⁻ + HCO₃⁻). Normal = 8-12 mEq/L. In DKA, ketone anions are not measured in the gap formula, so the gap widens (typically >20 mEq/L). The mnemonic MUDPILES (Methanol, Uremia, DKA, Paraldehyde, Iron, Lactic acidosis, Ethylene glycol, Salicylates) covers all high anion gap causes - Rosen's EM
Respiratory compensation (Kussmaul breathing): The brain detects falling pH via central chemoreceptors and drives the medullary respiratory center to hyperventilate. Deep, rapid breathing blows off CO₂ (a volatile acid), which partially compensates:
CO₂ + H₂O → H₂CO₃ → H⁺ + HCO₃⁻  (this reaction is reversed by blowing off CO₂)
Expected compensation: pCO₂ = 1.5 × [HCO₃⁻] + 8 ± 2 (Winter's formula). If pCO₂ is higher than expected, there is a coexisting respiratory acidosis (e.g., pneumonia precipitating DKA). If lower, there is a coexisting respiratory alkalosis.
Potassium from VBG: This is critical and action-determining. You MUST know K⁺ before starting insulin:
  • If K⁺ <3.3 mEq/L → do not start insulin yet - replace potassium first
  • Insulin will drive K⁺ back into cells and can precipitate fatal hypokalemia/arrhythmia if you start insulin with a low K⁺

4. Serum Electrolytes (Na⁺, K⁺, Cl⁻, HCO₃⁻)

Pathophysiology concept - each electrolyte explained:

Sodium (Na⁺) - and why it is falsely low

Osmotic dilution effect: Hyperglycemia raises extracellular osmolality. To equalize osmolality, water shifts from inside cells to outside cells. This extra water dilutes the measured sodium concentration - the sodium appears low even if total body sodium is normal or even depleted.
Corrected sodium formula:
Corrected Na⁺ = Measured Na⁺ + 2.4 × [(glucose mg/dL - 100) / 100]
(The correction factor is 2.4, especially when glucose >400 mg/dL - Tintinalli's EM, p. 3041)
The corrected sodium tells you the real hydration status. If the corrected Na⁺ is high, the patient is profoundly dehydrated. If it is normal/low, there may be true sodium loss (from osmotic diuresis).

Potassium (K⁺) - the most treacherous electrolyte in DKA

The paradox of DKA potassium:
  • Total body K⁺ is always depleted (average deficit: 3-5 mEq/kg from osmotic diuresis, vomiting, and poor intake) - Tintinalli's EM, p. 3037
  • Yet serum K⁺ is often normal or HIGH on admission
Why this paradox? Two mechanisms drive K⁺ out of cells into the blood:
  1. Acidosis - H⁺ ions enter cells to be buffered; electrically, K⁺ exits cells to maintain electroneutrality (for every 0.1 pH unit drop, serum K⁺ rises ~0.6 mEq/L)
  2. Hyperosmolality - high extracellular glucose concentration creates an osmotic gradient that pulls K⁺ out of cells with water
So the serum K⁺ is misleadingly "normal" - it is being held there by acidosis. The moment you give insulin (which drives K⁺ back into cells) and correct the acidosis, serum K⁺ can plummet. The drop during therapy averages ~1.5 mEq/L per glucose drop - Tintinalli's EM
Why does the serum K⁺ value determine the entire initial treatment sequence?
  • K⁺ <3.3: replace K⁺ first, no insulin (risk of fatal hypokalemia)
  • K⁺ 3.3-5.3: give insulin + concurrent K⁺ in fluids
  • K⁺ >5.3: give insulin, hold K⁺ (will fall naturally)

Chloride (Cl⁻) and Bicarbonate (HCO₃⁻)

  • Bicarbonate directly reflects the severity of acidosis and is used for DKA severity classification (mild: 15-18, moderate: 10-14, severe: <10 mEq/L)
  • Chloride and bicarbonate together let you calculate the anion gap = Na⁺ - (Cl⁻ + HCO₃⁻), which is the biochemical fingerprint of ketoacid accumulation
  • Chloride may rise later during treatment (especially with large volumes of 0.9% NaCl), causing a non-anion gap hyperchloremic acidosis - this is one reason balanced crystalloids are now preferred

5. BUN / Creatinine

What it tells you

Kidney function and degree of prerenal azotemia (dehydration).

Pathophysiology concept

The osmotic diuresis from hyperglycemia causes profound fluid losses (typically 3-6 liters in adults). This reduces effective circulating volume, dropping renal perfusion pressure. The kidneys respond by maximally retaining sodium and water, reducing GFR - this is prerenal azotemia:
  • BUN rises (reduced excretion)
  • Creatinine rises (reduced GFR)
  • BUN:Cr ratio >20:1 is classic for prerenal cause
Additional creatinine artifact: Acetoacetate (a ketone) can interfere with the colorimetric Jaffe reaction used to measure creatinine in many labs, falsely elevating the reported creatinine. So creatinine elevation in DKA can be partly artifact and partly real prerenal AKI.
Why does this matter? You need adequate urine output (>0.5 mL/kg/hr) before giving potassium supplements, since K⁺ is renally excreted. Severe AKI also modifies fluid management.

6. Serum Osmolality

What it tells you

The total solute concentration of plasma, reflecting the degree of hyperosmolality.

Pathophysiology concept

Measured osmolality = 2(Na⁺) + Glucose/18 + BUN/2.8
In DKA, both glucose and (if vomiting/dehydrated) BUN rise, pushing osmolality up. Normal is 280-295 mOsm/kg. In DKA, it typically runs 300-320 mOsm/kg; in HHS (hyperosmolar hyperglycemic state), it can exceed 340 mOsm/kg.
Why does osmolality matter?
  • It is the primary determinant of mental status in DKA. Hyperosmolality causes cerebral dehydration - water is pulled out of brain cells - leading to altered consciousness, stupor, and coma - Rosen's EM, p. 3690
  • The osmol gap (measured - calculated osmolality, normally <10) helps detect coingestions like alcohol or ethylene glycol, which can mimic DKA with a high anion gap
  • Tracking osmolality during treatment ensures you are not correcting too rapidly (especially important in HHS where rapid correction risks cerebral edema)

7. CBC (Complete Blood Count)

What it tells you

White cell count (infection), hemoglobin/hematocrit (hemoconcentration), platelets.

Pathophysiology concept

Leukocytosis without infection: Stress physiology in DKA causes catecholamine release, which demarginalizes neutrophils from vessel walls and releases them into circulation. Acidosis itself stimulates a pro-inflammatory state with cytokine release (IL-6, TNF-α). WBC of 10,000-25,000/mm³ is common in uncomplicated DKA without any infection.
Critical point: A WBC >25,000/mm³ or elevated band forms (>10,000/mm³ absolute neutrophil bands) suggest true infection as the precipitant - Tintinalli's EM, p. 3043. This is a critical threshold because infection is the #1 precipitant of DKA and must be identified and treated simultaneously.
Hemoconcentration: Volume depletion concentrates all blood elements. A high hematocrit reflects the degree of dehydration. Hemoglobin and hematocrit will fall as you rehydrate the patient - this is expected and reassuring that fluids are being distributed.

8. LFTs (Liver Function Tests)

What it tells you

Hepatocellular integrity, plus helps identify pancreatitis (a precipitant) via AST/ALT, and amylase/lipase if ordered separately.

Pathophysiology concept

Hepatic steatosis in DKA: Insulin deficiency leads to massive FFA influx into the liver (as described above for ketogenesis). Not all FFAs are converted to ketones - many are re-esterified into triglycerides and accumulate in hepatocytes (fatty liver/steatosis). This causes mild-to-moderate elevation of AST and ALT, which corrects as ketoacidosis is treated - Tintinalli's EM, p. 3043
Pancreatitis as precipitant: Acute pancreatitis can trigger DKA (stress hyperglycemia + glucagon surge). Elevated LFTs (especially ALT + raised amylase/lipase) point toward this. It is also a DKA complication - serum amylase and lipase are non-specifically elevated in up to 25% of DKA patients without true pancreatitis (due to salivary amylase release and impaired clearance).
Alcoholic ketoacidosis differential: LFTs help distinguish DKA from alcoholic ketoacidosis - the latter often shows a characteristic AST:ALT ratio >2:1.

9. ECG (Electrocardiogram)

What it tells you

Two critical things: (1) potassium-related arrhythmias, (2) myocardial infarction as a precipitant.

Pathophysiology concept

Potassium and myocardial membrane potential: Potassium is the primary determinant of the resting membrane potential of cardiac myocytes. The ratio of intracellular to extracellular K⁺ governs the resting potential via the Nernst equation. Any disruption causes electrical instability:
Hyperkalemia (when K⁺ is initially high, from acidosis):
  • Peaked (tall, narrow) T waves - earliest change
  • Prolonged PR interval → widening of QRS
  • Sine wave pattern → ventricular fibrillation if severe (K⁺ >7 mEq/L)
Hypokalemia (as treatment progresses, K⁺ shifts back into cells):
  • Flattened/inverted T waves
  • Prominent U waves (after T wave)
  • Prolonged QT interval → risk of Torsades de Pointes (a fatal polymorphic VT)
This is why continuous cardiac monitoring is mandatory throughout DKA treatment - the potassium is rapidly changing - Tintinalli's EM, p. 3039.
Myocardial infarction: Acute MI is a recognized precipitant of DKA (stress hormones spike, insulin counteraction worsens). Critically, the chest pain of MI can be masked in DKA because the non-specific abdominal pain, nausea, and Kussmaul breathing of DKA can mimic and overshadow typical MI symptoms. An ECG is mandatory to detect silent MI in any DKA patient.

10. Chest X-Ray

What it tells you

Pulmonary precipitants (pneumonia, TB), complications (pulmonary edema from overzealous fluid resuscitation), ARDS.

Pathophysiology concept

Infection as precipitant: Pneumonia is one of the most common precipitants of DKA. The stress response from infection drives counter-regulatory hormones (cortisol, catecholamines, glucagon) that directly oppose insulin. Even a chest infection in a T1DM patient can push them into DKA. A CXR identifies this and guides antibiotic choice.
ARDS in DKA: The pro-inflammatory cytokine storm in severe DKA (IL-6, TNF-α, free radical production) can cause pulmonary capillary leak, leading to non-cardiogenic pulmonary edema (ARDS). This worsens gas exchange and can be life-threatening. A baseline CXR establishes lung status before you start high-volume fluid resuscitation (which could worsen pulmonary edema in ARDS).
Aspiration risk: Gastroparesis (from autonomic neuropathy) and ileus are common in DKA. Gastric stasis combined with nausea/vomiting creates a high aspiration risk, especially in obtunded patients. A CXR can detect aspiration pneumonitis.

11. Urinary Catheter (if oliguric or comatose)

What it tells you

Accurate urine output measurement.

Pathophysiology concept

Why urine output is a critical monitoring parameter:
  • Urine output is a direct measure of renal perfusion and, by extension, cardiac output and fluid status
  • In DKA, you need at least 0.5 mL/kg/hr urine output before adding potassium to IV fluids - because potassium is renally excreted, and if the kidneys are not perfusing well, adding K⁺ risks fatal hyperkalemia
  • Oliguria (<0.5 mL/kg/hr) tells you the patient is still volume-depleted and more aggressive fluid replacement is needed
Why catheterize in an obtunded or comatose patient?
  • A comatose patient cannot sense bladder fullness and cannot void on command - without a catheter you have no idea what their urine output is
  • Urinary retention can itself cause obstructive uropathy, worsening renal function
  • Urine is also used for urinalysis/urine ketones and urine culture (if infection is suspected as the precipitant)

The Big Picture - How All Tests Connect

Insulin deficiency
      |
      ├── Hyperglycemia ──────────── Capillary glucose, serum glucose
      |        |
      |        └── Osmotic diuresis ─ BUN/Cr (prerenal AKI)
      |                    |           Na⁺ (corrected), osmolality
      |                    └──────────  K⁺, Mg²⁺, PO₄³⁻ depletion
      |
      ├── Uncontrolled lipolysis
      |        |
      |        └── Free fatty acids → Ketogenesis (β-OHB, AcAc)
      |                    |
      |                    ├── Blood/urine ketones
      |                    └── High anion gap metabolic acidosis
      |                               |
      |                               ├── VBG (pH, HCO₃⁻, pCO₂)
      |                               └── Serum electrolytes (anion gap)
      |
      ├── K⁺ paradox (high serum, depleted body stores) ── ECG (arrhythmia)
      |
      ├── Stress/infection (precipitant) ──────────────── CBC, CXR, cultures
      |
      └── Hepatic steatosis ──────────────────────────── LFTs
The investigations are not a checklist - each one is directly answering a specific pathophysiologic question about what the insulin-deficient body has done to itself. Knowing the "why" behind each test is what lets you act on the results immediately and correctly.

Create a diagnostic flowchart PDF for DKA workup and decision points

Reading File
Running Command

mkdir -p /tmp/workspace/dka-flowchart && ls /tmp/workspace/dka-flowchart/

Writing File

~/dka-flowchart/dka_flowchart.py

"""
DKA Diagnostic Flowchart PDF Generator
Uses ReportLab to create a multi-page clinical decision flowchart
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import Paragraph
from reportlab.lib.enums import TA_CENTER, TA_LEFT
import math

# ─── Colour palette ───────────────────────────────────────────────────────────
C_RED        = colors.HexColor("#C0392B")
C_RED_LIGHT  = colors.HexColor("#FADBD8")
C_ORANGE     = colors.HexColor("#E67E22")
C_ORANGE_LT  = colors.HexColor("#FDEBD0")
C_BLUE       = colors.HexColor("#1A5276")
C_BLUE_LT    = colors.HexColor("#D6EAF8")
C_BLUE_MED   = colors.HexColor("#2980B9")
C_GREEN      = colors.HexColor("#1E8449")
C_GREEN_LT   = colors.HexColor("#D5F5E3")
C_YELLOW     = colors.HexColor("#B7950B")
C_YELLOW_LT  = colors.HexColor("#FEF9E7")
C_PURPLE     = colors.HexColor("#6C3483")
C_PURPLE_LT  = colors.HexColor("#E8DAEF")
C_DARK       = colors.HexColor("#1C2833")
C_GREY       = colors.HexColor("#717D7E")
C_GREY_LT    = colors.HexColor("#F2F3F4")
C_WHITE      = colors.white

W, H = A4  # 595 x 842 pts

def pt(x): return x          # passthrough – already in points
def mm2pt(x): return x * mm  # mm to points

# ─── Drawing helpers ──────────────────────────────────────────────────────────

def draw_rounded_rect(c, x, y, w, h, r=6, fill_color=C_WHITE, stroke_color=C_DARK, lw=1):
    c.setFillColor(fill_color)
    c.setStrokeColor(stroke_color)
    c.setLineWidth(lw)
    c.roundRect(x, y, w, h, r, stroke=1, fill=1)

def draw_diamond(c, cx, cy, w, h, fill_color=C_YELLOW_LT, stroke_color=C_YELLOW, lw=1.5):
    hw, hh = w/2, h/2
    path = c.beginPath()
    path.moveTo(cx, cy + hh)
    path.lineTo(cx + hw, cy)
    path.lineTo(cx, cy - hh)
    path.lineTo(cx - hw, cy)
    path.close()
    c.setFillColor(fill_color)
    c.setStrokeColor(stroke_color)
    c.setLineWidth(lw)
    c.drawPath(path, stroke=1, fill=1)

def draw_arrow(c, x1, y1, x2, y2, color=C_DARK, lw=1.2, label=None, label_color=None):
    c.setStrokeColor(color)
    c.setLineWidth(lw)
    c.line(x1, y1, x2, y2)
    # arrowhead
    angle = math.atan2(y2 - y1, x2 - x1)
    size = 7
    ax1 = x2 - size * math.cos(angle - 0.4)
    ay1 = y2 - size * math.sin(angle - 0.4)
    ax2 = x2 - size * math.cos(angle + 0.4)
    ay2 = y2 - size * math.sin(angle + 0.4)
    path = c.beginPath()
    path.moveTo(x2, y2)
    path.lineTo(ax1, ay1)
    path.lineTo(ax2, ay2)
    path.close()
    c.setFillColor(color)
    c.drawPath(path, stroke=0, fill=1)
    if label:
        mx, my = (x1+x2)/2, (y1+y2)/2
        c.setFont("Helvetica-Bold", 7)
        c.setFillColor(label_color or color)
        c.drawCentredString(mx + 8, my + 3, label)

def draw_text_in_box(c, x, y, w, h, lines, font="Helvetica", size=8, color=C_DARK,
                     valign="middle", bold_first=False):
    """Draw multi-line text centred inside a box."""
    line_h = size * 1.35
    total_h = len(lines) * line_h
    if valign == "middle":
        start_y = y + h/2 + total_h/2 - line_h * 0.7
    else:
        start_y = y + h - 6
    c.setFillColor(color)
    for i, line in enumerate(lines):
        f = "Helvetica-Bold" if (bold_first and i == 0) else font
        c.setFont(f, size)
        c.drawCentredString(x + w/2, start_y - i * line_h, line)

def draw_box(c, x, y, w, h, lines, fill=C_BLUE_LT, stroke=C_BLUE_MED,
             font_size=8, bold_first=False, lw=1.2, r=5):
    draw_rounded_rect(c, x, y, w, h, r=r, fill_color=fill, stroke_color=stroke, lw=lw)
    draw_text_in_box(c, x, y, w, h, lines, size=font_size, bold_first=bold_first)

def section_header(c, x, y, w, h, text, fill=C_BLUE, text_color=C_WHITE, size=11):
    draw_rounded_rect(c, x, y, w, h, r=4, fill_color=fill, stroke_color=fill, lw=0)
    c.setFont("Helvetica-Bold", size)
    c.setFillColor(text_color)
    c.drawCentredString(x + w/2, y + h/2 - size*0.35, text)

# ─── Page 1: Diagnosis & Severity ─────────────────────────────────────────────

def page1(c):
    c.setPageSize(A4)

    # ── Background
    c.setFillColor(C_GREY_LT)
    c.rect(0, 0, W, H, fill=1, stroke=0)

    # ── Header bar
    c.setFillColor(C_BLUE)
    c.rect(0, H - 52, W, 52, fill=1, stroke=0)
    c.setFont("Helvetica-Bold", 17)
    c.setFillColor(C_WHITE)
    c.drawCentredString(W/2, H - 30, "DIABETIC KETOACIDOSIS (DKA) — DIAGNOSTIC FLOWCHART")
    c.setFont("Helvetica", 9)
    c.drawCentredString(W/2, H - 44, "Based on ADA/EASD/JBDS 2024 Consensus & ADA Standards of Care 2025  |  Page 1 of 3: Diagnosis & Severity")

    # ── Footer
    c.setFillColor(C_BLUE)
    c.rect(0, 0, W, 18, fill=1, stroke=0)
    c.setFont("Helvetica", 7)
    c.setFillColor(C_WHITE)
    c.drawCentredString(W/2, 5, "For clinical use — always apply individual patient judgment  |  ADA/EASD/JBDS 2024")

    # ── START node
    draw_rounded_rect(c, W/2-70, H-100, 140, 28, r=14,
                      fill_color=C_BLUE, stroke_color=C_BLUE, lw=0)
    c.setFont("Helvetica-Bold", 10)
    c.setFillColor(C_WHITE)
    c.drawCentredString(W/2, H-83, "PATIENT PRESENTS")
    draw_arrow(c, W/2, H-100, W/2, H-118)

    # ── Suspicion box
    draw_box(c, W/2-135, H-158, 270, 38,
             ["Symptoms suggesting DKA?",
              "Polyuria, polydipsia, nausea/vomiting, abdominal pain,",
              "Kussmaul breathing, fruity breath, altered consciousness"],
             fill=C_BLUE_LT, stroke=C_BLUE_MED, font_size=8, bold_first=True, r=5)
    draw_arrow(c, W/2, H-158, W/2, H-178)

    # ── Bedside tests box
    draw_box(c, W/2-150, H-232, 300, 52,
             ["IMMEDIATE BEDSIDE TESTS",
              "Capillary blood glucose (CBG)",
              "Blood beta-hydroxybutyrate (beta-OHB) — preferred over urine ketones",
              "Venous blood gas (VBG) — pH, HCO3-, pCO2, K+"],
             fill=C_ORANGE_LT, stroke=C_ORANGE, font_size=8, bold_first=True, lw=1.5, r=5)
    draw_arrow(c, W/2, H-232, W/2, H-252)

    # ── DKA criteria diamond
    diamond_y = H - 292
    draw_diamond(c, W/2, diamond_y, 260, 58,
                 fill_color=C_YELLOW_LT, stroke_color=C_YELLOW, lw=1.8)
    c.setFont("Helvetica-Bold", 8.5)
    c.setFillColor(C_DARK)
    c.drawCentredString(W/2, diamond_y + 14, "DKA Criteria Met? (ALL 3 required)")
    c.setFont("Helvetica", 7.5)
    c.drawCentredString(W/2, diamond_y + 2,  "Glucose > 11 mmol/L (200 mg/dL) OR known DM")
    c.drawCentredString(W/2, diamond_y - 10, "Beta-OHB >= 3.0 mmol/L  OR  Urine ketones >= 2+")
    c.drawCentredString(W/2, diamond_y - 22, "pH < 7.3  OR  HCO3- < 18 mEq/L")

    # NO branch → right
    draw_arrow(c, W/2 + 130, diamond_y, W/2 + 210, diamond_y, color=C_RED, lw=1.5, label="NO")
    draw_box(c, W/2 + 120, diamond_y - 26, 110, 52,
             ["CONSIDER", "Euglycemic DKA?",
              "(SGLT2i use?)", "HHS? Other cause?",
              "Refer / reassess"],
             fill=C_RED_LIGHT, stroke=C_RED, font_size=7.5, r=5)

    # YES branch → down
    draw_arrow(c, W/2, diamond_y - 29, W/2, diamond_y - 49, color=C_GREEN, lw=1.5, label="YES")

    # ── Full workup box
    fy = H - 400
    draw_box(c, 30, fy, W - 60, 68,
             ["FULL DIAGNOSTIC WORKUP",
              "VBG: pH, HCO3-, pCO2, K+ (IMMEDIATE — before starting insulin)",
              "Serum electrolytes: Na+, K+, Cl-, HCO3-, corrected Na+ [= measured Na + 2.4 x (glucose-100)/100]",
              "BUN / Creatinine  |  Serum Osmolality  |  Phosphate, Magnesium",
              "CBC (WBC >25k or bands >10k = infection)  |  LFTs  |  Serum amylase/lipase",
              "12-lead ECG (K+ arrhythmia? Silent MI?)  |  Chest X-ray  |  Blood + urine cultures",
              "Urinary catheter if oliguric or comatose"],
             fill=C_BLUE_LT, stroke=C_BLUE, font_size=8, bold_first=True, lw=1.5, r=5)
    draw_arrow(c, W/2, fy, W/2, fy - 18)

    # ── Severity box
    sy = fy - 130
    section_header(c, 30, fy - 26, W-60, 22, "SEVERITY CLASSIFICATION (ADA/EASD 2024)")
    # Table
    col_w = (W - 60) / 4
    headers = ["Parameter", "MILD", "MODERATE", "SEVERE"]
    rows = [
        ["Venous pH",       "7.25 – 7.30",   "7.00 – 7.24",   "< 7.00"],
        ["Serum HCO3-",     "15 – 18 mEq/L", "10 – 14 mEq/L", "< 10 mEq/L"],
        ["Blood beta-OHB",  "3 – 6 mmol/L",  "6 – 10 mmol/L", "> 10 mmol/L"],
        ["Mental status",   "Alert",          "Alert/Drowsy",  "Stupor/Coma"],
        ["Anion gap",       "> 12 mEq/L",     "> 12 mEq/L",    "> 12 mEq/L"],
    ]
    row_h = 17
    table_x = 30
    table_y = fy - 28

    # Header row
    header_colors = [C_BLUE, C_GREEN, C_ORANGE, C_RED]
    for ci, hdr in enumerate(headers):
        fc = header_colors[ci]
        c.setFillColor(fc)
        c.rect(table_x + ci*col_w, table_y - row_h, col_w, row_h, fill=1, stroke=0)
        c.setFont("Helvetica-Bold", 8.5)
        c.setFillColor(C_WHITE)
        c.drawCentredString(table_x + ci*col_w + col_w/2, table_y - row_h + 5, hdr)

    row_fills = [C_GREEN_LT, C_ORANGE_LT, C_RED_LIGHT]
    for ri, row in enumerate(rows):
        ty = table_y - row_h*(ri+2)
        for ci, cell in enumerate(row):
            if ci == 0:
                fc = C_GREY_LT
            else:
                fc = row_fills[ci-1]
            c.setFillColor(fc)
            c.setStrokeColor(C_GREY)
            c.setLineWidth(0.4)
            c.rect(table_x + ci*col_w, ty, col_w, row_h, fill=1, stroke=1)
            fnt = "Helvetica-Bold" if ci == 0 else "Helvetica"
            c.setFont(fnt, 8)
            c.setFillColor(C_DARK)
            c.drawCentredString(table_x + ci*col_w + col_w/2, ty + 5, cell)

    # ── Precipitants box
    py = sy - 60
    prec_y = table_y - row_h * 7 - 12
    section_header(c, 30, prec_y, W-60, 20, "IDENTIFY & TREAT PRECIPITATING CAUSE", fill=C_RED, size=10)
    prec_items = [
        ("Infection", "Fever, WBC >25k, bands, CXR, cultures", C_RED_LIGHT, C_RED),
        ("Insulin omission/non-adherence", "History, home medication review", C_ORANGE_LT, C_ORANGE),
        ("New-onset diabetes", "No prior Dx, young patient, HbA1c", C_BLUE_LT, C_BLUE_MED),
        ("Acute MI", "ECG, troponin (may be silent in DKA)", C_PURPLE_LT, C_PURPLE),
        ("SGLT2-inhibitor use", "Euglycemic DKA — glucose may be normal!", C_YELLOW_LT, C_YELLOW),
        ("Other", "PE, pancreatitis, CVA, alcohol, drugs", C_GREY_LT, C_GREY),
    ]
    pw = (W - 72) / 3
    ph = 34
    for i, (title, detail, fc, sc) in enumerate(prec_items):
        col = i % 3
        row = i // 3
        px = 36 + col * pw
        py2 = prec_y - 22 - row * (ph + 4)
        draw_rounded_rect(c, px, py2, pw - 4, ph, r=4, fill_color=fc, stroke_color=sc, lw=1)
        c.setFont("Helvetica-Bold", 8)
        c.setFillColor(C_DARK)
        c.drawCentredString(px + (pw-4)/2, py2 + ph - 11, title)
        c.setFont("Helvetica", 7)
        c.drawCentredString(px + (pw-4)/2, py2 + 6, detail)

    # ── Arrow to page 2
    draw_arrow(c, W/2, prec_y - 22 - 2*(ph+4) + 2, W/2, 24, color=C_BLUE, lw=1.5)
    draw_rounded_rect(c, W/2 - 90, 20, 180, 20, r=10,
                      fill_color=C_BLUE, stroke_color=C_BLUE, lw=0)
    c.setFont("Helvetica-Bold", 8.5)
    c.setFillColor(C_WHITE)
    c.drawCentredString(W/2, 28, "→  CONTINUE TO PAGE 2: MANAGEMENT (Fluids, Insulin, Electrolytes)")

    c.showPage()


# ─── Page 2: Fluid & Potassium & Insulin Management ───────────────────────────

def page2(c):
    c.setPageSize(A4)
    c.setFillColor(C_GREY_LT)
    c.rect(0, 0, W, H, fill=1, stroke=0)

    # Header
    c.setFillColor(C_BLUE)
    c.rect(0, H-52, W, 52, fill=1, stroke=0)
    c.setFont("Helvetica-Bold", 17)
    c.setFillColor(C_WHITE)
    c.drawCentredString(W/2, H-30, "DKA MANAGEMENT FLOWCHART")
    c.setFont("Helvetica", 9)
    c.drawCentredString(W/2, H-44, "ADA/EASD/JBDS 2024 Consensus  |  Page 2 of 3: Fluids · Potassium · Insulin")

    # Footer
    c.setFillColor(C_BLUE)
    c.rect(0, 0, W, 18, fill=1, stroke=0)
    c.setFont("Helvetica", 7)
    c.setFillColor(C_WHITE)
    c.drawCentredString(W/2, 5, "For clinical use — always apply individual patient judgment  |  ADA/EASD/JBDS 2024")

    cy = H - 65

    # ── Step 1: IV access + monitoring
    section_header(c, 30, cy, W-60, 20, "STEP 1 — IMMEDIATE RESUSCITATION & MONITORING", fill=C_BLUE)
    cy -= 22
    draw_box(c, 30, cy - 38, W-60, 38,
             ["IV access x2 large-bore  |  Continuous cardiac monitor  |  Strict I&O  |  Urinary catheter if oliguric/comatose",
              "Vitals q1h  |  CBG q1h  |  Electrolytes + VBG q2-4h  |  Blood beta-OHB q2-4h",
              "DO NOT delay fluids waiting for labs — begin 0.9% NaCl IMMEDIATELY"],
             fill=C_BLUE_LT, stroke=C_BLUE_MED, font_size=8.5, r=5)
    cy -= 48
    draw_arrow(c, W/2, cy, W/2, cy - 12)
    cy -= 12

    # ── Step 2: Fluid resuscitation
    section_header(c, 30, cy, W-60, 20, "STEP 2 — IV FLUID RESUSCITATION", fill=C_GREEN)
    cy -= 22
    # 3 column panels
    col_w3 = (W - 68) / 3
    panels_f = [
        ("HOUR 1 — Resuscitation",
         ["0.9% NaCl  1000 mL/hr",
          "(or 10-20 mL/kg bolus if",
          "haemodynamically unstable)",
          "Repeat bolus until SBP > 90"],
         C_GREEN_LT, C_GREEN),
        ("HOURS 2-8 — Replacement",
         ["0.9% NaCl OR balanced",
          "crystalloid (Ringer's Lactate)",
          "at 250-500 mL/hr",
          "Adjust by urine output + vitals"],
         C_ORANGE_LT, C_ORANGE),
        ("GLUCOSE < 250 mg/dL",
         ["Switch to D5-10% +",
          "0.45% NaCl",
          "Maintain glucose 140-200",
          "Continue insulin infusion!"],
         C_BLUE_LT, C_BLUE_MED),
    ]
    ph3 = 62
    for i, (title, lines, fc, sc) in enumerate(panels_f):
        px = 34 + i*(col_w3 + 5)
        draw_rounded_rect(c, px, cy - ph3, col_w3, ph3, r=5, fill_color=fc, stroke_color=sc, lw=1.5)
        c.setFont("Helvetica-Bold", 8)
        c.setFillColor(C_DARK)
        c.drawCentredString(px + col_w3/2, cy - 12, title)
        c.setFont("Helvetica", 7.5)
        for j, ln in enumerate(lines):
            c.drawCentredString(px + col_w3/2, cy - 24 - j*11, ln)
    cy -= (ph3 + 10)
    draw_arrow(c, W/2, cy, W/2, cy - 12)
    cy -= 12

    # ── Step 3: POTASSIUM — the critical gate
    section_header(c, 30, cy, W-60, 20, "STEP 3 — POTASSIUM CHECK (CRITICAL GATE — CHECK BEFORE INSULIN)", fill=C_RED)
    cy -= 22
    # Diamond
    d_cy = cy - 30
    draw_diamond(c, W/2, d_cy, 220, 52, fill_color=C_YELLOW_LT, stroke_color=C_YELLOW, lw=1.8)
    c.setFont("Helvetica-Bold", 9)
    c.setFillColor(C_DARK)
    c.drawCentredString(W/2, d_cy + 10, "Serum K+ level?")
    c.setFont("Helvetica", 8)
    c.drawCentredString(W/2, d_cy - 4, "(from VBG or formal labs)")

    # 3 branches
    bw = 130
    bh = 60

    # K < 3.3 — left
    draw_arrow(c, W/2 - 110, d_cy, 34 + bw/2, d_cy - 30, color=C_RED, lw=1.5)
    c.setFont("Helvetica-Bold", 7); c.setFillColor(C_RED)
    c.drawString(70, d_cy + 5, "< 3.3")
    draw_rounded_rect(c, 34, d_cy - 30 - bh, bw, bh, r=5, fill_color=C_RED_LIGHT, stroke_color=C_RED, lw=1.5)
    c.setFont("Helvetica-Bold", 8); c.setFillColor(C_RED)
    c.drawCentredString(34 + bw/2, d_cy - 30 - 12, "HOLD INSULIN")
    c.setFont("Helvetica", 7.5); c.setFillColor(C_DARK)
    for j, ln in enumerate(["Give KCl 40 mEq/hr IV", "Recheck K+ in 1 hr", "Start insulin only", "when K+ >= 3.3"]):
        c.drawCentredString(34 + bw/2, d_cy - 30 - 25 - j*10, ln)

    # K 3.3–5.3 — centre
    draw_arrow(c, W/2, d_cy - 26, W/2, d_cy - 30 - bh + bh/2 + 5, color=C_GREEN, lw=1.5)
    c.setFont("Helvetica-Bold", 7); c.setFillColor(C_GREEN)
    c.drawCentredString(W/2, d_cy - 18, "3.3 – 5.3")
    draw_rounded_rect(c, W/2 - bw/2, d_cy - 30 - bh, bw, bh, r=5, fill_color=C_GREEN_LT, stroke_color=C_GREEN, lw=1.5)
    c.setFont("Helvetica-Bold", 8); c.setFillColor(C_GREEN)
    c.drawCentredString(W/2, d_cy - 30 - 12, "START INSULIN")
    c.setFont("Helvetica", 7.5); c.setFillColor(C_DARK)
    for j, ln in enumerate(["Add KCl 20-40 mEq/L", "to IV fluids", "Target K+ 4.0-5.0", "Check K+ q2h"]):
        c.drawCentredString(W/2, d_cy - 30 - 25 - j*10, ln)

    # K > 5.3 — right
    draw_arrow(c, W/2 + 110, d_cy, W - 34 - bw/2, d_cy - 30, color=C_ORANGE, lw=1.5)
    c.setFont("Helvetica-Bold", 7); c.setFillColor(C_ORANGE)
    c.drawString(W/2 + 115, d_cy + 5, "> 5.3")
    draw_rounded_rect(c, W - 34 - bw, d_cy - 30 - bh, bw, bh, r=5, fill_color=C_ORANGE_LT, stroke_color=C_ORANGE, lw=1.5)
    c.setFont("Helvetica-Bold", 8); c.setFillColor(C_ORANGE)
    c.drawCentredString(W - 34 - bw/2, d_cy - 30 - 12, "HOLD POTASSIUM")
    c.setFont("Helvetica", 7.5); c.setFillColor(C_DARK)
    for j, ln in enumerate(["Start insulin (K+ will fall)", "ECG monitoring", "Recheck K+ q2h", "Add K+ when < 5.3"]):
        c.drawCentredString(W - 34 - bw/2, d_cy - 30 - 25 - j*10, ln)

    cy = d_cy - 30 - bh - 15
    draw_arrow(c, W/2, cy, W/2, cy - 12)
    cy -= 12

    # ── Step 4: Insulin
    section_header(c, 30, cy, W-60, 20, "STEP 4 — INSULIN THERAPY", fill=C_PURPLE)
    cy -= 22

    col_w2 = (W - 68) / 2
    panels_i = [
        ("IV INSULIN (Standard / Moderate-Severe DKA)",
         ["Fixed-rate infusion: 0.1 units/kg/hr Regular insulin",
          "Optional bolus 0.1 u/kg ONLY if delay in starting infusion",
          "Target glucose fall: 2-3 mmol/L/hr (36-54 mg/dL/hr)",
          "When glucose < 250 mg/dL: reduce to 0.05 units/kg/hr",
          "+ switch IV fluid to dextrose-containing (see Step 2)",
          "Maintain glucose 140-200 mg/dL until DKA resolved"],
         C_PURPLE_LT, C_PURPLE),
        ("SC INSULIN (NEW — Mild-Moderate DKA only)",
         ["Rapid-acting analogue (lispro/aspart) SC",
          "Valid alternative to IV insulin per ADA 2024/2025",
          "Only if: haemodynamically stable + alert + not vomiting",
          "Evidence: no difference in DKA resolution time,",
          "hypoglycemia, or mortality vs IV insulin (meta-analysis 2024)",
          "Allows step-down unit care; may reduce costs"],
         C_GREEN_LT, C_GREEN),
    ]
    pi_h = 72
    for i, (title, lines, fc, sc) in enumerate(panels_i):
        px = 34 + i*(col_w2 + 5)
        draw_rounded_rect(c, px, cy - pi_h, col_w2, pi_h, r=5, fill_color=fc, stroke_color=sc, lw=1.5)
        c.setFont("Helvetica-Bold", 8); c.setFillColor(C_DARK)
        c.drawCentredString(px + col_w2/2, cy - 11, title)
        c.setFont("Helvetica", 7.5)
        for j, ln in enumerate(lines):
            c.drawCentredString(px + col_w2/2, cy - 23 - j*9.5, ln)
    cy -= (pi_h + 6)

    # Basal insulin note
    draw_box(c, 30, cy - 22, W-60, 22,
             ["BASAL INSULIN: Continue home long-acting insulin OR add basal insulin alongside IV infusion to prevent rebound hyperglycemia (ADA 2025 / JBDS 2013)"],
             fill=C_YELLOW_LT, stroke=C_YELLOW, font_size=8, r=4)
    cy -= 32

    # Arrow to page 3
    draw_arrow(c, W/2, cy, W/2, 24, color=C_BLUE, lw=1.5)
    draw_rounded_rect(c, W/2 - 90, 20, 180, 20, r=10, fill_color=C_BLUE, stroke_color=C_BLUE, lw=0)
    c.setFont("Helvetica-Bold", 8.5); c.setFillColor(C_WHITE)
    c.drawCentredString(W/2, 28, "→  CONTINUE TO PAGE 3: Monitoring · Resolution · Transition · Discharge")

    c.showPage()


# ─── Page 3: Monitoring, Resolution, Transition, Special Situations ───────────

def page3(c):
    c.setPageSize(A4)
    c.setFillColor(C_GREY_LT)
    c.rect(0, 0, W, H, fill=1, stroke=0)

    # Header
    c.setFillColor(C_BLUE)
    c.rect(0, H-52, W, 52, fill=1, stroke=0)
    c.setFont("Helvetica-Bold", 17)
    c.setFillColor(C_WHITE)
    c.drawCentredString(W/2, H-30, "DKA: MONITORING · RESOLUTION · TRANSITION")
    c.setFont("Helvetica", 9)
    c.drawCentredString(W/2, H-44, "ADA/EASD/JBDS 2024 Consensus  |  Page 3 of 3")

    # Footer
    c.setFillColor(C_BLUE)
    c.rect(0, 0, W, 18, fill=1, stroke=0)
    c.setFont("Helvetica", 7)
    c.setFillColor(C_WHITE)
    c.drawCentredString(W/2, 5, "For clinical use — always apply individual patient judgment  |  ADA/EASD/JBDS 2024")

    cy = H - 65

    # ── Monitoring table
    section_header(c, 30, cy, W-60, 20, "MONITORING DURING TREATMENT", fill=C_BLUE)
    cy -= 22
    mon_rows = [
        ("Capillary blood glucose",       "Every 1 hour",        "Target: 2-3 mmol/L/hr fall; 140-200 mg/dL once stable"),
        ("Serum electrolytes (K+, Na+, HCO3-)", "Every 2-4 hours", "Adjust K+ replacement in fluids based on result"),
        ("Venous blood gas (pH, HCO3-)",  "Every 2-4 hours",     "Track acidosis resolution; calculate anion gap each time"),
        ("Blood beta-OHB",                "Every 2-4 hours",     "Resolution target: < 0.6 mmol/L (preferred over urine ketones)"),
        ("BUN / Creatinine",              "Every 4-6 hours",     "Monitor renal function; confirm adequate urine output before K+ supplements"),
        ("Urine output",                  "Continuous (catheter)", "Target >= 0.5 mL/kg/hr; critical before giving K+ supplementation"),
        ("Cardiac monitor (ECG)",         "Continuous",           "Detect hypo/hyperkalemia arrhythmia; K+ changes are rapid"),
        ("Neurological status",           "Every 1 hour",         "Altered consciousness, headache, bradycardia = suspect cerebral edema"),
    ]
    row_h = 16
    col_ws = [160, 105, W-60-160-105-6]
    header_row = ["Parameter", "Frequency", "Action / Target"]
    header_cs = [C_BLUE, C_BLUE_MED, C_BLUE]
    for ci, (hdr, cw) in enumerate(zip(header_row, col_ws)):
        cx2 = 30 + sum(col_ws[:ci]) + ci
        c.setFillColor(C_BLUE)
        c.rect(cx2, cy - row_h, cw, row_h, fill=1, stroke=0)
        c.setFont("Helvetica-Bold", 8); c.setFillColor(C_WHITE)
        c.drawCentredString(cx2 + cw/2, cy - row_h + 5, hdr)
    for ri, (p, f, a) in enumerate(mon_rows):
        ty = cy - row_h*(ri+2)
        row_fc = C_GREY_LT if ri % 2 == 0 else C_WHITE
        row_data = [p, f, a]
        for ci, (cell, cw) in enumerate(zip(row_data, col_ws)):
            cx2 = 30 + sum(col_ws[:ci]) + ci
            c.setFillColor(row_fc)
            c.setStrokeColor(C_GREY)
            c.setLineWidth(0.3)
            c.rect(cx2, ty, cw, row_h, fill=1, stroke=1)
            font = "Helvetica-Bold" if ci == 0 else "Helvetica"
            c.setFont(font, 7.5); c.setFillColor(C_DARK)
            c.drawCentredString(cx2 + cw/2, ty + 5, cell)
    cy -= row_h * 10 + 10
    draw_arrow(c, W/2, cy, W/2, cy - 12)
    cy -= 12

    # ── Resolution criteria diamond
    section_header(c, 30, cy, W-60, 20, "STEP 5 — RESOLUTION CRITERIA CHECK (ALL 4 must be met)", fill=C_GREEN)
    cy -= 22
    d_cy = cy - 38
    draw_diamond(c, W/2, d_cy, 280, 64, fill_color=C_YELLOW_LT, stroke_color=C_YELLOW, lw=1.8)
    c.setFont("Helvetica-Bold", 9); c.setFillColor(C_DARK)
    c.drawCentredString(W/2, d_cy + 16, "DKA RESOLVED? (All 4 met)")
    c.setFont("Helvetica", 8)
    c.drawCentredString(W/2, d_cy + 4,  "1. Blood glucose < 200 mg/dL (11.1 mmol/L)")
    c.drawCentredString(W/2, d_cy - 8,  "2. Serum HCO3- >= 18 mEq/L")
    c.drawCentredString(W/2, d_cy - 20, "3. Venous pH > 7.3")
    c.drawCentredString(W/2, d_cy - 32, "4. Blood beta-OHB < 0.6 mmol/L  OR  Anion gap <= 12")

    # NO → loop back
    draw_arrow(c, W/2 + 140, d_cy, W - 30, d_cy, color=C_RED, lw=1.5, label="NO")
    c.setFont("Helvetica-Bold", 7.5); c.setFillColor(C_RED)
    c.drawRightString(W - 32, d_cy + 8, "Continue insulin + fluids")
    c.setFont("Helvetica", 7); c.setFillColor(C_DARK)
    c.drawRightString(W - 32, d_cy - 2, "Add dextrose if glucose < 250")
    c.drawRightString(W - 32, d_cy - 12, "Never stop insulin while acidotic")

    # YES → down
    draw_arrow(c, W/2, d_cy - 32, W/2, d_cy - 52, color=C_GREEN, lw=1.5, label="YES")
    cy = d_cy - 52
    draw_arrow(c, W/2, cy, W/2, cy - 10); cy -= 10

    # ── Transition
    section_header(c, 30, cy, W-60, 20, "STEP 6 — TRANSITION TO SUBCUTANEOUS INSULIN", fill=C_GREEN)
    cy -= 22
    draw_box(c, 30, cy - 36, W-60, 36,
             ["Patient MUST be: eating, alert, clinically stable, and DKA resolved",
              "Give first SC dose (rapid-acting + basal) — then wait 1-2 HOURS before stopping IV insulin infusion",
              "Calculate SC dose based on prior home regimen OR total daily insulin used in last 24h (typically 70-80% as basal + bolus split)"],
             fill=C_GREEN_LT, stroke=C_GREEN, font_size=8.5, bold_first=False, r=5)
    cy -= 46
    draw_arrow(c, W/2, cy, W/2, cy - 10); cy -= 10

    # ── Special situations
    section_header(c, 30, cy, W-60, 20, "SPECIAL SITUATIONS & COMPLICATIONS", fill=C_RED)
    cy -= 22
    sp_items = [
        ("Cerebral Edema", ["Headache, falling HR,", "altered GCS in treatment",
                            "RX: Mannitol 0.5-1 g/kg IV", "OR 3% NaCl 2.5-5 mL/kg",
                            "Restrict fluids, raise HOB"], C_RED_LIGHT, C_RED),
        ("Euglycemic DKA (SGLT2i)", ["Glucose may be normal", "High index of suspicion",
                                      "Same management but", "start dextrose early",
                                      "Withhold SGLT2i"], C_ORANGE_LT, C_ORANGE),
        ("Severe Hypokalemia (K <3.0)", ["Hold insulin", "Replace at 40 mEq/hr",
                                          "Continuous ECG monitor", "Recheck q1h",
                                          "Risk: fatal arrhythmia"], C_PURPLE_LT, C_PURPLE),
        ("DKA in Pregnancy", ["Target glucose 100-140", "Fetal monitoring",
                               "Lower glucose threshold", "for dextrose switch",
                               "Urgent OB consult"], C_BLUE_LT, C_BLUE_MED),
        ("Bicarbonate use", ["ONLY if pH < 6.9", "100 mEq NaHCO3 in 400 mL",
                              "+ 20 mEq KCl over 2 hrs", "Reassess after",
                              "Risks: paradox CNS acidosis"], C_YELLOW_LT, C_YELLOW),
        ("HHS overlap", ["Glucose often >600", "Minimal ketosis", "Aggressive rehydration",
                          "Slower glucose correction", "(<90-120 mg/dL/hr)"], C_GREY_LT, C_GREY),
    ]
    sp_w = (W - 72) / 3
    sp_h = 72
    for i, (title, lines, fc, sc) in enumerate(sp_items):
        col = i % 3
        row = i // 3
        px = 36 + col * (sp_w + 3)
        py2 = cy - 4 - row * (sp_h + 5)
        draw_rounded_rect(c, px, py2 - sp_h, sp_w, sp_h, r=5, fill_color=fc, stroke_color=sc, lw=1.3)
        c.setFont("Helvetica-Bold", 8); c.setFillColor(C_DARK)
        c.drawCentredString(px + sp_w/2, py2 - 12, title)
        c.setFont("Helvetica", 7.5)
        for j, ln in enumerate(lines):
            c.drawCentredString(px + sp_w/2, py2 - 24 - j*10, ln)

    cy = cy - 4 - 2*(sp_h + 5) - sp_h - 10
    draw_arrow(c, W/2, cy, W/2, cy - 10); cy -= 10

    # ── Discharge box
    draw_box(c, 30, cy - 36, W-60, 36,
             ["DISCHARGE PLANNING",
              "Identify outpatient diabetes provider  |  Medication reconciliation (correct insulin dose, stop SGLT2i if implicated)",
              "Education: sick-day rules, when to call / return to ED, importance of insulin adherence, recognise early DKA signs",
              "Follow-up within 1-2 weeks"],
             fill=C_BLUE_LT, stroke=C_BLUE, font_size=8, bold_first=True, r=5, lw=1.5)
    cy -= 46

    c.showPage()


# ─── Main ─────────────────────────────────────────────────────────────────────

def build():
    out = "/tmp/workspace/dka-flowchart/DKA_Diagnostic_Flowchart.pdf"
    c = canvas.Canvas(out, pagesize=A4)
    c.setTitle("DKA Diagnostic & Management Flowchart — ADA/EASD/JBDS 2024")
    c.setAuthor("Orris Medical AI")
    c.setSubject("Diabetic Ketoacidosis Clinical Flowchart")
    page1(c)
    page2(c)
    page3(c)
    c.save()
    print(f"PDF saved: {out}")

build()
Running Command

cd /tmp/workspace/dka-flowchart && python dka_flowchart.py 2>&1

Running Command

ls -lh /tmp/workspace/dka-flowchart/DKA_Diagnostic_Flowchart.pdf

Your DKA flowchart PDF is ready:

DKA Diagnostic Flowchart

PDF Document · PDF


The PDF is 3 pages, A4 size, fully colour-coded and structured as follows:

Page 1 - Diagnosis & Severity

  • Patient presentation → bedside tests → diagnostic criteria diamond (D + K + A)
  • Full workup panel (VBG, electrolytes, ECG, CXR, etc.)
  • Severity classification table (Mild / Moderate / Severe) with pH, HCO₃⁻, beta-OHB thresholds per ADA/EASD 2024
  • Precipitating causes grid (infection, insulin omission, MI, new-onset DM, SGLT2i, other)

Page 2 - Management (Fluids, Potassium, Insulin)

  • Step-by-step fluid resuscitation panels (Hour 1 → Hours 2-8 → glucose <250 switch)
  • Potassium decision diamond (the critical gate before insulin) with 3 branches: K <3.3 / 3.3-5.3 / >5.3, and specific replacement rates
  • Insulin therapy: IV insulin (standard) vs SC insulin (new 2024/2025 option for mild-moderate DKA) side by side
  • Basal insulin continuation note

Page 3 - Monitoring, Resolution & Transition

  • Monitoring frequency table (what, how often, target/action)
  • Resolution criteria diamond (all 4 must be met: glucose <200, HCO₃⁻ ≥18, pH >7.3, beta-OHB <0.6)
  • SC insulin transition protocol (timing of overlap)
  • Special situations: cerebral edema, euglycemic DKA (SGLT2i), severe hypokalemia, DKA in pregnancy, bicarbonate use, HHS overlap
  • Discharge planning box

Create a bedside quick reference card PDF (1-page pocket guide) with key DKA thresholds and decision trees

Running Command

ls /tmp/workspace/dka-flowchart/

Writing File

~/dka-flowchart/dka_pocket_card.py

"""
DKA Bedside Quick Reference Card — 1 Page A5 landscape (pocket-card size)
Dense, colour-coded, print-and-laminate format.
ADA/EASD/JBDS 2024 | ADA Standards of Care 2025
"""

from reportlab.lib.pagesizes import A5, landscape
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
import math

# ── Canvas size: A5 landscape = 210 x 148 mm ──────────────────────────────────
W, H = landscape(A5)   # 595 x 420 pts  (≈ 210 x 148 mm)

# ── Palette ───────────────────────────────────────────────────────────────────
C_NAVY      = colors.HexColor("#0B2C5F")
C_BLUE      = colors.HexColor("#1A6DA8")
C_BLUE_LT   = colors.HexColor("#DAEAF7")
C_BLUE_MED  = colors.HexColor("#2980B9")
C_TEAL      = colors.HexColor("#0E7C6C")
C_TEAL_LT   = colors.HexColor("#D0EDE8")
C_GREEN     = colors.HexColor("#1A7A3C")
C_GREEN_LT  = colors.HexColor("#D5F0E0")
C_ORANGE    = colors.HexColor("#C0570A")
C_ORANGE_LT = colors.HexColor("#FDEBD0")
C_RED       = colors.HexColor("#B22222")
C_RED_LT    = colors.HexColor("#FADADD")
C_PURPLE    = colors.HexColor("#5B2C8D")
C_PURPLE_LT = colors.HexColor("#EAD9F7")
C_YELLOW    = colors.HexColor("#8B6914")
C_YELLOW_LT = colors.HexColor("#FEF9E3")
C_DARK      = colors.HexColor("#1C1C1C")
C_MGREY     = colors.HexColor("#5D6D7E")
C_LGREY     = colors.HexColor("#EEF0F2")
C_WHITE     = colors.white

# ── Helpers ───────────────────────────────────────────────────────────────────

def rr(c, x, y, w, h, r=4, fc=C_WHITE, sc=C_DARK, lw=0.8):
    c.setFillColor(fc); c.setStrokeColor(sc); c.setLineWidth(lw)
    c.roundRect(x, y, w, h, r, stroke=1, fill=1)

def filled_rect(c, x, y, w, h, fc, sc=None, lw=0):
    c.setFillColor(fc)
    if sc:
        c.setStrokeColor(sc); c.setLineWidth(lw); c.rect(x, y, w, h, fill=1, stroke=1)
    else:
        c.rect(x, y, w, h, fill=1, stroke=0)

def txt(c, x, y, text, font="Helvetica", size=7, color=C_DARK, align="left"):
    c.setFont(font, size); c.setFillColor(color)
    if align == "center":
        c.drawCentredString(x, y, text)
    elif align == "right":
        c.drawRightString(x, y, text)
    else:
        c.drawString(x, y, text)

def hdr(c, x, y, w, h, text, fc=C_NAVY, tc=C_WHITE, size=7.5):
    filled_rect(c, x, y, w, h, fc)
    txt(c, x + w/2, y + h/2 - size*0.38, text, "Helvetica-Bold", size, tc, "center")

def arrow(c, x1, y1, x2, y2, col=C_DARK, lw=0.9):
    c.setStrokeColor(col); c.setLineWidth(lw); c.line(x1, y1, x2, y2)
    angle = math.atan2(y2-y1, x2-x1)
    sz = 5
    ax1 = x2 - sz*math.cos(angle-0.4); ay1 = y2 - sz*math.sin(angle-0.4)
    ax2 = x2 - sz*math.cos(angle+0.4); ay2 = y2 - sz*math.sin(angle+0.4)
    p = c.beginPath(); p.moveTo(x2,y2); p.lineTo(ax1,ay1); p.lineTo(ax2,ay2); p.close()
    c.setFillColor(col); c.drawPath(p, stroke=0, fill=1)

def diamond(c, cx, cy, hw, hh, fc=C_YELLOW_LT, sc=C_YELLOW, lw=1.1):
    p = c.beginPath()
    p.moveTo(cx, cy+hh); p.lineTo(cx+hw, cy); p.lineTo(cx, cy-hh); p.lineTo(cx-hw, cy); p.close()
    c.setFillColor(fc); c.setStrokeColor(sc); c.setLineWidth(lw); c.drawPath(p, stroke=1, fill=1)

def bullet_block(c, x, y, w, items, size=6.5, leading=8.5, color=C_DARK, bold=False):
    font = "Helvetica-Bold" if bold else "Helvetica"
    for i, item in enumerate(items):
        c.setFont(font, size); c.setFillColor(color)
        c.drawString(x, y - i*leading, item)

# ─────────────────────────────────────────────────────────────────────────────
# LAYOUT PLAN  (A5 landscape 595 x 420 pt)
#
#  [  HEADER BAR  — full width, 22 pt tall  ]
#
#  Col A (x=6..188, w=182)  |  Col B (x=196..388, w=192)  |  Col C (x=394..589, w=195)
#
#  A: Dx Criteria + Severity table
#  B: K+ decision tree + Insulin
#  C: Fluids + Resolution + Discharge
#
#  [  FOOTER BAR  — full width, 12 pt tall  ]
# ─────────────────────────────────────────────────────────────────────────────

def build():
    out = "/tmp/workspace/dka-flowchart/DKA_Pocket_Reference_Card.pdf"
    cv = canvas.Canvas(out, pagesize=landscape(A5))
    cv.setTitle("DKA Bedside Quick Reference Card — ADA/EASD/JBDS 2024")
    cv.setAuthor("Orris Medical AI")
    cv.setSubject("DKA Pocket Guide")

    # ── Background
    filled_rect(cv, 0, 0, W, H, colors.HexColor("#F5F7FA"))

    # ═══════════════════════════════════════════════════════════════
    # HEADER
    # ═══════════════════════════════════════════════════════════════
    filled_rect(cv, 0, H-24, W, 24, C_NAVY)
    txt(cv, W/2, H-15, "DKA BEDSIDE QUICK REFERENCE  —  ADA/EASD/JBDS 2024  |  ADA Standards of Care 2025",
        "Helvetica-Bold", 8.5, C_WHITE, "center")

    # thin accent line
    filled_rect(cv, 0, H-26, W, 2, C_BLUE)

    # ═══════════════════════════════════════════════════════════════
    # COLUMN GEOMETRY
    # ═══════════════════════════════════════════════════════════════
    TOP = H - 30          # content starts here
    BOT = 14              # above footer
    USABLE = TOP - BOT    # usable height

    cA_x, cA_w = 6,   184
    cB_x, cB_w = 196, 192
    cC_x, cC_w = 394, 195

    div_x1 = cB_x - 4
    div_x2 = cC_x - 4
    cv.setStrokeColor(colors.HexColor("#CBD0D8")); cv.setLineWidth(0.6)
    cv.line(div_x1, BOT+2, div_x1, TOP)
    cv.line(div_x2, BOT+2, div_x2, TOP)

    # ═══════════════════════════════════════════════════════════════
    # COLUMN A — Diagnosis & Severity
    # ═══════════════════════════════════════════════════════════════
    y = TOP

    # Section: DX CRITERIA
    hdr(cv, cA_x, y-13, cA_w, 13, "▶  DIAGNOSTIC CRITERIA  (all 3 required)", fc=C_NAVY, size=7.5)
    y -= 14
    rr(cv, cA_x, y-42, cA_w, 42, r=3, fc=C_LGREY, sc=colors.HexColor("#BDC3C7"), lw=0.5)
    rows_dx = [
        ("D", "Glucose",  "> 11 mmol/L (200 mg/dL) OR known DM", C_BLUE_LT,   C_BLUE),
        ("K", "Ketones",  "Beta-OHB ≥ 3.0 mmol/L  OR  Urine 2+",  C_ORANGE_LT, C_ORANGE),
        ("A", "Acidosis", "pH < 7.3  OR  HCO3- < 18 mEq/L",         C_RED_LT,    C_RED),
    ]
    for i, (letter, label, val, fc, sc) in enumerate(rows_dx):
        ry = y - 5 - i*13
        filled_rect(cv, cA_x+2, ry-9, 12, 11, fc, sc, 0.6)
        txt(cv, cA_x+8, ry-6, letter, "Helvetica-Bold", 8, sc, "center")
        txt(cv, cA_x+17, ry-6, label+":", "Helvetica-Bold", 6.8, C_DARK)
        txt(cv, cA_x+45, ry-6, val, "Helvetica", 6.5, C_DARK)
    y -= 44

    # Note: blood beta-OHB preferred over urine
    rr(cv, cA_x, y-11, cA_w, 11, r=2, fc=C_YELLOW_LT, sc=C_YELLOW, lw=0.6)
    txt(cv, cA_x+4, y-8, "★  Blood beta-OHB preferred over urine ketone dipstick (more accurate)", "Helvetica-Oblique", 6, C_YELLOW, "left")
    y -= 13

    # Section: SEVERITY TABLE
    hdr(cv, cA_x, y-13, cA_w, 13, "▶  SEVERITY CLASSIFICATION", fc=C_BLUE, size=7.5)
    y -= 14

    col_labels = ["Parameter", "MILD", "MODERATE", "SEVERE"]
    col_fc     = [C_LGREY,   C_GREEN_LT, C_ORANGE_LT, C_RED_LT]
    col_hc     = [C_MGREY,   C_GREEN,    C_ORANGE,    C_RED]
    sev_cw     = [58, 38, 44, 40]
    sev_rows   = [
        ["pH",             "7.25–7.30",   "7.00–7.24",   "< 7.00"],
        ["HCO3- (mEq/L)", "15–18",        "10–14",        "< 10"],
        ["Beta-OHB",       "3–6 mmol/L",  "6–10 mmol/L", "> 10 mmol/L"],
        ["Mental status",  "Alert",        "Alert/Drowsy", "Stupor/Coma"],
    ]
    row_h_s = 11
    # header row
    cx_acc = cA_x
    for ci, (cl, cw, fc, hc) in enumerate(zip(col_labels, sev_cw, col_fc, col_hc)):
        filled_rect(cv, cx_acc, y-row_h_s, cw, row_h_s, hc)
        txt(cv, cx_acc+cw/2, y-row_h_s+3, cl, "Helvetica-Bold", 6, C_WHITE, "center")
        cx_acc += cw
    y -= row_h_s
    for ri, row in enumerate(sev_rows):
        cx_acc = cA_x
        for ci, (cell, cw, fc) in enumerate(zip(row, sev_cw, col_fc)):
            bg = C_LGREY if ri%2==0 else C_WHITE
            if ci > 0: bg = col_fc[ci]
            cv.setFillColor(bg); cv.setStrokeColor(colors.HexColor("#CBD0D8")); cv.setLineWidth(0.3)
            cv.rect(cx_acc, y-row_h_s, cw, row_h_s, fill=1, stroke=1)
            fnt = "Helvetica-Bold" if ci==0 else "Helvetica"
            txt(cv, cx_acc+cw/2, y-row_h_s+3, cell, fnt, 6, C_DARK, "center")
            cx_acc += cw
        y -= row_h_s
    y -= 3

    # Section: PRECIPITANTS
    hdr(cv, cA_x, y-13, cA_w, 13, "▶  COMMON PRECIPITANTS", fc=C_RED, size=7.5)
    y -= 14
    prec = [
        ("🔴", "Infection (most common) — cultures, CXR, WBC"),
        ("🟠", "Insulin omission / non-adherence"),
        ("🟡", "New-onset T1DM"),
        ("🟣", "Acute MI (may be silent — get ECG)"),
        ("🔵", "SGLT2-inhibitor → euglycemic DKA (glucose can be normal!)"),
        ("⚫", "PE, pancreatitis, CVA, alcohol, steroids"),
    ]
    rr(cv, cA_x, y-len(prec)*9-2, cA_w, len(prec)*9+2, r=3, fc=C_LGREY, sc=colors.HexColor("#BDC3C7"), lw=0.5)
    for i, (icon, line) in enumerate(prec):
        txt(cv, cA_x+4, y-7-i*9, icon+" "+line, "Helvetica", 6.2, C_DARK)
    y -= len(prec)*9 + 5

    # ═══════════════════════════════════════════════════════════════
    # COLUMN B — Potassium Decision Tree + Insulin
    # ═══════════════════════════════════════════════════════════════
    y = TOP

    hdr(cv, cB_x, y-13, cB_w, 13, "▶  POTASSIUM — CRITICAL GATE BEFORE INSULIN", fc=C_RED, size=7.5)
    y -= 14

    # Mini potassium flow
    rr(cv, cB_x, y-12, cB_w, 12, r=3, fc=C_YELLOW_LT, sc=C_YELLOW, lw=1)
    txt(cv, cB_x+cB_w/2, y-8.5, "CHECK SERUM K+  (from VBG or labs) — before starting insulin",
        "Helvetica-Bold", 6.5, C_DARK, "center")
    y -= 14
    arrow(cv, cB_x+cB_w/2, y, cB_x+cB_w/2, y-7, C_DARK)
    y -= 7

    # Three K branches side by side
    bw = 58; bh = 58; gap = 3
    b_xs = [cB_x+1, cB_x+1+bw+gap, cB_x+1+2*(bw+gap)]
    b_fcs= [C_RED_LT, C_GREEN_LT, C_ORANGE_LT]
    b_scs= [C_RED,    C_GREEN,     C_ORANGE]
    b_titles = ["K+ < 3.3", "K+ 3.3 – 5.3", "K+ > 5.3"]
    b_actions = [
        ["HOLD INSULIN",
         "Give KCl 40 mEq/hr IV",
         "Recheck q1h",
         "Start insulin only",
         "when K+ ≥ 3.3"],
        ["START INSULIN",
         "Add KCl 20-40 mEq/L",
         "to IV fluids",
         "Target K+ 4.0-5.0",
         "Recheck q2h"],
        ["HOLD POTASSIUM",
         "Start insulin",
         "K+ will fall with Rx",
         "ECG monitor",
         "Add K+ when < 5.3"],
    ]
    for i, (bx, fc, sc, title, acts) in enumerate(zip(b_xs, b_fcs, b_scs, b_titles, b_actions)):
        rr(cv, bx, y-bh, bw, bh, r=3, fc=fc, sc=sc, lw=1)
        txt(cv, bx+bw/2, y-9, title, "Helvetica-Bold", 7, sc, "center")
        for j, act in enumerate(acts):
            fnt = "Helvetica-Bold" if j==0 else "Helvetica"
            txt(cv, bx+bw/2, y-18-j*8, act, fnt, 6, C_DARK, "center")
    y -= bh + 5

    # ECG reminder
    rr(cv, cB_x, y-10, cB_w, 10, r=2, fc=C_PURPLE_LT, sc=C_PURPLE, lw=0.7)
    txt(cv, cB_x+4, y-7.5, "⚡ ECG: hyperK → peaked T, wide QRS  |  hypoK → flat T, U waves, long QT → arrhythmia!",
        "Helvetica-Bold", 6, C_PURPLE)
    y -= 12

    # Section: INSULIN
    hdr(cv, cB_x, y-13, cB_w, 13, "▶  INSULIN THERAPY", fc=C_PURPLE, size=7.5)
    y -= 14

    iv_lines = [
        "IV Regular insulin: 0.1 u/kg/hr fixed infusion",
        "Target fall: 2-3 mmol/L/hr (36-54 mg/dL/hr)",
        "Glucose < 250: reduce to 0.05 u/kg/hr",
        "  + switch fluids to D5-10% + 0.45% NaCl",
        "Target glucose: 140-200 mg/dL until resolved",
    ]
    sc_lines = [
        "SC rapid-acting (lispro/aspart) — NEW option",
        "Mild-moderate DKA only if: alert +",
        "  haemodynamically stable + not vomiting",
        "Evidence: equivalent to IV (meta-analysis 2024)",
    ]

    # IV box
    rr(cv, cB_x, y-len(iv_lines)*8-5, cB_w//2-2, len(iv_lines)*8+5, r=3, fc=C_PURPLE_LT, sc=C_PURPLE, lw=0.8)
    txt(cv, cB_x+cB_w//4, y-6, "IV INSULIN (standard)", "Helvetica-Bold", 6.5, C_PURPLE, "center")
    for i, ln in enumerate(iv_lines):
        txt(cv, cB_x+3, y-14-i*8, ln, "Helvetica", 6, C_DARK)

    # SC box
    sc_x = cB_x + cB_w//2 + 2
    sc_w = cB_w - cB_w//2 - 2
    rr(cv, sc_x, y-len(iv_lines)*8-5, sc_w, len(iv_lines)*8+5, r=3, fc=C_GREEN_LT, sc=C_GREEN, lw=0.8)
    txt(cv, sc_x+sc_w/2, y-6, "SC INSULIN (new 2024)", "Helvetica-Bold", 6.5, C_GREEN, "center")
    for i, ln in enumerate(sc_lines):
        txt(cv, sc_x+3, y-14-i*8, ln, "Helvetica", 6, C_DARK)
    y -= len(iv_lines)*8 + 8

    # Basal note
    rr(cv, cB_x, y-10, cB_w, 10, r=2, fc=C_YELLOW_LT, sc=C_YELLOW, lw=0.7)
    txt(cv, cB_x+4, y-7.5,
        "★ Continue / add basal insulin alongside IV infusion (ADA 2025 / JBDS)",
        "Helvetica-Oblique", 6, C_YELLOW)
    y -= 13

    # Section: TRANSITION
    hdr(cv, cB_x, y-12, cB_w, 12, "▶  TRANSITION TO SC INSULIN", fc=C_TEAL, size=7)
    y -= 13
    trans = [
        "Patient eating + alert + DKA resolved",
        "Give SC rapid-acting + basal FIRST",
        "Wait 1-2 hrs THEN stop IV infusion",
        "Dose: 70-80% of 24-hr IV total as basal+bolus",
    ]
    rr(cv, cB_x, y-len(trans)*8-3, cB_w, len(trans)*8+3, r=3, fc=C_TEAL_LT, sc=C_TEAL, lw=0.8)
    for i, ln in enumerate(trans):
        txt(cv, cB_x+4, y-8-i*8, "• "+ln, "Helvetica", 6.2, C_DARK)
    y -= len(trans)*8 + 6

    # ═══════════════════════════════════════════════════════════════
    # COLUMN C — Fluids, Monitoring, Resolution, Special Situations
    # ═══════════════════════════════════════════════════════════════
    y = TOP

    # FLUIDS
    hdr(cv, cC_x, y-13, cC_w, 13, "▶  IV FLUID RESUSCITATION", fc=C_TEAL, size=7.5)
    y -= 14
    fluid_rows = [
        ("Hour 1",      "0.9% NaCl 1000 mL/hr",           "Bolus 10-20 mL/kg if shock", C_BLUE_LT),
        ("Hours 2-8",   "0.9% NaCl or balanced crystal",  "250-500 mL/hr; adjust by UO", C_TEAL_LT),
        ("Glu<250",     "D5-10% + 0.45% NaCl",            "Never stop insulin! Add dextrose", C_ORANGE_LT),
    ]
    fh = 12
    fl_cw = [36, 70, 85]
    fl_hdrs = ["Phase", "Fluid", "Notes"]
    # header
    fxacc = cC_x
    for flh, flcw, fcc in zip(fl_hdrs, fl_cw, [C_TEAL, C_TEAL, C_TEAL]):
        filled_rect(cv, fxacc, y-fh, flcw, fh, C_TEAL)
        txt(cv, fxacc+flcw/2, y-fh+3.5, flh, "Helvetica-Bold", 6, C_WHITE, "center")
        fxacc += flcw
    y -= fh
    for phase, fluid, note, fc in fluid_rows:
        fxacc = cC_x
        for cell, flcw in zip([phase, fluid, note], fl_cw):
            cv.setFillColor(fc if fl_cw.index(flcw)>0 else C_LGREY)
            cv.setStrokeColor(colors.HexColor("#CBD0D8")); cv.setLineWidth(0.3)
            cv.rect(fxacc, y-fh, flcw, fh, fill=1, stroke=1)
            txt(cv, fxacc+flcw/2, y-fh+3.5, cell, "Helvetica", 5.8, C_DARK, "center")
            fxacc += flcw
        y -= fh
    y -= 4

    # MONITORING
    hdr(cv, cC_x, y-12, cC_w, 12, "▶  MONITORING FREQUENCY", fc=C_BLUE, size=7.5)
    y -= 13
    mon_items = [
        ("CBG",              "q1h",      "Target 140-200 mg/dL when stable"),
        ("Electrolytes/VBG", "q2-4h",    "K+, HCO3-, anion gap each time"),
        ("Blood beta-OHB",   "q2-4h",    "Resolution: < 0.6 mmol/L"),
        ("Urine output",     "Continuous","≥ 0.5 mL/kg/hr before giving K+"),
        ("ECG/cardiac mon.", "Continuous","Arrhythmia from K+ shifts"),
        ("Neuro status",     "q1h",      "Headache/bradycardia = cerebral edema?"),
    ]
    mon_cw = [55, 35, 100]
    rr(cv, cC_x, y-len(mon_items)*9-2, cC_w, len(mon_items)*9+2, r=3, fc=C_LGREY, sc=colors.HexColor("#BDC3C7"), lw=0.4)
    for i, (param, freq, note) in enumerate(mon_items):
        my = y - 8 - i*9
        txt(cv, cC_x+3, my, param, "Helvetica-Bold", 6, C_DARK)
        txt(cv, cC_x+58, my, freq, "Helvetica-Bold", 6, C_BLUE_MED)
        txt(cv, cC_x+92, my, note, "Helvetica", 5.8, C_MGREY)
    y -= len(mon_items)*9 + 5

    # RESOLUTION CRITERIA
    hdr(cv, cC_x, y-13, cC_w, 13, "▶  RESOLUTION CRITERIA  (ALL 4 required)", fc=C_GREEN, size=7.5)
    y -= 14
    res_items = [
        ("1.", "Blood glucose",    "< 200 mg/dL (11.1 mmol/L)"),
        ("2.", "Serum HCO3-",      "≥ 18 mEq/L"),
        ("3.", "Venous pH",        "> 7.3"),
        ("4.", "Blood beta-OHB",   "< 0.6 mmol/L  ★ preferred criterion"),
    ]
    rr(cv, cC_x, y-len(res_items)*9-4, cC_w, len(res_items)*9+4, r=3, fc=C_GREEN_LT, sc=C_GREEN, lw=0.8)
    for i, (num, param, val) in enumerate(res_items):
        ry2 = y - 8 - i*9
        txt(cv, cC_x+4, ry2, num, "Helvetica-Bold", 7, C_GREEN)
        txt(cv, cC_x+14, ry2, param, "Helvetica-Bold", 6.5, C_DARK)
        txt(cv, cC_x+14, ry2-8, "    → "+val, "Helvetica", 6, C_DARK)
    y -= len(res_items)*9 + 7

    # SPECIAL ALERTS
    hdr(cv, cC_x, y-13, cC_w, 13, "▶  SPECIAL ALERTS", fc=C_RED, size=7.5)
    y -= 14
    alerts = [
        ("⚠", "CEREBRAL EDEMA",       C_RED_LT,    C_RED,
         "Headache+slow HR in Rx → mannitol 0.5-1g/kg OR 3% NaCl"),
        ("⚠", "EUGLYCEMIC DKA",       C_ORANGE_LT, C_ORANGE,
         "SGLT2i use → normal glucose, high AG acidosis → start D5 early"),
        ("⚠", "BICARB USE",           C_PURPLE_LT, C_PURPLE,
         "Only if pH < 6.9 → 100 mEq NaHCO3 + 20 mEq KCl over 2 hrs"),
        ("⚠", "PREGNANCY",            C_BLUE_LT,   C_BLUE,
         "Target glucose 100-140 mg/dL; fetal monitoring; OB consult"),
    ]
    for i, (icon, title, fc, sc, detail) in enumerate(alerts):
        ay = y - 3 - i*20
        rr(cv, cC_x, ay-16, cC_w, 16, r=3, fc=fc, sc=sc, lw=0.8)
        txt(cv, cC_x+4, ay-8, icon+" "+title+":", "Helvetica-Bold", 6.5, sc)
        txt(cv, cC_x+4, ay-15, "   "+detail, "Helvetica", 5.8, C_DARK)
    y -= len(alerts)*20 + 5

    # ═══════════════════════════════════════════════════════════════
    # FOOTER
    # ═══════════════════════════════════════════════════════════════
    filled_rect(cv, 0, 0, W, 13, C_NAVY)
    txt(cv, W/2, 4, "ADA/EASD/JBDS 2024 Consensus  |  ADA Standards of Care 2025  |  For clinical reference — apply individual patient judgement  |  Orris Medical AI",
        "Helvetica", 5.5, C_WHITE, "center")

    cv.save()
    print(f"Pocket card saved: {out}")

build()
Running Command

cd /tmp/workspace/dka-flowchart && python dka_pocket_card.py 2>&1

Running Command

ls -lh /tmp/workspace/dka-flowchart/

Your pocket reference card is ready:

DKA Pocket Reference Card

PDF Document · PDF


Format: Single page, A5 landscape (148 × 210 mm) - print, laminate, and carry in a white coat pocket or clip to a clipboard.
The card is laid out in 3 dense columns:

Column 1 - Diagnosis & Severity

  • The D-K-A triad criteria with colour-coded badges (blue/orange/red)
  • Blood beta-OHB preferred over urine ketone note
  • Severity table: Mild / Moderate / Severe with pH, HCO₃⁻, beta-OHB, and mental status cutoffs
  • 6 common precipitants including the SGLT2i euglycemic DKA flag

Column 2 - Potassium Gate + Insulin

  • The potassium decision split (K <3.3 / 3.3-5.3 / >5.3) with exact actions in three colour-coded boxes - the most critical bedside decision point
  • ECG changes banner: peaked T (hyperK) vs flat T + U waves (hypoK)
  • IV insulin protocol (standard) vs SC insulin (new 2024/2025 option) side by side
  • Basal insulin continuation note
  • Transition-to-SC checklist with timing rule

Column 3 - Fluids, Monitoring, Resolution, Alerts

  • Fluid phase table (Hour 1 → Hours 2-8 → glucose <250 switch)
  • Monitoring frequency quick table (what, how often, target)
  • Resolution criteria box (all 4 must be met, beta-OHB <0.6 starred as preferred)
  • 4 special alerts: cerebral edema, euglycemic DKA, bicarbonate threshold (pH <6.9 only), pregnancy targets
This is a shared conversation. Sign in to Orris to start your own chat.