Patient with abdomen pain and vomating
"It is critical to approach acute abdominal pain in a systematic fashion. This stepwise approach begins with a detailed history and physical examination..." - Yamada's Textbook of Gastroenterology, 7th ed.
| Feature | Clinical Significance |
|---|---|
| Site | Epigastric = upper GI / pancreas; Periumbilical = small intestine; RLQ = appendix; LLQ = diverticulitis; RUQ = biliary |
| Onset | Sudden/explosive = perforation, volvulus, ruptured aneurysm; Gradual = appendicitis, cholecystitis |
| Character | Colicky (waxes/wanes, restless patient) = obstruction, renal colic, biliary colic; Constant = peritonitis/ischemia |
| Radiation | RUQ to right shoulder = cholecystitis; Back = pancreatitis, AAA; Groin = ureteric colic |
| Severity | Rate 1-10; "worst ever" suggests catastrophic event |
| Aggravating/relieving | Worse with movement = peritonitis; Better with leaning forward = pancreatitis |
| Timing | Duration, progression, previous similar episodes |
| Sign | Significance |
|---|---|
| Tenderness location | Guides anatomical differential |
| Guarding (voluntary) | Abdominal wall spasm; peritoneal irritation |
| Rigidity (involuntary) | True peritonitis ("board-like") |
| Rebound tenderness | Parietal peritoneal irritation |
| Murphy's sign | Acute cholecystitis |
| Rovsing's sign | Appendicitis |
| Psoas sign | Retrocecal appendicitis |
| Obturator sign | Pelvic appendicitis or pelvic abscess |
| Bowel sounds | Absent = ileus/peritonitis; Tinkling/high-pitched = obstruction |
| Distension | Obstruction, ileus |
| Hernial orifices | Strangulated hernia (a common missed cause) |
| Region | Key Diagnoses |
|---|---|
| Epigastric | Peptic ulcer disease, GERD, acute pancreatitis, gastritis, MI (atypical) |
| RUQ | Acute cholecystitis, cholangitis, hepatitis, hepatic abscess |
| LUQ | Splenic infarct/rupture, splenic flexure colitis |
| Periumbilical | Early appendicitis, small bowel obstruction, mesenteric ischemia |
| RLQ | Appendicitis, Meckel's diverticulitis, Crohn's, ovarian torsion/cyst, ectopic pregnancy |
| LLQ | Diverticulitis, sigmoid volvulus, IBD, ovarian pathology |
| Diffuse | Peritonitis (any cause), gastroenteritis, mesenteric ischemia, bowel obstruction |
| Loin/flank | Renal colic, pyelonephritis, renal infarct |
| Investigation | Purpose |
|---|---|
| FBC/CBC | Leukocytosis = infection/inflammation; anemia = hemorrhage |
| CRP / ESR | Inflammatory marker |
| Serum amylase / lipase | Acute pancreatitis (lipase more sensitive/specific) |
| LFTs (bilirubin, ALP, AST, ALT, GGT) | Biliary pathology, hepatitis |
| Serum lactate | Mesenteric ischemia, sepsis (elevated = poor perfusion) |
| Renal function (urea, creatinine, electrolytes) | Dehydration, renal pathology, DKA |
| Coagulation screen (INR/PT) | Hepatic disease, pre-operative |
| Group & save / cross-match | If hemorrhage suspected |
| Blood cultures | If febrile / sepsis suspected |
| Calcium | Pancreatitis cause, hypercalcemia |
| Modality | Indications / Findings |
|---|---|
| Erect chest X-ray | Free air under diaphragm (perforation) - FIRST LINE |
| Plain abdominal X-ray (AXR) | Bowel obstruction (dilated loops, air-fluid levels), volvulus, calcified stones |
| Ultrasound abdomen/pelvis | First-line for RUQ pain (biliary), appendicitis (in children/young), ovarian pathology, free fluid, AAA; operator-dependent but no radiation |
| CT abdomen/pelvis (with IV contrast) | Gold standard for most acute abdominal emergencies - appendicitis, diverticulitis, mesenteric ischemia, pancreatitis staging, bowel obstruction, aortic pathology |
| MRI | Preferred in pregnancy (avoid radiation); excellent for biliary and soft tissue |
| MRCP | Biliary stones, cholangitis |
"Vomiting accompanied by abdominal pain may suggest biliary colic or intestinal obstruction. Copious vomiting of large volumes may occur in gastric outlet obstruction." - Pye's Surgical Handicraft, 22nd ed.
Acute abdominal pain + vomiting
↓
Vital signs STABLE?
↓ ↓
YES NO → Resuscitate (IV access, fluids, O2)
↓ → Surgical consult URGENT
Detailed History
(SOCRATES + vomiting character + associated symptoms)
↓
Physical Examination
(Inspect → Palpate → Percuss → Auscultate → Hernia orifices → PR/PV)
↓
Immediate Tests:
β-hCG (females) | ECG | Urine dipstick | Blood glucose
↓
Blood Tests: FBC, CRP, Amylase/Lipase, LFTs, U&E, Lactate, Blood cultures
↓
Imaging:
Erect CXR → Ultrasound (biliary/pelvic) → CT if diagnosis unclear
↓
Targeted management based on likely diagnosis
Create a quick reference guide (PDF checklist) for acute abdominal pain evaluation
ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or not foun…
mkdir -p /home/daytona/workspace/acute-abdomen-guide && python3 -c "import repor…
~/acute-abdomen-guide/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
OUTPUT = "/home/daytona/workspace/acute-abdomen-guide/Acute_Abdomen_Quick_Reference.pdf"
# ── Colour palette ──────────────────────────────────────────────────
RED = colors.HexColor("#C0392B")
DARK_RED = colors.HexColor("#922B21")
ORANGE = colors.HexColor("#E67E22")
BLUE = colors.HexColor("#1A5276")
LIGHT_BG = colors.HexColor("#EBF5FB")
YELLOW = colors.HexColor("#FEF9E7")
GREEN_BG = colors.HexColor("#EAFAF1")
RED_BG = colors.HexColor("#FDEDEC")
GREY_BG = colors.HexColor("#F2F3F4")
WHITE = colors.white
TEXT = colors.HexColor("#17202A")
W, H = A4 # 595 x 842 pt
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=15*mm, rightMargin=15*mm,
topMargin=18*mm, bottomMargin=15*mm,
title="Acute Abdominal Pain – Quick Reference Checklist",
author="Orris Medical Reference"
)
styles = getSampleStyleSheet()
# ── Custom styles ────────────────────────────────────────────────────
def S(name, **kw):
base = kw.pop("parent", "Normal")
s = ParagraphStyle(name, parent=styles[base], **kw)
return s
TITLE_S = S("Title2", fontSize=18, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, spaceAfter=2)
SUBTITLE_S= S("Subtitle2",fontSize=9, textColor=colors.HexColor("#D6EAF8"),
fontName="Helvetica", alignment=TA_CENTER)
SEC_HEAD = S("SecHead", fontSize=10, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_LEFT, spaceAfter=1, spaceBefore=1, leftIndent=4)
BODY = S("Body2", fontSize=8, textColor=TEXT, fontName="Helvetica",
leading=11, spaceAfter=1)
BODY_B = S("BodyB", fontSize=8, textColor=TEXT, fontName="Helvetica-Bold",
leading=11)
SMALL = S("Small", fontSize=7, textColor=colors.HexColor("#555555"),
fontName="Helvetica", leading=9)
FLAG = S("Flag", fontSize=8, textColor=DARK_RED, fontName="Helvetica-Bold",
leading=11)
CB = S("CB", fontSize=8, textColor=TEXT, fontName="Helvetica",
leading=12, leftIndent=2)
def cb(text, bold=False):
"""Checkbox bullet item."""
style = BODY_B if bold else BODY
return Paragraph(f"☐ {text}", style)
def bullet(text, bold=False):
style = BODY_B if bold else BODY
return Paragraph(f"• {text}", style)
def flag(text):
return Paragraph(f"⚠ {text}", FLAG)
def section_header(text, bg=BLUE):
data = [[Paragraph(text, SEC_HEAD)]]
t = Table(data, colWidths=[W - 30*mm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("ROUNDEDCORNERS", (0,0), (-1,-1), [3,3,3,3]),
]))
return t
# ── Content builder ──────────────────────────────────────────────────
story = []
# ╔══════════════════════════════════════════════════════╗
# TITLE BANNER
# ╚══════════════════════════════════════════════════════╝
banner_data = [[
Paragraph("ACUTE ABDOMINAL PAIN", TITLE_S),
Paragraph("Quick Reference Evaluation Checklist", SUBTITLE_S),
]]
banner = Table(banner_data, colWidths=[W - 30*mm])
banner.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_RED),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 8),
("SPAN", (0,0), (-1,-1)),
]))
story.append(banner)
story.append(Spacer(1, 4*mm))
# ── STEP 1 : IMMEDIATE ASSESSMENT ──────────────────────────────────
story.append(section_header("STEP 1 — IMMEDIATE STABILISATION"))
story.append(Spacer(1, 1.5*mm))
vitals_items = [
cb("Assess A-B-C, mental status"),
cb("Measure HR, BP, RR, SpO2, Temperature"),
cb("Establish IV access + draw bloods if unstable"),
cb("Administer IV fluids if haemodynamically compromised"),
cb("Supplemental O₂ if SpO₂ < 94%"),
cb("Nil by mouth if surgical condition suspected"),
]
flags_items = [
flag("BP < 90/60 or HR > 120 → immediate resuscitation + surgical consult"),
flag("Board-like rigidity / peritonism → urgent surgical review"),
flag("Pulsatile abdominal mass → AAA until proven otherwise"),
]
col1 = Table([[i] for i in vitals_items], colWidths=[(W-30*mm)*0.52])
col1.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BG),
("TOPPADDING", (0,0), (-1,-1), 1), ("BOTTOMPADDING", (0,0), (-1,-1), 1),
("LEFTPADDING", (0,0), (-1,-1), 4), ("RIGHTPADDING", (0,0), (-1,-1), 4),
]))
col2 = Table([[i] for i in flags_items], colWidths=[(W-30*mm)*0.46])
col2.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), RED_BG),
("TOPPADDING", (0,0), (-1,-1), 1), ("BOTTOMPADDING", (0,0), (-1,-1), 1),
("LEFTPADDING", (0,0), (-1,-1), 4), ("RIGHTPADDING", (0,0), (-1,-1), 4),
]))
two_col = Table([[col1, col2]], colWidths=[(W-30*mm)*0.52, (W-30*mm)*0.48])
two_col.setStyle(TableStyle([("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 0)]))
story.append(two_col)
story.append(Spacer(1, 3*mm))
# ── STEP 2 : HISTORY ───────────────────────────────────────────────
story.append(section_header("STEP 2 — HISTORY (SOCRATES + Associated Symptoms)"))
story.append(Spacer(1, 1.5*mm))
history_col1 = [
Paragraph("<b>Pain Characterisation</b>", BODY_B),
cb("Site & radiation"),
cb("Onset – sudden vs gradual"),
cb("Character – colicky / constant / burning"),
cb("Severity (1–10)"),
cb("Timing – duration, progression"),
cb("Aggravating / relieving factors"),
Spacer(1, 3),
Paragraph("<b>Vomiting Assessment</b>", BODY_B),
cb("Did pain precede vomiting? (surgical clue)"),
cb("Character – bilious / feculent / coffee-ground"),
cb("Volume & frequency"),
cb("Haematemesis?"),
]
history_col2 = [
Paragraph("<b>Associated Symptoms</b>", BODY_B),
cb("Fever / chills"),
cb("Anorexia"),
cb("Bowel habit change / obstipation"),
cb("Diarrhoea – bloody?"),
cb("Dysuria / haematuria"),
cb("Jaundice"),
cb("Chest pain / dyspnoea"),
Spacer(1, 3),
Paragraph("<b>Past History / Risk Factors</b>", BODY_B),
cb("Prior similar episodes"),
cb("Previous abdominal surgery"),
cb("Medications (NSAIDs, steroids, anticoagulants)"),
cb("Alcohol / drug use"),
cb("LMP — ALL females of reproductive age", bold=True),
]
h_col1_t = Table([[i] for i in history_col1], colWidths=[(W-30*mm)*0.5])
h_col1_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BG),
("TOPPADDING", (0,0), (-1,-1), 1), ("BOTTOMPADDING", (0,0), (-1,-1), 1),
("LEFTPADDING", (0,0), (-1,-1), 4), ("RIGHTPADDING", (0,0), (-1,-1), 4),
]))
h_col2_t = Table([[i] for i in history_col2], colWidths=[(W-30*mm)*0.5])
h_col2_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BG),
("TOPPADDING", (0,0), (-1,-1), 1), ("BOTTOMPADDING", (0,0), (-1,-1), 1),
("LEFTPADDING", (0,0), (-1,-1), 4), ("RIGHTPADDING", (0,0), (-1,-1), 4),
]))
hist_row = Table([[h_col1_t, h_col2_t]], colWidths=[(W-30*mm)*0.5, (W-30*mm)*0.5])
hist_row.setStyle(TableStyle([("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 0)]))
story.append(hist_row)
story.append(Spacer(1, 3*mm))
# ── STEP 3 : PHYSICAL EXAMINATION ─────────────────────────────────
story.append(section_header("STEP 3 — PHYSICAL EXAMINATION"))
story.append(Spacer(1, 1.5*mm))
exam_data = [
[Paragraph("<b>Inspect</b>", BODY_B),
Paragraph("Posture (writhing=colic; still=peritonitis), distension, visible peristalsis, scars, jaundice, pallor", BODY)],
[Paragraph("<b>Auscultate</b>", BODY_B),
Paragraph("Bowel sounds: Absent=ileus/peritonitis; Tinkling/high-pitched=obstruction", BODY)],
[Paragraph("<b>Palpate</b>", BODY_B),
Paragraph("Tenderness location • Guarding (voluntary) • Rigidity (involuntary – true peritonitis) • Rebound tenderness • Masses", BODY)],
[Paragraph("<b>Special Signs</b>", BODY_B),
Paragraph("Murphy's (cholecystitis) • Rovsing's (appendicitis) • Psoas sign (retrocecal appendix) • Obturator sign (pelvic appendix/abscess) • Carnett's (abdominal wall vs visceral)", BODY)],
[Paragraph("<b>Hernial Orifices</b>", BODY_B),
Paragraph("Inguinal, femoral, umbilical — strangulated hernia is a common missed cause", BODY)],
[Paragraph("<b>PR Exam</b>", BODY_B),
Paragraph("Rectal mass, tenderness, blood, pelvic collection", BODY)],
[Paragraph("<b>PV Exam</b>", BODY_B),
Paragraph("(Females) Cervical excitation, adnexal tenderness/mass — exclude ectopic/PID/torsion", BODY)],
[Paragraph("<b>Chest / CVS</b>", BODY_B),
Paragraph("Lung bases (pneumonia), arrhythmia (AF → mesenteric ischemia), murmurs", BODY)],
]
exam_t = Table(exam_data, colWidths=[(W-30*mm)*0.18, (W-30*mm)*0.82])
exam_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), GREY_BG),
("BACKGROUND", (0,0), (0,-1), colors.HexColor("#D5D8DC")),
("TOPPADDING", (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5), ("RIGHTPADDING", (0,0), (-1,-1), 5),
("ROWBACKGROUNDS",(0,0), (-1,-1), [GREY_BG, colors.HexColor("#EAF2FF")]),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#BDC3C7")),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(exam_t)
story.append(Spacer(1, 3*mm))
# ── STEP 4 : BEDSIDE TESTS ──────────────────────────────────────────
story.append(section_header("STEP 4 — BEDSIDE & IMMEDIATE TESTS"))
story.append(Spacer(1, 1.5*mm))
bedside = [
cb("⚡ β-hCG (urine/serum) — ALL females of reproductive age", bold=True),
cb("12-lead ECG — exclude inferior MI / PE"),
cb("Urine dipstick — haematuria (calculi), nitrites (UTI), ketones (DKA)"),
cb("Capillary blood glucose — DKA / hypoglycaemia"),
cb("Temperature (core)"),
]
bedside_t = Table([[i] for i in bedside], colWidths=[W-30*mm])
bedside_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), YELLOW),
("TOPPADDING", (0,0), (-1,-1), 2), ("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 6),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#F0B27A")),
]))
story.append(bedside_t)
story.append(Spacer(1, 3*mm))
# ── STEP 5 : BLOOD TESTS ───────────────────────────────────────────
story.append(section_header("STEP 5 — BLOOD INVESTIGATIONS"))
story.append(Spacer(1, 1.5*mm))
blood_headers = [
Paragraph("<b>Test</b>", BODY_B),
Paragraph("<b>Purpose / Key Finding</b>", BODY_B)
]
blood_rows = [
["FBC / CBC", "Leucocytosis = infection/inflammation; Anaemia = haemorrhage"],
["CRP / ESR", "Inflammatory marker; markedly elevated in peritonitis/sepsis"],
["Amylase / Lipase", "Acute pancreatitis (lipase more sensitive & specific)"],
["LFTs", "Bilirubin ↑, ALP ↑ = biliary; AST/ALT ↑ = hepatitis"],
["Serum Lactate", "⚠ Elevated (>2 mmol/L) = mesenteric ischaemia / sepsis / shock"],
["U&E / Creatinine", "Dehydration, renal disease, electrolyte disturbance"],
["Serum Calcium", "Cause of pancreatitis; hypercalcaemia-related pain"],
["Coagulation (INR/PT)", "Hepatic disease, pre-operative assessment"],
["Group & Save / X-match","Suspected haemorrhage (AAA, ectopic, upper GI bleed)"],
["Blood Cultures (x2)", "If fever ≥38°C or signs of systemic sepsis"],
]
blood_table_data = [blood_headers] + [
[Paragraph(r[0], BODY_B), Paragraph(r[1], BODY)] for r in blood_rows
]
blood_t = Table(blood_table_data, colWidths=[(W-30*mm)*0.28, (W-30*mm)*0.72])
blood_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), BLUE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, colors.HexColor("#EBF5FB")]),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#AED6F1")),
("TOPPADDING", (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5), ("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
# Highlight lactate row
("BACKGROUND", (0,5), (-1,5), colors.HexColor("#FDE8E8")),
]))
story.append(blood_t)
story.append(Spacer(1, 3*mm))
# ── STEP 6 : IMAGING ───────────────────────────────────────────────
story.append(section_header("STEP 6 — IMAGING"))
story.append(Spacer(1, 1.5*mm))
img_headers = [
Paragraph("<b>Modality</b>", BODY_B),
Paragraph("<b>When to Use</b>", BODY_B),
Paragraph("<b>Key Findings</b>", BODY_B),
]
img_rows = [
["Erect CXR\n(FIRST-LINE)",
"All acute abdominal presentations",
"Free air under diaphragm = perforation"],
["AXR",
"Suspected obstruction / volvulus",
"Dilated bowel loops, air-fluid levels, 'coffee bean' (volvulus)"],
["USS Abdomen/Pelvis",
"RUQ pain (biliary), RLQ (appendix), females, child",
"Gallstones, cholecystitis, appendix, ovarian pathology, free fluid, AAA"],
["CT Abdomen/Pelvis\n(IV contrast)",
"Diagnosis unclear after USS; severe/complex presentations",
"Gold standard – appendicitis, diverticulitis, pancreatitis staging, SBO, ischaemia, AAA"],
["MRI / MRCP",
"Pregnancy, biliary pathology, soft tissue",
"Biliary stones, choledocholithiasis – preferred when radiation contraindicated"],
]
img_table_data = [img_headers] + [
[Paragraph(r[0], BODY_B), Paragraph(r[1], BODY), Paragraph(r[2], BODY)] for r in img_rows
]
img_t = Table(img_table_data, colWidths=[(W-30*mm)*0.20, (W-30*mm)*0.33, (W-30*mm)*0.47])
img_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#1F618D")),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, GREEN_BG]),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#A9CCE3")),
("TOPPADDING", (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5), ("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("BACKGROUND", (0,3), (-1,3), colors.HexColor("#D6EAF8")), # CT row highlight
]))
story.append(img_t)
story.append(Spacer(1, 3*mm))
# ── STEP 7 : DIFFERENTIAL DIAGNOSIS ───────────────────────────────
story.append(section_header("STEP 7 — DIFFERENTIAL DIAGNOSIS BY LOCATION"))
story.append(Spacer(1, 1.5*mm))
dd_headers = [
Paragraph("<b>Region</b>", BODY_B),
Paragraph("<b>Key Diagnoses</b>", BODY_B),
]
dd_rows = [
["Epigastric", "PUD, gastritis, acute pancreatitis, GERD, MI (atypical)"],
["RUQ", "Acute cholecystitis, biliary colic, cholangitis, hepatitis, hepatic abscess"],
["LUQ", "Splenic infarct/rupture, gastric volvulus, splenic flexure colitis"],
["Periumbilical","Early appendicitis, small bowel obstruction, mesenteric ischaemia"],
["RLQ", "Appendicitis, Meckel's diverticulitis, Crohn's, ovarian torsion, ectopic pregnancy"],
["LLQ", "Diverticulitis, sigmoid volvulus, IBD, ovarian/tubal pathology"],
["Loin / Flank", "Renal colic (ureteric stone), pyelonephritis, renal infarct"],
["Diffuse", "Peritonitis, gastroenteritis, mesenteric ischaemia, bowel obstruction"],
["Extra-abdominal","Inferior MI, pneumonia (lower lobe), PE, DKA, sickle cell crisis, herpes zoster"],
]
dd_data = [dd_headers] + [
[Paragraph(r[0], BODY_B), Paragraph(r[1], BODY)] for r in dd_rows
]
dd_t = Table(dd_data, colWidths=[(W-30*mm)*0.22, (W-30*mm)*0.78])
dd_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#117A65")),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, GREEN_BG]),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#A9DFBF")),
("TOPPADDING", (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5), ("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("BACKGROUND", (0,9), (-1,9), colors.HexColor("#FDFEFE")),
]))
story.append(dd_t)
story.append(Spacer(1, 3*mm))
# ── RED FLAGS ──────────────────────────────────────────────────────
story.append(section_header("⚠ RED FLAGS — REQUIRE URGENT SURGICAL / SPECIALIST REVIEW", bg=DARK_RED))
story.append(Spacer(1, 1.5*mm))
rf_items = [
"Haemodynamic instability (HR >120 or SBP <90)",
"Board-like rigidity / rebound tenderness (peritonitis)",
"Free air under diaphragm on CXR (perforation)",
"Pulsatile abdominal mass (AAA)",
"Positive β-hCG + acute pain (ectopic until excluded)",
"Vomiting + obstipation + distension (bowel obstruction / strangulation)",
"Serum lactate >2 mmol/L (ischaemia / sepsis)",
"Coffee-ground vomit / haematemesis (upper GI bleed)",
"Severe epigastric pain radiating to back (pancreatitis / AAA)",
"Elderly / immunocompromised with ANY abdominal pain — higher threshold for workup",
]
rf_col1 = rf_items[:5]
rf_col2 = rf_items[5:]
rf1_t = Table([[flag(i)] for i in rf_col1], colWidths=[(W-30*mm)*0.50])
rf1_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), RED_BG),
("TOPPADDING", (0,0), (-1,-1), 2), ("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 4),
]))
rf2_t = Table([[flag(i)] for i in rf_col2], colWidths=[(W-30*mm)*0.50])
rf2_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), RED_BG),
("TOPPADDING", (0,0), (-1,-1), 2), ("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 4),
]))
rf_row = Table([[rf1_t, rf2_t]], colWidths=[(W-30*mm)*0.50, (W-30*mm)*0.50])
rf_row.setStyle(TableStyle([("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 0)]))
story.append(rf_row)
story.append(Spacer(1, 3*mm))
# ── VOMITING CLUES QUICK BOX ───────────────────────────────────────
story.append(section_header("VOMITING PATTERN — DIAGNOSTIC CLUES", bg=ORANGE))
story.append(Spacer(1, 1.5*mm))
vom_data = [
[Paragraph("<b>Vomiting Pattern</b>", BODY_B), Paragraph("<b>Suggests</b>", BODY_B)],
[Paragraph("Pain THEN vomiting", BODY), Paragraph("Surgical condition", BODY)],
[Paragraph("Vomiting THEN pain", BODY), Paragraph("Medical/non-surgical (gastroenteritis)", BODY)],
[Paragraph("Bilious vomiting", BODY), Paragraph("Obstruction distal to duodenum", BODY)],
[Paragraph("Feculent vomiting", BODY), Paragraph("Distal SBO with bacterial proliferation", BODY)],
[Paragraph("Large-volume non-bilious", BODY), Paragraph("Gastric outlet obstruction", BODY)],
[Paragraph("Coffee-ground / haematemesis", BODY), Paragraph("Upper GI bleed (PUD, erosive gastritis)", BODY)],
[Paragraph("Self-limited with diarrhoea", BODY), Paragraph("Gastroenteritis / food-borne illness", BODY)],
]
vom_t = Table(vom_data, colWidths=[(W-30*mm)*0.38, (W-30*mm)*0.62])
vom_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), ORANGE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, YELLOW]),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#F0B27A")),
("TOPPADDING", (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5), ("RIGHTPADDING", (0,0), (-1,-1), 5),
]))
story.append(vom_t)
story.append(Spacer(1, 4*mm))
# ── FOOTER ──────────────────────────────────────────────────────────
story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#AEB6BF")))
story.append(Spacer(1, 1.5*mm))
footer_text = (
"Sources: Yamada's Textbook of Gastroenterology 7e • Bailey & Love's Short Practice of Surgery 28e • "
"Pye's Surgical Handicraft 22e | For clinical decision-making, always apply local protocols and senior review."
)
story.append(Paragraph(footer_text, SMALL))
# ── BUILD ────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved to: {OUTPUT}")
cd /home/daytona/workspace/acute-abdomen-guide && python3 generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/acute-abdomen-guide/
Acute Abdomen Quick Reference
PDF Document · PDF
| Section | Content |
|---|---|
| Step 1 | Immediate stabilisation checklist + red-flag callouts |
| Step 2 | History - SOCRATES, vomiting assessment, associated symptoms, risk factors |
| Step 3 | Physical examination - all signs (Murphy's, Rovsing's, Psoas, etc.) |
| Step 4 | Bedside tests - β-hCG, ECG, urine dipstick, glucose |
| Step 5 | Blood investigations table with purpose of each test |
| Step 6 | Imaging - when to use CXR vs USS vs CT vs MRI |
| Step 7 | Differential diagnosis by abdominal region |
| Vomiting box | Pattern-to-diagnosis quick reference |
| Red flags | 10 urgent warning signs highlighted in red |