Explain same in organise and easy way covering all
| Category | Examples |
|---|---|
| Psychological stress | Anxiety, critical illness |
| Shock | Hypovolemic, septic |
| Severe trauma | — |
| Septicemia | — |
| Burns | Curling's ulcers (posterior duodenum) |
| Brain trauma/tumors | Cushing's ulcers (intracranial lesions → hyperacidity from vagal stimulation) |
| Drugs | Aspirin, steroids, butyazolidine, indomethacin |
| Local irritants | Alcohol, smoking, coffee |
| Feature | Duodenal Ulcer | Gastric Ulcer |
|---|---|---|
| Incidence | 4× more common | Less common |
| Age | 25–50 yrs (5th decade) | Usually >60 yrs (6th decade) |
| Sex | Male > Female (4:1) | Male > Female (3.5:1) |
| Etiology | Mainly H. pylori; also acid hypersecretion, blood group O, genetic factors | H. pylori asymptomatic colonisation; higher risk of duodenal ulcer coexistence; gastritis, bile reflux, drugs, alcohol, tobacco |
| Pathogenesis | Mucosal digestion from hyperacidity (most significant) | Usually normal-to-low acid; hyperacidity only if high serum gastrin |
| Protective gastric mucus barrier may be damaged | Damage to mucus barrier is most significant factor | |
| Pathologic changes | Most common in 1st part of duodenum | Most common along lesser curvature and pyloric antrum |
| Often solitary, 1–2.5 cm, round-to-oval, "punched out" | Grossly similar to duodenal ulcer | |
| Histologically: 4 layers — necrotic → superficial exudative → granulation tissue → cicatrisation | Histologically indistinguishable from duodenal ulcer | |
| Complications | Haemorrhage, perforation, sometimes stenosis | Perforation, haemorrhage, and at times obstruction |
| Malignant risk | Very rare | ⚠️ Can be malignant — always biopsy to exclude gastric carcinoma |
Trigger (H. pylori / NSAIDs / stress)
↓
Disruption of mucosal "barrier"
↓
Acid-pepsin attacks mucosa
↓
Erosion → Ulceration
↓
Acute: superficial, heals without scar
Chronic: deeper, 4-layer histology, complications
| Complication | Notes |
|---|---|
| Haemorrhage | Most common; may be occult or massive (hematemesis/melena) |
| Perforation | Gastric > duodenal risk; surgical emergency |
| Obstruction/Stenosis | Duodenal ulcer healing → pyloric stenosis |
| Malignant transformation | Gastric ulcer only (not duodenal) |
| Penetration | Ulcer burrows into adjacent organ (pancreas, liver) |
Sources: Harsh Mohan Textbook of Pathology, pp. 533–534 | Robbins & Kumar Basic Pathology | Bailey & Love's Short Practice of Surgery, 28th Ed.
Explain same ebut using points and flowcharts diagrams
Medical pathology flowchart diagram titled "Peptic Ulcer - Pathogenesis" showing: A clean white background flowchart with colored boxes. Top box in dark blue: "Trigger Factors: H. pylori / NSAIDs / Stress / Drugs". Arrow down to orange box: "Disruption of Mucosal Barrier (mucus, bicarbonate, blood flow)". Arrow down to red box: "Acid-Pepsin Attacks Mucosa". Then splits into two branches - left branch in yellow: "ACUTE (Stress Ulcer): Superficial, Multiple, Heals without scar, Complications: Bleed/Perforate". Right branch in purple: "CHRONIC Peptic Ulcer: Deeper, 4-layer histology, Gastric or Duodenal, Complications: Bleed/Perforate/Obstruct/Malignancy". Clean medical textbook style, clear arrows, bold labels, readable fonts.
Medical comparison table diagram titled "Gastric Ulcer vs Duodenal Ulcer" with two columns side by side. Left column header in green: "DUODENAL ULCER". Right column header in orange: "GASTRIC ULCER". Rows showing: Incidence: 4x more common vs Less common | Age: 25-50 yrs (5th decade) vs Over 60 yrs (6th decade) | Sex: Male:Female 4:1 vs 3.5:1 | Site: 1st part of duodenum vs Lesser curvature and antrum | Main cause: H. pylori + Hyperacidity vs Mucosal barrier damage | Acid level: HIGH vs NORMAL or LOW | Malignant risk: VERY RARE vs YES - must biopsy | Shape: Solitary, punched out, 1-2.5cm vs Similar to duodenal. Clean white background, medical textbook style, clear grid lines, bold text, color coded columns.
1st part of Duodenum ← MOST COMMON
↓
Lesser Curvature of Stomach
↓
Lower Oesophagus (GERD-related)
↓
Meckel's Diverticulum (ectopic gastric mucosa)
PEPTIC ULCERS
│
┌──────────────┴──────────────┐
▼ ▼
ACUTE (Stress) CHRONIC PEPTIC
Ulcers Ulcers
│ │
Multiple, small, ┌────────┴────────┐
superficial ▼ ▼
GASTRIC DUODENAL
ULCER ULCER
P → Psychological stress
S → Shock
S → Severe trauma
I → Intracranial lesions → Cushing's ulcers
B → Burns (Curling's ulcers — posterior duodenum)
C → Corticosteroids / Drugs (Aspirin, Indomethacin)
D → Drug intake
L → Local irritants (alcohol, smoking, coffee)
Severe stress / Drugs / Burns / Shock
│
▼
Two mechanisms operate:
┌──────────────────────────┐
│ 1. Ischaemic hypoxia │──→ Mucosal cells die
│ of mucosal cells │
└──────────────────────────┘
┌──────────────────────────┐
│ 2. Depletion of │──→ Mucus barrier gone
│ gastric mucus barrier │
└──────────────────────────┘
│
▼
Acid-pepsin attacks unprotected mucosa
│
▼
ACUTE SUPERFICIAL EROSION
Haemorrhage ←──── Acute Stress Ulcer ────→ Perforation
┌───────────────────────────────────────────────────────┐
│ 4 FACTORS IN PEPTIC ULCER PATHOGENESIS │
├───────────────┬───────────────────────────────────────┤
│ FACTOR 1 │ H. pylori Gastritis │
│ FACTOR 2 │ NSAIDs-Induced Mucosal Injury │
│ FACTOR 3 │ Acid-Pepsin Secretions │
│ FACTOR 4 │ Gastritis (background) │
└───────────────┴───────────────────────────────────────┘
H. pylori infection
Parietal cell hyperplasia
Excessive secretory response
Loss of inhibitory signals
Zollinger-Ellison syndrome (gastrinoma → massive acid → ulcers in stomach + duodenum + jejunum)
H. pylori / NSAIDs / Hyperacidity / Gastritis
│
▼
┌───────────────────────────────┐
│ MUCOSAL BARRIER DISRUPTED │
│ (mucus ↓, bicarbonate ↓, │
│ blood flow ↓) │
└───────────────────────────────┘
│
▼
┌───────────────────────────────┐
│ ACID-PEPSIN ATTACKS MUCOSA │
└───────────────────────────────┘
│
▼
┌───────────────────────────────┐
│ MUCOSAL EROSION │
└───────────────────────────────┘
│
┌───────────┴───────────┐
▼ ▼
GASTRIC ULCER DUODENAL ULCER
(normal/low acid; (high acid; H. pylori
barrier damage + hyperacidity main
is key factor) factor)
┌───────────────────┬─────────────────────────┬──────────────────────────┐
│ FEATURE │ DUODENAL ULCER │ GASTRIC ULCER │
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Incidence │ 4× MORE COMMON │ LESS common │
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Age │ 25–50 yrs (5th decade) │ >60 yrs (6th decade) │
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Sex │ Male : Female = 4:1 │ Male : Female = 3.5:1 │
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Main cause │ H. pylori + Hyperacidity │ Mucosal barrier damage │
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Acid level │ HIGH ↑ │ NORMAL or LOW │
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Site │ 1st part of duodenum │ Lesser curvature + antrum│
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Appearance │ Solitary, punched-out, │ Grossly similar │
│ │ 1–2.5 cm, round/oval │ │
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Histology │ 4 layers: │ Indistinguishable from │
│ │ Necrotic → Exudative │ duodenal ulcer │
│ │ → Granulation → Scar │ │
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Malignant risk │ VERY RARE │ ⚠️ YES — always biopsy! │
├───────────────────┼─────────────────────────┼──────────────────────────┤
│ Complications │ Haemorrhage, Perforation,│ Perforation, Haemorrhage,│
│ │ Stenosis │ Obstruction │
└───────────────────┴─────────────────────────┴──────────────────────────┘
CHRONIC PEPTIC ULCER
│
┌────────┬───────┼────────┬──────────┐
▼ ▼ ▼ ▼ ▼
Haemorrhage Perf- Obst- Penetra- Malignant
(most common) oration ruction tion change
(pyloric (gastric
↓ stenosis) ulcer only)
Surgical
emergency
Step 1 → PPI (Omeprazole/Pantoprazole) → Suppress acid → Heals ulcer
Step 2 → H. pylori eradication → Triple therapy:
PPI + Clarithromycin + Amoxicillin (x 14 days)
→ Prevents recurrence
Step 3 → Stop NSAIDs / Smoking / Alcohol
Step 4 (if complications) → Endoscopy → Surgery
| Point | Key Fact |
|---|---|
| No acid = no ulcer | PPIs cure by making patient achlorhydric |
| Most common cause | H. pylori (70–80%) |
| Duodenal : Gastric ratio | 4 : 1 |
| Curling's ulcer | Burns → posterior duodenum |
| Cushing's ulcer | Brain injury → vagal stimulation → hyperacidity |
| Pernicious anaemia | NEVER get peptic ulcers (no acid/pepsin) |
| Zollinger-Ellison | Gastrinoma → massive acid → multiple ulcers stomach + duodenum + jejunum |
| Always biopsy | Gastric ulcer (rule out malignancy) |
| Duodenal histology | 4 layers: Necrotic → Exudative → Granulation → Scar |
Generate a PDF quick reference guide for peptic ulcer diagnosis & treatment
ls -la /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace
mkdir -p /home/daytona/workspace/peptic-ulcer-pdf && python3 -c "from reportlab.lib import colors; print('reportlab ok')"
~/peptic-ulcer-pdf/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 cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus.flowables import Flowable
OUTPUT = "/home/daytona/workspace/peptic-ulcer-pdf/Peptic_Ulcer_Quick_Reference.pdf"
# ── Colours ──────────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B3A6B")
STEEL = colors.HexColor("#2E6DA4")
TEAL = colors.HexColor("#1A7A6E")
ORANGE = colors.HexColor("#E07B2A")
RED = colors.HexColor("#C0392B")
GREEN = colors.HexColor("#1E7F45")
PURPLE = colors.HexColor("#6C3483")
YELLOW_BG = colors.HexColor("#FFF8E1")
BLUE_BG = colors.HexColor("#E8F4FD")
GREEN_BG = colors.HexColor("#E8F8F0")
RED_BG = colors.HexColor("#FDEDEC")
GRAY_BG = colors.HexColor("#F5F5F5")
LIGHT_GRAY= colors.HexColor("#ECEFF1")
WHITE = colors.white
BLACK = colors.HexColor("#212121")
# ── Styles ────────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
COVER_TITLE = S("CoverTitle", fontSize=28, textColor=WHITE,
leading=34, alignment=TA_CENTER, fontName="Helvetica-Bold")
COVER_SUB = S("CoverSub", fontSize=13, textColor=colors.HexColor("#CFE2FF"),
leading=18, alignment=TA_CENTER, fontName="Helvetica")
COVER_META = S("CoverMeta", fontSize=10, textColor=colors.HexColor("#AED6F1"),
leading=14, alignment=TA_CENTER, fontName="Helvetica-Oblique")
SEC_HEAD = S("SecHead", fontSize=13, textColor=WHITE,
leading=17, fontName="Helvetica-Bold", alignment=TA_LEFT)
SUBSEC = S("SubSec", fontSize=11, textColor=NAVY,
leading=15, fontName="Helvetica-Bold", spaceBefore=6)
BODY = S("Body", fontSize=9, textColor=BLACK,
leading=14, fontName="Helvetica", alignment=TA_JUSTIFY)
BULLET = S("Bullet", fontSize=9, textColor=BLACK,
leading=13, fontName="Helvetica", leftIndent=12,
firstLineIndent=-10)
SMALL = S("Small", fontSize=8, textColor=colors.HexColor("#555555"),
leading=11, fontName="Helvetica-Oblique", alignment=TA_CENTER)
TBL_HEAD = S("TblHead", fontSize=9, textColor=WHITE,
leading=12, fontName="Helvetica-Bold", alignment=TA_CENTER)
TBL_CELL = S("TblCell", fontSize=8.5, textColor=BLACK,
leading=12, fontName="Helvetica", alignment=TA_LEFT)
TBL_CELL_C = S("TblCellC", fontSize=8.5, textColor=BLACK,
leading=12, fontName="Helvetica", alignment=TA_CENTER)
BADGE = S("Badge", fontSize=8, textColor=WHITE,
leading=11, fontName="Helvetica-Bold", alignment=TA_CENTER)
FLOW_TEXT= S("FlowText", fontSize=8.5, textColor=BLACK,
leading=12, fontName="Helvetica", alignment=TA_CENTER)
WARN = S("Warn", fontSize=9, textColor=RED,
leading=13, fontName="Helvetica-Bold")
FOOTER = S("Footer", fontSize=7.5, textColor=colors.HexColor("#888888"),
leading=10, fontName="Helvetica-Oblique", alignment=TA_CENTER)
# ── Helper Flowables ──────────────────────────────────────────────────────────
class SectionHeader(Flowable):
def __init__(self, text, bg=NAVY, width=None):
super().__init__()
self.text = text
self.bg = bg
self._width = width or (A4[0] - 3*cm)
self.height = 24
def draw(self):
c = self.canv
c.setFillColor(self.bg)
c.roundRect(0, 0, self._width, self.height, 5, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 11)
c.drawString(10, 7, self.text)
def wrap(self, *args):
return self._width, self.height
class ColorBox(Flowable):
"""A coloured banner box with centred text."""
def __init__(self, text, bg, fg=WHITE, width=None, height=18, radius=4,
font="Helvetica-Bold", fontsize=9):
super().__init__()
self.text = text
self.bg = bg
self.fg = fg
self._width = width or (A4[0] - 3*cm)
self._height = height
self.radius = radius
self.font = font
self.fontsize = fontsize
def draw(self):
c = self.canv
c.setFillColor(self.bg)
c.roundRect(0, 0, self._width, self._height, self.radius, fill=1, stroke=0)
c.setFillColor(self.fg)
c.setFont(self.font, self.fontsize)
c.drawCentredString(self._width / 2, (self._height - self.fontsize) / 2 + 1, self.text)
def wrap(self, *args):
return self._width, self._height
def bullet(text, color=STEEL):
marker = f'<font color="#{hex(int(color.red*255))[2:].zfill(2)}{hex(int(color.green*255))[2:].zfill(2)}{hex(int(color.blue*255))[2:].zfill(2)}">●</font>'
return Paragraph(f"{marker} {text}", BULLET)
def sp(h=4):
return Spacer(1, h)
def hr(color=LIGHT_GRAY, thickness=0.5):
return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=4, spaceBefore=4)
# ── Cover Page ────────────────────────────────────────────────────────────────
class CoverPage(Flowable):
def __init__(self, w, h):
super().__init__()
self._w = w
self._h = h
def draw(self):
c = self.canv
# Gradient-style background: navy top, steel bottom
c.setFillColor(NAVY)
c.rect(0, 0, self._w, self._h, fill=1, stroke=0)
# Accent strip
c.setFillColor(STEEL)
c.rect(0, self._h * 0.38, self._w, self._h * 0.62, fill=1, stroke=0)
c.setFillColor(NAVY)
c.rect(0, self._h * 0.42, self._w, self._h * 0.58, fill=1, stroke=0)
# Bottom accent
c.setFillColor(TEAL)
c.rect(0, 0, self._w, 8, fill=1, stroke=0)
c.setFillColor(ORANGE)
c.rect(0, 8, self._w, 4, fill=1, stroke=0)
def wrap(self, *args):
return self._w, self._h
# ── Build PDF ─────────────────────────────────────────────────────────────────
W, H = A4
MARGIN = 1.5 * cm
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=MARGIN, bottomMargin=MARGIN,
title="Peptic Ulcer Quick Reference Guide",
author="Medical Quick Reference",
subject="Peptic Ulcer Diagnosis & Treatment"
)
story = []
CONTENT_W = W - 2 * MARGIN
# ══════════════════════════════════════════════════════════════════════════════
# PAGE 1 — COVER
# ══════════════════════════════════════════════════════════════════════════════
story.append(CoverPage(CONTENT_W, H - 2*MARGIN))
# Overlay text via table on cover
cover_data = [
[Paragraph("QUICK REFERENCE GUIDE", S("cr1", fontSize=11, textColor=colors.HexColor("#AED6F1"),
fontName="Helvetica", alignment=TA_CENTER, leading=14))],
[Spacer(1, 10)],
[Paragraph("PEPTIC ULCER", S("cr2", fontSize=36, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=42))],
[Paragraph("DISEASE", S("cr3", fontSize=36, textColor=colors.HexColor("#FFD700"),
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=42))],
[Spacer(1, 12)],
[Paragraph("Diagnosis · Pathogenesis · Treatment · Complications", S("cr4",
fontSize=12, textColor=colors.HexColor("#CFE2FF"),
fontName="Helvetica-Oblique", alignment=TA_CENTER, leading=16))],
[Spacer(1, 30)],
[Paragraph("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", S("cr5", fontSize=10,
textColor=TEAL, alignment=TA_CENTER, leading=14))],
[Spacer(1, 12)],
[Paragraph("Based on: Harsh Mohan Textbook of Pathology · Robbins & Kumar Basic Pathology<br/>"
"Bailey & Love's Short Practice of Surgery · Sleisenger & Fordtran's GI Disease",
S("cr6", fontSize=9, textColor=colors.HexColor("#AED6F1"),
fontName="Helvetica-Oblique", alignment=TA_CENTER, leading=13))],
[Spacer(1, 20)],
[Paragraph("For Educational Use Only | May 2026",
S("cr7", fontSize=9, textColor=colors.HexColor("#7FB3D3"),
fontName="Helvetica", alignment=TA_CENTER, leading=12))],
]
cover_table = Table(cover_data, colWidths=[CONTENT_W])
cover_table.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
]))
# Place the cover text over the cover background using a frame trick
# We wrap cover bg + text as a composite table
final_cover = Table(
[[cover_table]],
colWidths=[CONTENT_W],
rowHeights=[H - 2*MARGIN]
)
final_cover.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("ROUNDEDCORNERS", [8]),
("TOPPADDING", (0,0), (-1,-1), 60),
("BOTTOMPADDING", (0,0), (-1,-1), 40),
]))
story.append(final_cover)
story.append(Spacer(1, 10))
# ══════════════════════════════════════════════════════════════════════════════
# PAGE 2 — OVERVIEW + CLASSIFICATION + ACUTE ULCERS
# ══════════════════════════════════════════════════════════════════════════════
# ── Section 1: Overview ──────────────────────────────────────────────────────
story.append(SectionHeader("1 OVERVIEW — PEPTIC ULCERS", bg=NAVY))
story.append(sp(6))
overview_cols = [
# Left column
[
Paragraph("<b>Definition</b>", SUBSEC),
bullet("Areas of degeneration & necrosis of GI mucosa"),
bullet("Exposed to acid-pepsin secretions"),
bullet("<b>Acid is essential</b> — no acid = no ulcer"),
bullet("PPIs render patient achlorhydric → heal ulcers"),
sp(6),
Paragraph("<b>Common Sites</b>", SUBSEC),
bullet("1st part of duodenum <b>(most common)</b>"),
bullet("Stomach — lesser curvature & antrum"),
bullet("Lower oesophagus (GERD-related)"),
bullet("Meckel's diverticulum (ectopic gastric mucosa)"),
sp(6),
Paragraph("<b>Duodenum : Stomach Ratio = 4 : 1</b>",
S("ratio", fontSize=10, textColor=STEEL, fontName="Helvetica-Bold",
leading=14, leftIndent=8)),
],
# Right column — classification box
[
Paragraph("<b>Classification</b>", SUBSEC),
sp(4),
Table([
[Paragraph("PEPTIC ULCERS", S("ct", fontSize=10, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13))],
], colWidths=[7.5*cm], style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("ROUNDEDCORNERS", [6]),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
])),
sp(4),
Table([
[
Table([[Paragraph("TYPE 1\nACUTE\n(Stress) Ulcers", S("bt1",
fontSize=9, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=13))]],
colWidths=[3.4*cm],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), ORANGE),
("ROUNDEDCORNERS",[6]),
("TOPPADDING",(0,0),(-1,-1),10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
])),
Table([[Paragraph("TYPE 2\nCHRONIC\nPeptic Ulcers", S("bt2",
fontSize=9, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=13))]],
colWidths=[3.4*cm],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), STEEL),
("ROUNDEDCORNERS",[6]),
("TOPPADDING",(0,0),(-1,-1),10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
])),
]
], colWidths=[3.6*cm, 3.6*cm], style=TableStyle([
("ALIGN",(0,0),(-1,-1),"CENTER"),
("LEFTPADDING",(0,0),(-1,-1),3),
("RIGHTPADDING",(0,0),(-1,-1),3),
])),
sp(6),
Table([
[
Table([[Paragraph("GASTRIC\nULCER", S("bt3", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13))]],
colWidths=[3.4*cm],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), TEAL),
("ROUNDEDCORNERS",[6]),
("TOPPADDING",(0,0),(-1,-1),8),
("BOTTOMPADDING",(0,0),(-1,-1),8),
])),
Table([[Paragraph("DUODENAL\nULCER", S("bt4", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13))]],
colWidths=[3.4*cm],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), PURPLE),
("ROUNDEDCORNERS",[6]),
("TOPPADDING",(0,0),(-1,-1),8),
("BOTTOMPADDING",(0,0),(-1,-1),8),
])),
]
], colWidths=[3.6*cm, 3.6*cm], style=TableStyle([
("ALIGN",(0,0),(-1,-1),"CENTER"),
("LEFTPADDING",(0,0),(-1,-1),3),
("RIGHTPADDING",(0,0),(-1,-1),3),
])),
]
]
overview_table = Table(
[[overview_cols[0], overview_cols[1]]],
colWidths=[CONTENT_W*0.50, CONTENT_W*0.50],
style=TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
])
)
story.append(overview_table)
story.append(sp(10))
# ── Section 2: Acute Stress Ulcers ───────────────────────────────────────────
story.append(SectionHeader("2 ACUTE (STRESS) ULCERS", bg=ORANGE))
story.append(sp(6))
acute_left = [
Paragraph("<b>Etiology</b>", SUBSEC),
bullet("Psychological stress"),
bullet("Shock (hypovolemic / septic)"),
bullet("Severe trauma"),
bullet("Septicaemia"),
bullet("<b>Burns</b> → <b>Curling's ulcers</b> (posterior duodenum)"),
bullet("<b>Brain injury / tumours</b> → <b>Cushing's ulcers</b><br/>"
"<i>(intracranial → ↑ vagal stimulation → hyperacidity)</i>"),
bullet("Drugs: Aspirin, steroids, indomethacin"),
bullet("Local irritants: alcohol, smoking, coffee"),
sp(6),
Paragraph("<b>Pathogenesis</b>", SUBSEC),
bullet("Ischaemic hypoxic injury to mucosal cells"),
bullet("Depletion of gastric mucus barrier"),
bullet("→ Acid-pepsin attacks unprotected mucosa"),
]
acute_right = [
Paragraph("<b>Morphology</b>", SUBSEC),
Paragraph("<b>Gross:</b>", S("gh", fontSize=9, textColor=STEEL, fontName="Helvetica-Bold", leading=13)),
bullet("Multiple (>3 ulcers in 75% of cases)"),
bullet("Distribution: Stomach > Duodenum (1st part)"),
bullet("Oval/circular, <b>< 1 cm</b> diameter"),
sp(4),
Paragraph("<b>Microscopic:</b>", S("mh", fontSize=9, textColor=STEEL, fontName="Helvetica-Bold", leading=13)),
bullet("Shallow — do NOT invade muscularis"),
bullet("Base shows mild inflammatory reaction"),
bullet("Heal by <b>complete re-epithelialisation</b>"),
bullet("<b>No scar formation</b>"),
sp(6),
Paragraph("<b>Complications</b>", SUBSEC),
Table([
[Paragraph("⚠ Haemorrhage", S("comp1", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)),
Paragraph("⚠ Perforation", S("comp2", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13))]
], colWidths=[CONTENT_W*0.22, CONTENT_W*0.22],
style=TableStyle([
("BACKGROUND", (0,0), (0,0), RED),
("BACKGROUND", (1,0), (1,0), ORANGE),
("ROUNDEDCORNERS", [5]),
("TOPPADDING",(0,0),(-1,-1),6),
("BOTTOMPADDING",(0,0),(-1,-1),6),
]))
]
acute_table = Table(
[[acute_left, acute_right]],
colWidths=[CONTENT_W*0.50, CONTENT_W*0.50],
style=TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
("BACKGROUND", (0,0), (0,0), YELLOW_BG),
("BACKGROUND", (1,0), (1,0), colors.HexColor("#FFF3E0")),
("ROUNDEDCORNERS", [6]),
("TOPPADDING",(0,0),(-1,-1),8),
("BOTTOMPADDING",(0,0),(-1,-1),8),
])
)
story.append(acute_table)
story.append(sp(10))
# ── Section 3: Pathogenesis of Chronic PUD ───────────────────────────────────
story.append(SectionHeader("3 CHRONIC PEPTIC ULCER — PATHOGENESIS", bg=STEEL))
story.append(sp(8))
# Flowchart as a table
fc_style = lambda bg, fg=WHITE: TableStyle([
("BACKGROUND",(0,0),(-1,-1), bg),
("ROUNDEDCORNERS",[8]),
("TOPPADDING",(0,0),(-1,-1),7),
("BOTTOMPADDING",(0,0),(-1,-1),7),
("LEFTPADDING",(0,0),(-1,-1),8),
("RIGHTPADDING",(0,0),(-1,-1),8),
("ALIGN",(0,0),(-1,-1),"CENTER"),
])
arrow_p = Paragraph("▼", S("arr", fontSize=14, textColor=STEEL,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=16))
def fc_box(text, bg, fg=WHITE, width=CONTENT_W*0.6):
return Table([[Paragraph(text, S("fc"+text[:5], fontSize=9, textColor=fg,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13))]],
colWidths=[width], style=fc_style(bg))
def fc_row(box):
return [Spacer(CONTENT_W*0.2, 1), box]
flow_data = [
[Spacer(1,2), fc_box("H. pylori · NSAIDs · Stress · Hyperacidity · Gastritis",
NAVY, width=CONTENT_W*0.85)],
[Spacer(1,2), arrow_p],
[Spacer(1,2), fc_box("DISRUPTION OF MUCOSAL BARRIER\n(↓ mucus · ↓ bicarbonate · ↓ mucosal blood flow)",
STEEL, width=CONTENT_W*0.85)],
[Spacer(1,2), arrow_p],
[Spacer(1,2), fc_box("ACID-PEPSIN ATTACKS UNPROTECTED MUCOSA",
ORANGE, width=CONTENT_W*0.85)],
[Spacer(1,2), arrow_p],
[Spacer(1,2), fc_box("MUCOSAL EROSION → ULCERATION",
RED, width=CONTENT_W*0.85)],
[Spacer(1,2), arrow_p],
]
center_fc = Table(flow_data, colWidths=[CONTENT_W*0.07, CONTENT_W*0.93],
style=TableStyle([
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
("ALIGN",(0,0),(-1,-1),"CENTER"),
("TOPPADDING",(0,0),(-1,-1),1),
("BOTTOMPADDING",(0,0),(-1,-1),1),
]))
story.append(center_fc)
# Branch boxes
branch_data = [[
Table([[Paragraph("GASTRIC ULCER\n\n• Normal / Low acid\n• Mucosal barrier\n damage is KEY",
S("gb", fontSize=9, textColor=WHITE, fontName="Helvetica",
alignment=TA_CENTER, leading=13))]],
colWidths=[CONTENT_W*0.38],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), TEAL),
("ROUNDEDCORNERS",[8]),
("TOPPADDING",(0,0),(-1,-1),10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
])),
Spacer(CONTENT_W*0.08, 1),
Table([[Paragraph("DUODENAL ULCER\n\n• HIGH acid levels\n• H. pylori is\n primary driver",
S("db", fontSize=9, textColor=WHITE, fontName="Helvetica",
alignment=TA_CENTER, leading=13))]],
colWidths=[CONTENT_W*0.38],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), PURPLE),
("ROUNDEDCORNERS",[8]),
("TOPPADDING",(0,0),(-1,-1),10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
])),
]]
branch_table = Table(branch_data, colWidths=[CONTENT_W*0.44, CONTENT_W*0.08, CONTENT_W*0.44],
style=TableStyle([
("ALIGN",(0,0),(-1,-1),"CENTER"),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
]))
story.append(branch_table)
story.append(sp(10))
# 4 factors in 2x2 grid
story.append(Paragraph("<b>4 Key Pathogenic Factors</b>", SUBSEC))
story.append(sp(6))
factor_data = [
[
Table([[
Paragraph("<b>1. H. pylori Infection 🦠</b>", S("f1h", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", leading=13)),
Spacer(1,4),
Paragraph("• 70–80% of PUD associated with H. pylori\n"
"• H. pylori in antrum → duodenal ulcer\n"
"• Gastric colonisation = asymptomatic\n"
"• Only 5–10% of infected → ulcers\n"
"• Identified by histology/culture/serology",
S("f1b", fontSize=8.5, textColor=WHITE, fontName="Helvetica", leading=13)),
]], colWidths=[CONTENT_W*0.46],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), STEEL),
("ROUNDEDCORNERS",[8]),
("TOPPADDING",(0,0),(-1,-1),10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
("LEFTPADDING",(0,0),(-1,-1),10),
("RIGHTPADDING",(0,0),(-1,-1),10),
])),
Table([[
Paragraph("<b>2. NSAIDs-Induced Injury 💊</b>", S("f2h", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", leading=13)),
Spacer(1,4),
Paragraph("• Most common drug class causing PUD\n"
"• Inhibit COX → ↓ prostaglandins\n"
"• ↓ Mucus & bicarbonate secretion\n"
"• Damage endothelial cells + epithelium\n"
"• Risk ↑ with low-dose aspirin in elderly",
S("f2b", fontSize=8.5, textColor=WHITE, fontName="Helvetica", leading=13)),
]], colWidths=[CONTENT_W*0.46],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), ORANGE),
("ROUNDEDCORNERS",[8]),
("TOPPADDING",(0,0),(-1,-1),10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
("LEFTPADDING",(0,0),(-1,-1),10),
("RIGHTPADDING",(0,0),(-1,-1),10),
])),
],
[Spacer(1,8), Spacer(1,8)],
[
Table([[
Paragraph("<b>3. Acid-Pepsin Secretions 🧪</b>", S("f3h", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", leading=13)),
Spacer(1,4),
Paragraph("• Essential for ulcer formation\n"
"• PU never occurs in pernicious anaemia\n"
" (no acid / pepsin-secreting cells)\n"
"• Zollinger-Ellison: gastrinoma → massive\n"
" acid → ulcers in stomach + duodenum +\n"
" jejunum",
S("f3b", fontSize=8.5, textColor=WHITE, fontName="Helvetica", leading=13)),
]], colWidths=[CONTENT_W*0.46],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), TEAL),
("ROUNDEDCORNERS",[8]),
("TOPPADDING",(0,0),(-1,-1),10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
("LEFTPADDING",(0,0),(-1,-1),10),
("RIGHTPADDING",(0,0),(-1,-1),10),
])),
Table([[
Paragraph("<b>4. Gastritis (Background) 🔥</b>", S("f4h", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", leading=13)),
Spacer(1,4),
Paragraph("• Gastritis ALWAYS present near gastric\n"
" ulcer region\n"
"• Gastric ulcer distribution mirrors\n"
" chronic gastritis distribution\n"
"• Other cofactors: smoking, alcohol,\n"
" cirrhosis, renal failure, hyperPTH",
S("f4b", fontSize=8.5, textColor=WHITE, fontName="Helvetica", leading=13)),
]], colWidths=[CONTENT_W*0.46],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), PURPLE),
("ROUNDEDCORNERS",[8]),
("TOPPADDING",(0,0),(-1,-1),10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
("LEFTPADDING",(0,0),(-1,-1),10),
("RIGHTPADDING",(0,0),(-1,-1),10),
])),
],
]
factor_table = Table(factor_data,
colWidths=[CONTENT_W*0.49, CONTENT_W*0.49],
style=TableStyle([
("VALIGN",(0,0),(-1,-1),"TOP"),
("LEFTPADDING",(0,0),(-1,-1),3),
("RIGHTPADDING",(0,0),(-1,-1),3),
]))
story.append(factor_table)
story.append(sp(10))
# ── Section 4: Comparison Table ───────────────────────────────────────────────
story.append(SectionHeader("4 GASTRIC vs DUODENAL ULCER — COMPARISON", bg=TEAL))
story.append(sp(8))
hdr = lambda t: Paragraph(t, TBL_HEAD)
cel = lambda t: Paragraph(t, TBL_CELL)
celc= lambda t: Paragraph(t, TBL_CELL_C)
comp_data = [
[hdr("Feature"), hdr("Duodenal Ulcer"), hdr("Gastric Ulcer")],
[cel("Incidence"), cel("4× MORE COMMON"), cel("Less common")],
[cel("Age"), cel("25–50 yrs (5th decade)"), cel("> 60 yrs (6th decade)")],
[cel("Sex (M:F)"), cel("4 : 1"), cel("3.5 : 1")],
[cel("Main Cause"), cel("H. pylori + Hyperacidity"), cel("Mucosal barrier damage")],
[cel("Acid Level"), cel("HIGH ↑"), cel("Normal or LOW ↓")],
[cel("Site"), cel("1st part of duodenum"), cel("Lesser curvature + antrum")],
[cel("Appearance"), cel("Solitary, punched-out,\n1–2.5 cm, round/oval"), cel("Grossly similar")],
[cel("Histology"), cel("4 layers:\nNecrotic → Exudative\n→ Granulation → Scar"),
cel("Indistinguishable from\nduodenal ulcer")],
[cel("Malignant risk"), cel("Very RARE"), cel("⚠ YES — always biopsy!")],
[cel("Complications"), cel("Haemorrhage, Perforation,\nStenosis"), cel("Perforation, Haemorrhage,\nObstruction")],
]
comp_table = Table(comp_data,
colWidths=[CONTENT_W*0.26, CONTENT_W*0.37, CONTENT_W*0.37],
repeatRows=1)
comp_table.setStyle(TableStyle([
# Header row
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 9),
("ALIGN", (0,0), (-1,0), "CENTER"),
# Feature column
("BACKGROUND", (0,1), (0,-1), colors.HexColor("#E0F2F1")),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("FONTSIZE", (0,1), (0,-1), 8.5),
# Alternating rows
("BACKGROUND", (1,1), (-1,1), WHITE),
("BACKGROUND", (1,2), (-1,2), LIGHT_GRAY),
("BACKGROUND", (1,3), (-1,3), WHITE),
("BACKGROUND", (1,4), (-1,4), LIGHT_GRAY),
("BACKGROUND", (1,5), (-1,5), WHITE),
("BACKGROUND", (1,6), (-1,6), LIGHT_GRAY),
("BACKGROUND", (1,7), (-1,7), WHITE),
("BACKGROUND", (1,8), (-1,8), LIGHT_GRAY),
("BACKGROUND", (1,9), (-1,9), RED_BG),
("BACKGROUND", (0,9), (0,9), RED_BG),
("BACKGROUND", (1,10), (-1,10), WHITE),
# Grid
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("ROWBACKGROUNDS", (0,0), (-1,-1), [None]),
]))
story.append(comp_table)
story.append(sp(10))
# ── Section 5: Incidence + Diagnosis ─────────────────────────────────────────
story.append(SectionHeader("5 CLINICAL FEATURES & DIAGNOSIS", bg=PURPLE))
story.append(sp(6))
diag_left = [
Paragraph("<b>Symptoms</b>", SUBSEC),
bullet("Epigastric pain / burning (most common)"),
bullet("Duodenal ulcer: pain <b>relieved</b> by food/antacids"),
bullet("Gastric ulcer: pain <b>worsened</b> by food"),
bullet("Nausea, vomiting, bloating"),
bullet("Weight loss (esp. gastric ulcer)"),
bullet("Haematemesis or melaena (bleeding)"),
sp(6),
Paragraph("<b>Signs</b>", SUBSEC),
bullet("Epigastric tenderness"),
bullet("Succussion splash (pyloric stenosis)"),
bullet("Peritonism (perforation)"),
bullet("Anaemia (chronic blood loss)"),
]
diag_right = [
Paragraph("<b>Investigations</b>", SUBSEC),
Table([
[Paragraph("TEST", TBL_HEAD), Paragraph("PURPOSE", TBL_HEAD)],
[cel("OGD (endoscopy)"), cel("Gold standard — visualise + biopsy")],
[cel("Biopsy (CLO test)"), cel("H. pylori detection + exclude malignancy")],
[cel("Urea breath test"), cel("Non-invasive H. pylori test")],
[cel("Stool antigen test"), cel("H. pylori — test of cure")],
[cel("Serology (IgG)"), cel("H. pylori (less specific)")],
[cel("Barium meal"), cel("If endoscopy unavailable")],
[cel("FBC / Iron studies"), cel("Assess anaemia from blood loss")],
[cel("AXR / CXR erect"), cel("Free air under diaphragm (perforation)")],
], colWidths=[CONTENT_W*0.25, CONTENT_W*0.23],
style=TableStyle([
("BACKGROUND",(0,0),(-1,0), PURPLE),
("TEXTCOLOR",(0,0),(-1,0), WHITE),
("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
("FONTSIZE",(0,0),(-1,-1),8),
("GRID",(0,0),(-1,-1),0.4, colors.HexColor("#C0C0C0")),
("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, LIGHT_GRAY]),
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
("TOPPADDING",(0,0),(-1,-1),4),
("BOTTOMPADDING",(0,0),(-1,-1),4),
("LEFTPADDING",(0,0),(-1,-1),5),
("RIGHTPADDING",(0,0),(-1,-1),5),
])),
]
diag_table = Table(
[[diag_left, diag_right]],
colWidths=[CONTENT_W*0.40, CONTENT_W*0.60],
style=TableStyle([
("VALIGN",(0,0),(-1,-1),"TOP"),
("LEFTPADDING",(0,0),(-1,-1),4),
("RIGHTPADDING",(0,0),(-1,-1),4),
])
)
story.append(diag_table)
story.append(sp(10))
# ── Section 6: Treatment ──────────────────────────────────────────────────────
story.append(SectionHeader("6 TREATMENT", bg=GREEN))
story.append(sp(6))
# Step-by-step treatment flowchart
steps = [
("STEP 1", "Acid Suppression", "PPI (Omeprazole 20–40 mg BD or Pantoprazole 40 mg OD)\n→ Renders patient achlorhydric → heals mucosa", GREEN),
("STEP 2", "H. pylori Eradication", "Triple Therapy × 14 days:\nPPI + Clarithromycin 500 mg + Amoxicillin 1 g (all BD)\nIf penicillin allergy: replace amoxicillin with Metronidazole 400 mg", STEEL),
("STEP 3", "Lifestyle Modification", "Stop NSAIDs · Stop smoking · Avoid alcohol\nReduce stress · Small frequent meals", TEAL),
("STEP 4", "Test for Eradication", "Urea breath test or stool antigen test\n≥ 4 weeks after completing therapy (off PPIs × 2 weeks)", ORANGE),
("STEP 5", "Surgery (Complications)", "Perforation → Laparotomy + repair\nBleeding → Endoscopic haemostasis → surgery if refractory\nObstruction → Balloon dilatation / gastrojejunostomy", RED),
]
for step, title, detail, col in steps:
step_data = [[
Table([[Paragraph(step, S("st_badge", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13))]],
colWidths=[1.5*cm],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), col),
("ROUNDEDCORNERS",[5]),
("TOPPADDING",(0,0),(-1,-1),10),
("BOTTOMPADDING",(0,0),(-1,-1),10),
])),
Table([[
Paragraph(f"<b>{title}</b>", S("st_t", fontSize=9.5, textColor=col,
fontName="Helvetica-Bold", leading=13)),
Paragraph(detail, S("st_d", fontSize=8.5, textColor=BLACK,
fontName="Helvetica", leading=13)),
]], colWidths=[CONTENT_W - 2.2*cm],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), GRAY_BG),
("TOPPADDING",(0,0),(-1,-1),6),
("BOTTOMPADDING",(0,0),(-1,-1),6),
("LEFTPADDING",(0,0),(-1,-1),8),
("RIGHTPADDING",(0,0),(-1,-1),8),
])),
]]
story.append(Table(step_data, colWidths=[1.8*cm, CONTENT_W - 1.8*cm],
style=TableStyle([
("VALIGN",(0,0),(-1,-1),"MIDDLE"),
("LEFTPADDING",(0,0),(-1,-1),2),
("RIGHTPADDING",(0,0),(-1,-1),2),
])))
story.append(sp(4))
story.append(sp(6))
# ── Section 7: Complications ──────────────────────────────────────────────────
story.append(SectionHeader("7 COMPLICATIONS", bg=RED))
story.append(sp(6))
comp_boxes = [
("Haemorrhage\n(Most Common)", "Haematemesis / melaena\nEndoscopic haemostasis\nSurgery if refractory", RED),
("Perforation", "Gastric > Duodenal\nPeritonitis\nSurgical emergency\nFree air on CXR", ORANGE),
("Obstruction /\nStenosis", "Duodenal ulcer → pyloric stenosis\nVomiting + weight loss\nBalloon dilatation", TEAL),
("Penetration", "Ulcer into pancreas,\nliver, biliary tree\nPain radiates to back", STEEL),
("Malignancy", "GASTRIC ULCER ONLY\n(Duodenal = very rare)\nMUST biopsy all\ngastric ulcers", PURPLE),
]
comp_row = []
for title, detail, col in comp_boxes:
comp_row.append(
Table([[
Paragraph(title, S("cbt", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=13)),
Spacer(1,4),
Paragraph(detail, S("cbd", fontSize=7.5, textColor=WHITE, fontName="Helvetica",
alignment=TA_CENTER, leading=12)),
]], colWidths=[CONTENT_W/5 - 4],
style=TableStyle([
("BACKGROUND",(0,0),(-1,-1), col),
("ROUNDEDCORNERS",[8]),
("TOPPADDING",(0,0),(-1,-1),8),
("BOTTOMPADDING",(0,0),(-1,-1),8),
("LEFTPADDING",(0,0),(-1,-1),5),
("RIGHTPADDING",(0,0),(-1,-1),5),
]))
)
complications_table = Table(
[comp_row],
colWidths=[CONTENT_W/5]*5,
style=TableStyle([
("VALIGN",(0,0),(-1,-1),"TOP"),
("LEFTPADDING",(0,0),(-1,-1),3),
("RIGHTPADDING",(0,0),(-1,-1),3),
])
)
story.append(complications_table)
story.append(sp(10))
# ── Section 8: High-Yield Summary ─────────────────────────────────────────────
story.append(SectionHeader("8 HIGH-YIELD EXAM POINTS", bg=colors.HexColor("#37474F")))
story.append(sp(6))
hye_data = [
["No acid = No ulcer", "PPIs cure by rendering patient achlorhydric"],
["Most common cause", "H. pylori (70–80% of PUD)"],
["D : G ulcer ratio", "Duodenal : Gastric = 4 : 1"],
["Curling's ulcer", "Burns → posterior duodenum"],
["Cushing's ulcer", "Brain injury → vagal stim → hyperacidity"],
["Pernicious anaemia", "NEVER get peptic ulcers (no acid/pepsin)"],
["Zollinger-Ellison", "Gastrinoma → massive acid → ulcers in stomach + duodenum + jejunum"],
["Always biopsy", "Gastric ulcer (rule out malignancy — never skip!)"],
["Duodenal histology", "4 layers: Necrotic → Exudative → Granulation → Scar"],
["Duodenal pain", "RELIEVED by food/antacids (food buffers acid)"],
["Gastric pain", "WORSENED by food (food stimulates acid)"],
["Test of cure", "Urea breath test ≥ 4 weeks after triple therapy"],
]
hye_table = Table(
[[Paragraph(f"<b>{row[0]}</b>", S("hyek", fontSize=8.5, textColor=NAVY,
fontName="Helvetica-Bold", leading=13)),
Paragraph(f"→ {row[1]}", S("hyev", fontSize=8.5, textColor=BLACK,
fontName="Helvetica", leading=13))]
for row in hye_data],
colWidths=[CONTENT_W*0.34, CONTENT_W*0.66],
style=TableStyle([
("ROWBACKGROUNDS", (0,0), (-1,-1), [WHITE, LIGHT_GRAY]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CFD8DC")),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("BACKGROUND", (0,0), (0,-1), colors.HexColor("#E3F2FD")),
("FONTNAME", (0,0), (0,-1), "Helvetica-Bold"),
])
)
story.append(hye_table)
story.append(sp(10))
# ── Footer ─────────────────────────────────────────────────────────────────────
story.append(hr(LIGHT_GRAY, 1))
story.append(Paragraph(
"Sources: Harsh Mohan Textbook of Pathology pp.533–534 · Robbins & Kumar Basic Pathology · "
"Bailey & Love's Short Practice of Surgery 28th Ed. · Sleisenger & Fordtran's GI Disease | "
"For Educational Use Only | May 2026",
FOOTER
))
# ── Build ──────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUTPUT}")
Perfect way to present in exam
Anti arrythmic drugs