~/abdominal-exam/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import ListFlowable, ListItem
OUTPUT = "/home/daytona/workspace/abdominal-exam/Abdominal_Examination_Notes.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=1.8*cm, leftMargin=1.8*cm,
topMargin=2*cm, bottomMargin=2*cm,
title="Comprehensive Notes: Abdominal Examination",
author="Orris Medical"
)
W = A4[0] - 3.6*cm # usable width
styles = getSampleStyleSheet()
# Custom styles
TITLE_STYLE = ParagraphStyle('Title', parent=styles['Title'],
fontSize=20, textColor=colors.HexColor('#1a3a5c'), spaceAfter=6,
fontName='Helvetica-Bold', alignment=TA_CENTER)
SUBTITLE_STYLE = ParagraphStyle('Subtitle', parent=styles['Normal'],
fontSize=11, textColor=colors.HexColor('#2c5282'), spaceAfter=8,
fontName='Helvetica', alignment=TA_CENTER)
H1 = ParagraphStyle('H1', parent=styles['Heading1'],
fontSize=14, textColor=colors.white,
backColor=colors.HexColor('#1a3a5c'),
spaceBefore=14, spaceAfter=6,
fontName='Helvetica-Bold', leftIndent=4, rightIndent=4,
borderPadding=(4,6,4,6))
H2 = ParagraphStyle('H2', parent=styles['Heading2'],
fontSize=12, textColor=colors.HexColor('#1a3a5c'),
spaceBefore=10, spaceAfter=4,
fontName='Helvetica-Bold',
borderPadding=(2,0,2,0))
H3 = ParagraphStyle('H3', parent=styles['Heading3'],
fontSize=10.5, textColor=colors.HexColor('#2c5282'),
spaceBefore=8, spaceAfter=3,
fontName='Helvetica-Bold')
BODY = ParagraphStyle('Body', parent=styles['Normal'],
fontSize=9.5, leading=14, textColor=colors.HexColor('#222222'),
spaceAfter=4, fontName='Helvetica', alignment=TA_JUSTIFY)
BULLET = ParagraphStyle('Bullet', parent=styles['Normal'],
fontSize=9.5, leading=13, textColor=colors.HexColor('#222222'),
spaceAfter=2, fontName='Helvetica',
leftIndent=16, firstLineIndent=-10)
SUB_BULLET = ParagraphStyle('SubBullet', parent=styles['Normal'],
fontSize=9, leading=13, textColor=colors.HexColor('#333333'),
spaceAfter=2, fontName='Helvetica',
leftIndent=28, firstLineIndent=-10)
HIGHLIGHT = ParagraphStyle('Highlight', parent=styles['Normal'],
fontSize=9.5, leading=13,
backColor=colors.HexColor('#fff3cd'),
textColor=colors.HexColor('#7d5a00'),
spaceBefore=4, spaceAfter=4, fontName='Helvetica-Bold',
leftIndent=8, rightIndent=8, borderPadding=(4,6,4,6))
PEARL = ParagraphStyle('Pearl', parent=styles['Normal'],
fontSize=9.5, leading=13,
backColor=colors.HexColor('#d4edda'),
textColor=colors.HexColor('#155724'),
spaceBefore=4, spaceAfter=4, fontName='Helvetica-Bold',
leftIndent=8, rightIndent=8, borderPadding=(4,6,4,6))
MNEMONIC = ParagraphStyle('Mnemonic', parent=styles['Normal'],
fontSize=9.5, leading=13,
backColor=colors.HexColor('#cce5ff'),
textColor=colors.HexColor('#004085'),
spaceBefore=4, spaceAfter=4, fontName='Helvetica-Bold',
leftIndent=8, rightIndent=8, borderPadding=(4,6,4,6))
EXAM_TIP = ParagraphStyle('ExamTip', parent=styles['Normal'],
fontSize=9.5, leading=13,
backColor=colors.HexColor('#f8d7da'),
textColor=colors.HexColor('#721c24'),
spaceBefore=4, spaceAfter=4, fontName='Helvetica-Bold',
leftIndent=8, rightIndent=8, borderPadding=(4,6,4,6))
CAPTION = ParagraphStyle('Caption', parent=styles['Normal'],
fontSize=8.5, textColor=colors.HexColor('#555555'),
fontName='Helvetica-Oblique', alignment=TA_CENTER, spaceAfter=4)
VIVA_Q = ParagraphStyle('VivaQ', parent=styles['Normal'],
fontSize=9.5, leading=14, textColor=colors.HexColor('#1a3a5c'),
spaceAfter=2, fontName='Helvetica-Bold',
leftIndent=8, spaceBefore=6)
VIVA_A = ParagraphStyle('VivaA', parent=styles['Normal'],
fontSize=9.5, leading=13, textColor=colors.HexColor('#222222'),
spaceAfter=6, fontName='Helvetica',
leftIndent=16)
# ---- Table helpers ----
def make_table(data, col_widths=None, header_bg=colors.HexColor('#1a3a5c'), alt_bg=colors.HexColor('#eaf0fb')):
if col_widths is None:
n = len(data[0])
col_widths = [W/n]*n
t = Table(data, colWidths=col_widths, repeatRows=1)
style = [
('BACKGROUND', (0,0), (-1,0), header_bg),
('TEXTCOLOR', (0,0), (-1,0), colors.white),
('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
('FONTSIZE', (0,0), (-1,0), 9),
('ALIGN', (0,0), (-1,-1), 'LEFT'),
('VALIGN', (0,0), (-1,-1), 'TOP'),
('FONTNAME', (0,1), (-1,-1), 'Helvetica'),
('FONTSIZE', (0,1), (-1,-1), 8.5),
('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.white, alt_bg]),
('GRID', (0,0), (-1,-1), 0.4, colors.HexColor('#aaaaaa')),
('TOPPADDING', (0,0), (-1,-1), 3),
('BOTTOMPADDING', (0,0), (-1,-1), 3),
('LEFTPADDING', (0,0), (-1,-1), 5),
('RIGHTPADDING', (0,0), (-1,-1), 5),
]
t.setStyle(TableStyle(style))
return t
def b(text): return Paragraph(f"• {text}", BULLET)
def sb(text): return Paragraph(f" – {text}", SUB_BULLET)
def h1(text): return Paragraph(text, H1)
def h2(text): return Paragraph(text, H2)
def h3(text): return Paragraph(text, H3)
def p(text): return Paragraph(text, BODY)
def sp(n=6): return Spacer(1, n)
def hr(): return HRFlowable(width="100%", thickness=0.5, color=colors.HexColor('#cccccc'), spaceAfter=4)
def must(text): return Paragraph(f"⭐ MUST KNOW: {text}", HIGHLIGHT)
def pearl(text): return Paragraph(f"🟢 Clinical Pearl: {text}", PEARL)
def mnemo(text): return Paragraph(f"🔵 Mnemonic: {text}", MNEMONIC)
def tip(text): return Paragraph(f"🔴 Examiner Tip: {text}", EXAM_TIP)
# ========== BUILD CONTENT ==========
story = []
# COVER
story += [
sp(30),
Paragraph("COMPREHENSIVE MEDICINE NOTES", TITLE_STYLE),
Paragraph("ABDOMINAL EXAMINATION", ParagraphStyle('BigTitle', parent=TITLE_STYLE, fontSize=26, textColor=colors.HexColor('#c0392b'))),
sp(10),
HRFlowable(width="80%", thickness=2, color=colors.HexColor('#1a3a5c'), hAlign='CENTER'),
sp(10),
Paragraph("Clinical Medicine | MBBS Professional Exams | NEET PG | INI-CET | FMGE | MRCP | MD Medicine", SUBTITLE_STYLE),
sp(8),
Paragraph("Sources: S Das Manual of Clinical Surgery 13e · Sleisenger & Fordtran GI & Liver Disease · Bailey & Love's Surgery 28e · Goldman-Cecil Medicine · Campbell-Walsh Urology · Yamada's Gastroenterology 7e", CAPTION),
sp(6),
Paragraph("Prepared by <b>Orris Medical AI</b> | July 2026", CAPTION),
PageBreak(),
]
# ===================== PART 1: INTRODUCTION =====================
story += [h1("PART 1: INTRODUCTION"), sp(4)]
story += [h2("1.1 Objectives of Abdominal Examination"), sp(2)]
story += [
b("Detect organomegaly, masses, tenderness, ascites"),
b("Identify signs of peritonitis, obstruction, perforation"),
b("Determine site, size, shape, consistency, mobility of any swelling"),
b("Assess for vascular abnormalities (bruits, AAA)"),
b("Guide differential diagnosis and investigation plan"),
sp(6),
]
story += [h2("1.2 Nine Abdominal Regions"), sp(2)]
story.append(make_table(
[["Right","Central","Left"],
["Right Hypochondrium","Epigastrium","Left Hypochondrium"],
["Right Lumbar (Flank)","Umbilical","Left Lumbar (Flank)"],
["Right Iliac Fossa","Hypogastrium (Pubic)","Left Iliac Fossa"]],
col_widths=[W/3, W/3, W/3]
))
story += [sp(4), p("Vertical planes: Mid-clavicular lines (lateral edges of rectus). Horizontal planes: Subcostal (L2) and Intertubercular (L5)."), sp(4)]
story += [h2("1.3 Four Abdominal Quadrants"), sp(2)]
story.append(make_table(
[["Quadrant","Contents"],
["RUQ","Liver, gallbladder, right kidney, hepatic flexure, duodenum"],
["LUQ","Stomach, spleen, left kidney, tail of pancreas, splenic flexure"],
["RLQ","Appendix, cecum, right ovary/tube, right ureter"],
["LLQ","Sigmoid colon, left ovary/tube, left ureter"]],
col_widths=[W*0.2, W*0.8]
))
story += [sp(4)]
story += [h2("1.4 Surface Markings of Important Organs"), sp(2)]
story.append(make_table(
[["Organ","Surface Marking"],
["Liver (upper border)","5th rib in MCL (right); 5th ICS (left)"],
["Liver (lower border)","Right costal margin"],
["Spleen","9th-11th ribs, left side; long axis = 10th rib"],
["Gallbladder","Tip of 9th costal cartilage, MCL"],
["McBurney's point","Junction: lateral 1/3 and medial 2/3 of ASIS-umbilicus line (right)"],
["Right kidney","T12-L3 (right slightly lower)"],
["Aortic bifurcation","L4 (level of umbilicus)"]],
col_widths=[W*0.35, W*0.65]
))
story += [sp(4)]
story += [h2("1.5 Abdominal Planes"), sp(2)]
story.append(make_table(
[["Plane","Level","Key Structures"],
["Transpyloric","L1 (halfway xiphoid-umbilicus)","Pylorus, gallbladder fundus, 2nd duodenum, renal hila"],
["Subcostal","L2 (below 10th costal cartilage)","3rd part of duodenum"],
["Transtubercular","L5 (ASIS-ASIS)","Aortic bifurcation"],
["Intertubercular","L5 (iliac crest tubercles)","Cecum, sigmoid origin"]],
col_widths=[W*0.28, W*0.35, W*0.37]
))
story += [sp(8), PageBreak()]
# ===================== PART 2: PREPARATION =====================
story += [h1("PART 2: PREPARATION"), sp(4)]
story += [h2("2.1 Patient & Examiner Preparation"), sp(2)]
story += [
b("Ask patient to empty bladder before examination"),
b("Expose: nipple line to inguinal ligaments"),
b("Supine position, one pillow, arms by sides (NOT behind head - tenses abdomen)"),
b("Examiner at patient's right side; kneel to be at level of abdomen"),
b("Warm hands (cold hands cause voluntary guarding)"),
b("Begin away from site of pain; watch the patient's face"),
sp(4),
tip("In OSCE: always wash hands, introduce yourself, explain procedure, ask about pain before touching."),
sp(4),
]
story += [h2("2.2 Examination Sequence"), sp(2)]
story += [
mnemo("ILPPA: Inspect → Listen (Auscultate) → Percuss → Palpate → Assess special signs"),
sp(4),
p("<b>Standard sequence:</b> Inspection → Palpation → Percussion → Auscultation"),
p("<b>Acute abdomen:</b> Inspection → Auscultation (first, before palpation) → Palpation → Percussion"),
sp(8), PageBreak()
]
# ===================== PART 3: INSPECTION =====================
story += [h1("PART 3: INSPECTION"), sp(4)]
story += [
mnemo("SCDS VERHF: Shape/Symmetry – Contour – Distension – Scars – Veins – Eversion of umbilicus – Respiration – Hernias – Fistulae"),
sp(6),
]
story += [h2("3.1 Distension - 5 Fs (+ 1 F)"), sp(2)]
story += [b("Fat (obesity)"), b("Fluid (ascites)"), b("Flatus (intestinal obstruction)"), b("Feces (constipation)"), b("Fetus (pregnancy)"), b("Fibroid / other masses"), sp(4)]
story += [pearl("In obesity: umbilicus deeply INVERTED. In ascites: umbilicus EVERTED. Key differentiator!"), sp(4)]
story += [h2("3.2 Scars and Their Significance"), sp(2)]
story.append(make_table(
[["Scar Position","Surgery"],
["Right subcostal (Kocher's)","Cholecystectomy, biliary surgery"],
["Left subcostal","Splenectomy"],
["Midline upper","Gastrectomy, peptic ulcer surgery"],
["Right iliac fossa (gridiron/McBurney's)","Appendicectomy"],
["Pfannenstiel","Cesarean section, pelvic surgery"],
["Loin (flank)","Nephrectomy"],
["Paramedian","Colostomy, laparotomy"]],
col_widths=[W*0.45, W*0.55]
))
story += [sp(4), tip("Linear scar = primary healing. Broad/irregular scar = wound infection/dehiscence."), sp(4)]
story += [h2("3.3 Dilated Veins / Caput Medusae"), sp(2)]
story.append(make_table(
[["Finding","Blood Flow Direction","Cause"],
["Caput medusae (radiates from umbilicus)","AWAY from umbilicus (all directions)","Portal hypertension"],
["Lateral abdominal veins","Upward (cephalad)","IVC obstruction"],
["Inferior epigastric veins","Downward","SVC obstruction"]],
col_widths=[W*0.38, W*0.32, W*0.30]
))
story += [sp(4), must("In portal hypertension - flow is AWAY from umbilicus. In IVC obstruction - flow is UPWARD on both sides."), sp(4)]
story += [h2("3.4 Umbilical Changes"), sp(2)]
story.append(make_table(
[["Change","Cause"],
["Everted","Ascites, large abdominal mass"],
["Inverted","Normal, obesity"],
["Displaced downward (Tanyol's sign)","Ascites"],
["Displaced upward","Pelvic mass, pregnancy"],
["Sister Mary Joseph's nodule (hard)","Intra-abdominal malignancy (gastric, ovarian, colon)"],
["Blue discoloration (Cullen's sign)","Retroperitoneal hemorrhage (acute pancreatitis, ruptured ectopic)"],
["Discharge","Urachal fistula, umbilical sinus"]],
col_widths=[W*0.4, W*0.6]
))
story += [sp(4)]
story += [h2("3.5 Skin Signs - High Yield"), sp(2)]
story.append(make_table(
[["Sign","Appearance","Disease"],
["Cullen's sign","Bluish periumbilical discoloration","Hemoperitoneum (pancreatitis, ectopic)"],
["Grey Turner's sign","Bruising in flanks/loins","Retroperitoneal hemorrhage (pancreatitis)"],
["Caput medusae","Dilated periumbilical veins","Portal hypertension"],
["Striae","Silver/pink streaks","Pregnancy, ascites, Cushing's, obesity"],
["Erythema ab igne","Mottled lattice pigmentation","Hot-water bottle use - chronic pain"],
["Spider angiomata","Central arteriole + radiating vessels","Liver disease (SVC territory)"]],
col_widths=[W*0.25, W*0.37, W*0.38]
))
story += [sp(4)]
story += [h2("3.6 Visible Peristalsis"), sp(2)]
story.append(make_table(
[["Location","Pattern","Disease"],
["Upper abdomen (left to right)","Oblique / gastric waves","Gastric outlet obstruction (pyloric stenosis)"],
["Central abdomen","Ladder pattern","Small bowel obstruction"],
["Lower abdomen","Rare","Large bowel obstruction"]],
col_widths=[W*0.3, W*0.3, W*0.4]
))
story += [sp(4), pearl("Visible peristalsis is ALWAYS pathological in adults. Seen in thin/cachectic patients with obstruction only."), sp(8), PageBreak()]
# ===================== PART 4: PALPATION =====================
story += [h1("PART 4: PALPATION"), sp(4)]
story += [h2("4.1 Guarding vs. Rigidity"), sp(2)]
story.append(make_table(
[["Feature","Voluntary Guarding","Involuntary Rigidity"],
["Cause","Anxiety, anticipation","Peritoneal irritation"],
["Relaxes with distraction","Yes","No"],
["With deep breathing","Relaxes","Persists"],
["Extreme form","–","Board-like rigidity (perforated PU)"],
["Clinical significance","Less specific","Highly specific for peritonitis"]],
col_widths=[W*0.38, W*0.31, W*0.31]
))
story += [sp(4), tip("To differentiate: Ask the patient to breathe deeply - voluntary guarding relaxes; involuntary rigidity persists."), sp(6)]
story += [h2("4.2 Tenderness Types"), sp(2)]
story.append(make_table(
[["Type","Definition","Clinical Significance"],
["Superficial","Pain on light pressure","Parietal peritonitis, cutaneous lesion"],
["Deep","Pain on deep pressure","Visceral pathology"],
["Rebound (Blumberg's)","Pain on sudden release","Peritonitis"],
["Referred rebound (Rovsing's)","LIF pressure → pain in RIF","Appendicitis"]],
col_widths=[W*0.28, W*0.37, W*0.35]
))
story += [sp(6)]
story += [h2("4.3 Describing Abdominal Masses - SITS CMTD"), sp(2)]
story += [
mnemo("SITS CMTD: Site – Involvement (moves with respiration?) – Tenderness – Size – Consistency – Mobility – Transillumination – Definition of edges"),
sp(4),
b("Also: Can you get above/below it? Pulsatile? Ballottable? Bruit?"),
sp(6),
]
story += [h2("4.4 Liver Palpation"), sp(2)]
story += [
h3("Technique"),
b("Start in RIF with fingers pointing toward right hypochondrium"),
b("Ask patient to breathe in - feel for liver edge descending on inspiration"),
b("Move hand superiorly after each breath until you reach costal margin"),
b("Use 'dipping' technique in ascites"),
sp(4),
h3("Normal Findings"),
b("Not normally palpable, or just palpable at costal margin in thin individuals"),
b("If palpable: note size (cm below costal margin in MCL), consistency, edge, surface, tenderness, pulsatility"),
sp(4),
]
story.append(make_table(
[["Hepatomegaly Grade","Below Costal Margin"],
["Mild","2-4 cm"],
["Moderate","4-8 cm"],
["Massive",">8 cm"]],
col_widths=[W*0.5, W*0.5]
))
story += [sp(4)]
story.append(make_table(
[["Liver Characteristic","Disease"],
["Tender, smooth, soft","Hepatitis, CCF, Budd-Chiari"],
["Tender, pulsatile","Tricuspid regurgitation, CCF"],
["Hard, nodular, irregular","HCC, metastases"],
["Firm, non-tender","Cirrhosis (often small in advanced)"],
["Craggy, rock-hard","Metastatic carcinoma"],
["Massive, smooth","Amyloidosis, fatty liver, malaria"],
["Hepatic bruit","HCC, hepatic artery aneurysm"],
["Normal liver span (percussion)","8-12 cm in mid-clavicular line"]],
col_widths=[W*0.45, W*0.55]
))
story += [sp(4), must("In cirrhosis, liver is often SMALL, firm, irregular. Massively enlarged hard nodular liver = HCC or secondaries."), sp(6)]
story += [h2("4.5 Spleen Palpation"), sp(2)]
story += [
h3("Technique"),
b("Start in RIF; progress toward left hypochondrium in steps"),
b("Ask patient to breathe deeply; spleen descends on inspiration"),
b("Roll patient slightly to right lateral if not palpable supine"),
b("Bimanual: left hand on left 9th-11th ribs posteriorly"),
sp(4),
h3("Features of Splenomegaly"),
b("Cannot get above it (under left rib cage)"),
b("Notch on medial border - pathognomonic when palpable"),
b("Moves with respiration"),
b("Dull to percussion anteriorly"),
b("Ballottement NOT possible (unlike kidney)"),
sp(4),
]
story.append(make_table(
[["Grade","Description"],
["Grade 1","Just palpable below left costal margin"],
["Grade 2","Up to the umbilicus"],
["Grade 3","Extends to the right of umbilicus"],
["Grade 4","Massive - into pelvis"]],
col_widths=[W*0.3, W*0.7]
))
story += [sp(4)]
story.append(make_table(
[["Mild-Moderate Splenomegaly","Massive Splenomegaly"],
["Viral hepatitis","CML (most common in India)"],
["Cirrhosis + portal hypertension","Kala-azar (visceral leishmaniasis)"],
["Infective endocarditis","Myelofibrosis"],
["SLE","Chronic malaria (HMS)"],
["Hemolytic anemias","Thalassemia major"],
["Lymphoma","Gaucher's disease"],
["Typhoid, EBV","–"]],
col_widths=[W*0.5, W*0.5]
))
story += [sp(4), mnemo("Massive splenomegaly: CCGMaTh - CML, Chronic malaria, Gaucher's, Myelofibrosis, ala-azar (Kala-azar), Thalassemia"), sp(4)]
story += [
pearl("Spleen vs. Kidney: Spleen has notch; cannot get above spleen; spleen moves more with respiration; no ballottement; band of colonic resonance anterior to kidney only."),
sp(8), PageBreak()
]
story += [h2("4.6 Kidney Palpation"), sp(2)]
story += [
h3("Bimanual Ballottement Technique"),
b("Left hand in renal angle (loin) posteriorly"),
b("Right hand anteriorly in flank below costal margin"),
b("Push forward with left hand - kidney felt as ballottable mass anteriorly"),
sp(4),
h3("Renal Angle Tenderness (Murphy's Punch Test)"),
b("Firm percussion over costovertebral angle (12th rib + erector spinae)"),
b("Positive = pyelonephritis, perinephric abscess, renal calculi"),
sp(4),
]
story.append(make_table(
[["Unilateral Enlarged Kidney","Bilateral Enlarged Kidneys"],
["Renal cell carcinoma","Polycystic kidney disease (PKD)"],
["Hydronephrosis","Bilateral hydronephrosis"],
["Perinephric abscess","Amyloidosis"],
["Pyonephrosis","Diabetic nephropathy (early)"]],
col_widths=[W*0.5, W*0.5]
))
story += [sp(6)]
story += [h2("4.7 Gallbladder - Murphy's Sign & Courvoisier's Law"), sp(2)]
story += [
h3("Murphy's Sign"),
b("Technique: Place fingers over GB fossa; ask patient to breathe in deeply"),
b("Positive: Inspiratory arrest (patient catches breath) due to pain"),
b("Disease: Acute cholecystitis"),
b("False positive: Hepatitis, liver abscess, sub-diaphragmatic abscess"),
tip("Must check the LEFT side (control) - must be NEGATIVE on left."),
sp(4),
]
story.append(make_table(
[["Courvoisier's Law"],
["\"If the gallbladder is palpable and the patient is jaundiced, the cause is UNLIKELY to be gallstones.\""]],
col_widths=[W], header_bg=colors.HexColor('#c0392b')
))
story += [sp(4)]
story.append(make_table(
[["Jaundice + Palpable GB (Malignant)","Jaundice + Non-palpable GB (Stone)"],
["Ca head of pancreas","Gallstones (fibrotic GB can't distend)"],
["Ca ampulla of Vater","Hepatitis"],
["Periampullary carcinoma","Cirrhosis"],
["Choledochal cyst","Primary biliary cholangitis"]],
col_widths=[W*0.5, W*0.5]
))
story += [sp(4), must("Courvoisier's law = palpable GB in obstructive jaundice suggests MALIGNANCY, not stones."), sp(8), PageBreak()]
# ===================== PART 5: PERCUSSION =====================
story += [h1("PART 5: PERCUSSION"), sp(4)]
story += [h2("5.1 Percussion for Ascites"), sp(2)]
story.append(make_table(
[["Sign","Technique","Minimum Fluid Detected"],
["Shifting dullness","Dullness shifts as patient turns to side","~1500 mL"],
["Fluid thrill","Impulse transmitted across fluid with midline block","~3000 mL (tense ascites)"],
["Puddle sign","Knee-elbow position; percuss centrally","~120 mL (minimal ascites)"],
["Ultrasound (reference)","Imaging","10-20 mL"]],
col_widths=[W*0.28, W*0.46, W*0.26]
))
story += [sp(4)]
story += [
h3("Shifting Dullness - Step-by-Step"),
b("Percuss from umbilicus to right flank - note resonance-dullness interface"),
b("Percuss from umbilicus to left flank - note interface"),
b("Keep finger at dull spot; turn patient to opposite side; wait 30 seconds"),
b("Re-percuss: previously dull = now resonant (fluid moved away)"),
b("Previously resonant area now dull = fluid shifted there"),
b("Positive = Ascites (sensitivity ~83%, specificity ~56%)"),
sp(4),
]
story += [h2("5.2 Splenic Percussion"), sp(2)]
story.append(make_table(
[["Sign","Technique","Positive Finding","Disease"],
["Traube's space","Percuss semilunar area (L 6th rib - costal margin - AAL)","Dull (normally resonant)","Splenomegaly, left pleural effusion"],
["Castell's sign","Percuss 8th-9th ICS in AAL on full inspiration","Dull (normally resonant)","Splenomegaly"]],
col_widths=[W*0.22, W*0.35, W*0.2, W*0.23]
))
story += [sp(4)]
story += [h2("5.3 Liver Percussion"), sp(2)]
story += [
b("Normal liver span: 8-12 cm in right MCL"),
b("Percuss from lung resonance downward (upper border) and from below umbilicus upward (lower border)"),
b("Absent liver dullness = FREE GAS under diaphragm = pneumoperitoneum (perforated viscus)"),
must("Absent liver dullness = perforated hollow viscus (most common: perforated peptic ulcer). Erect CXR is best initial investigation."),
sp(4),
]
story += [h2("5.4 Succussion Splash"), sp(2)]
story += [
b("Place stethoscope over epigastrium; shake patient from side to side"),
b("Positive (splashing sound): Gastric outlet obstruction / large gastric residual"),
b("Positive only if >3 hours post-meal (normal stomach should have emptied)"),
pearl("Succussion splash = gastric outlet obstruction (pyloric stenosis, gastroparesis, carcinoma pylorus)."),
sp(8), PageBreak()
]
# ===================== PART 6: AUSCULTATION =====================
story += [h1("PART 6: AUSCULTATION"), sp(4)]
story += [h2("6.1 Bowel Sounds"), sp(2)]
story.append(make_table(
[["Finding","Description","Cause"],
["Normal","5-15 gurgles/min, every few seconds","Normal gut motility"],
["Hyperactive/Tinkling","Loud, frequent, high-pitched, metallic rushes","Mechanical obstruction (early), gastroenteritis"],
["Hypoactive","Decreased frequency","Early ileus, post-op"],
["Absent (>2 min, multiple quadrants)","No sounds","Paralytic ileus, peritonitis, late obstruction"]],
col_widths=[W*0.27, W*0.38, W*0.35]
))
story += [sp(4), tip("Listen for at least 2 minutes in more than one quadrant before declaring bowel sounds absent."), sp(4)]
story += [h2("6.2 Vascular Sounds"), sp(2)]
story.append(make_table(
[["Sound","Location","Cause"],
["Systolic bruit (epigastric)","Epigastrium","Celiac artery stenosis, AAA"],
["Systolic bruit (renal)","Paraumbilical (L/R)","Renal artery stenosis (renovascular HT)"],
["Venous hum","Around umbilicus","Portal hypertension (Cruveilhier-Baumgarten)"],
["Hepatic rub","RUQ","HCC, hepatic infarction"],
["Splenic rub","LUQ","Splenic infarction, perisplenitis"]],
col_widths=[W*0.3, W*0.28, W*0.42]
))
story += [sp(4), must("Venous hum at umbilicus = portal hypertension (Cruveilhier-Baumgarten murmur = recanalized paraumbilical vein)."), sp(8), PageBreak()]
# ===================== PART 7: ASCITES =====================
story += [h1("PART 7: EXAMINATION OF ASCITES"), sp(4)]
story += [h2("7.1 SAAG Classification"), sp(2)]
story.append(make_table(
[["SAAG ≥ 1.1 g/dL (Portal HTN)","SAAG < 1.1 g/dL (Non-Portal HTN)"],
["Cirrhosis (80% of all ascites)","Peritoneal tuberculosis"],
["Cardiac failure (CCF)","Peritoneal carcinomatosis"],
["Budd-Chiari syndrome","Pancreatitis"],
["Portal vein thrombosis","Nephrotic syndrome"],
["Alcoholic hepatitis","Meigs' syndrome"],
["Sinusoidal obstruction","Chylous ascites"]],
col_widths=[W*0.5, W*0.5]
))
story += [sp(4), mnemo("SAAG < 1.1 causes: MALT CAP - Malignancy, Amylase (pancreatitis), Lymphoma, TB, Chylous, Autoimmune, Peritonitis"), sp(4)]
story += [h2("7.2 Clinical Signs of Ascites"), sp(2)]
story.append(make_table(
[["Sign","Description","Volume Required"],
["Flank fullness","Fluid in flanks on inspection","~500 mL"],
["Shifting dullness","Dullness moves on turning","~1,500 mL"],
["Fluid thrill","Transmitted impulse across fluid","~3,000 mL"],
["Everted umbilicus","Fluid pressure pushes out","Moderate-large"],
["Horseshoe dullness","Flanks + suprapubic dull; umbilicus resonant","Moderate"],
["Tanyol's sign","Umbilicus displaced downward","Large"]],
col_widths=[W*0.28, W*0.45, W*0.27]
))
story += [sp(4)]
story += [h2("7.3 Ascites vs. Ovarian Cyst (Key Distinction)"), sp(2)]
story.append(make_table(
[["Feature","Ascites","Ovarian Cyst"],
["Percussion flanks","Dull (fluid pools in flanks)","Resonant (bowel displaced laterally)"],
["Percussion centre","Resonant","Dull (cyst is central)"],
["Shifting dullness","Present","Absent"],
["Fluid thrill","Present (if tense)","Absent"],
["Can get above it","No (fills peritoneum)","Yes (intraperitoneal)"]],
col_widths=[W*0.28, W*0.36, W*0.36]
))
story += [sp(4), must("OVARIAN CYST = CENTRAL DULLNESS + LATERAL RESONANCE (opposite to ascites!)"), sp(8), PageBreak()]
# ===================== PART 8: SPECIAL CLINICAL SIGNS =====================
story += [h1("PART 8: SPECIAL CLINICAL SIGNS"), sp(4)]
story.append(make_table(
[["Sign","Mechanism / Technique","Positive Finding","Disease"],
["Murphy's sign","Palpate GB fossa; ask to breathe in","Inspiratory arrest","Acute cholecystitis"],
["McBurney's tenderness","Press 1/3 ASIS to umbilicus (R)","Max tenderness here","Appendicitis"],
["Rovsing's sign","Deep palpate LIF","Pain referred to RIF","Appendicitis"],
["Psoas sign","Extend R hip / raise R leg against resistance","RIF pain","Retrocecal appendicitis"],
["Obturator sign","Flex + internally rotate R hip","RIF/hypogastric pain","Pelvic appendicitis"],
["Blumberg's sign","Deep pressure then sudden release","Pain worse on release","Peritonitis"],
["Carnett's sign","Palpate; ask to raise head (tense rectus)","Pain increases = wall pain","Abdominal wall pain"],
["Grey Turner's sign","Inspect flanks (delayed 24-48h)","Bruising in flanks","Hemorrhagic pancreatitis"],
["Cullen's sign","Inspect periumbilical region","Blue periumbilical discoloration","Hemorrhagic pancreatitis"],
["Kehr's sign","Trendelenburg; left shoulder pain","Left shoulder tip pain","Splenic rupture"],
["Courvoisier's sign","Palpate GB in jaundiced patient","Non-tender palpable GB","Ca head of pancreas"],
["Castell's sign","Percuss 8th-9th ICS in AAL on inspiration","Dull (normally resonant)","Splenomegaly"],
["Traube's space","Percuss semilunar LUQ area","Dull (normally resonant)","Splenomegaly"],
["Markle sign (jar sign)","Patient drops onto heels from tiptoes","Abdominal pain","Peritonitis"],
["Dance sign","Inspect/palpate RIF","Empty RIF (cecum absent)","Intussusception"]],
col_widths=[W*0.2, W*0.3, W*0.25, W*0.25]
))
story += [sp(8), PageBreak()]
# ===================== PART 9: HERNIAS =====================
story += [h1("PART 9: EXAMINATION OF HERNIAS"), sp(4)]
story.append(make_table(
[["Feature","Indirect Inguinal","Direct Inguinal","Femoral"],
["Age","Any (congenital)","Older adults","Middle-aged women > men"],
["Path","Through deep inguinal ring; may reach scrotum","Through Hesselbach's triangle","Through femoral canal"],
["Controlled by ring pressure","YES","No","N/A"],
["Risk of strangulation","Moderate","Low","HIGH"],
["Common side","Right > left","Bilateral","Right"],
["In women","Rare","Rare","More common than inguinal"]],
col_widths=[W*0.27, W*0.25, W*0.24, W*0.24]
))
story += [sp(4)]
story.append(make_table(
[["Hernia Type","Characteristics"],
["Umbilical (infant)","At umbilicus; often resolves by age 2"],
["Para-umbilical (adult)","Above/below umbilicus; does NOT resolve; needs repair"],
["Incisional","At scar site; appears on straining; risk: infection, obesity, steroids"],
["Epigastric","Along linea alba above umbilicus; often asymptomatic"]],
col_widths=[W*0.32, W*0.68]
))
story += [sp(8), PageBreak()]
# ===================== PART 10: CLINICAL CASES =====================
story += [h1("PART 10: COMMON CLINICAL CASES"), sp(4)]
story += [h2("10.1 Chronic Liver Disease (CLD) / Cirrhosis"), sp(2)]
story += [
mnemo("SPACED: Spider nevi, Palmar erythema, Asterixis, Caput medusae/Clubbing, Erythema (palmar), Dupuytren's"),
sp(4),
]
story.append(make_table(
[["System","Signs"],
["Hands/Nails","Leukonychia (white nails), palmar erythema, Dupuytren's contracture, clubbing, Terry's nails"],
["Face","Jaundice, parotid enlargement, scleral icterus"],
["Skin","Spider angiomata (>5 significant; SVC territory), jaundice"],
["Hormonal","Gynecomastia, testicular atrophy, loss of axillary/pubic hair"],
["CNS","Asterixis (flapping tremor), fetor hepaticus, encephalopathy"],
["Abdomen","Hepatomegaly or shrunken liver, splenomegaly, ascites, caput medusae, venous hum, scrotal edema"]],
col_widths=[W*0.25, W*0.75]
))
story += [sp(6)]
story += [h2("10.2 Acute Appendicitis"), sp(2)]
story += [
b("Central/periumbilical colicky pain (visceral T10) → migrates to RIF (somatic)"),
b("Signs: McBurney's tenderness, Rovsing's, guarding, Blumberg's, Psoas sign (retrocecal), Obturator sign (pelvic)"),
sp(4),
]
story.append(make_table(
[["Alvarado Score (MANTREL)","Points"],
["Migration of pain to RIF","1"],
["Anorexia","1"],
["Nausea/Vomiting","1"],
["Tenderness in RIF","2"],
["Rebound Tenderness","1"],
["Elevated Temperature (>37.3°C)","1"],
["Leukocytosis (WBC >10,000)","2"],
["TOTAL","10"]],
col_widths=[W*0.7, W*0.3]
))
story += [sp(4), must("Alvarado ≥7 = surgical. 5-6 = observe. ≤4 = appendicitis unlikely."), sp(4)]
story.append(make_table(
[["Children","Adult","Adult Female","Elderly"],
["Gastroenteritis","Crohn's disease","Mittelschmerz","Diverticulitis"],
["Mesenteric adenitis","Ureteric colic","PID","Intestinal obstruction"],
["Meckel's diverticulitis","Perforated peptic ulcer","Ectopic pregnancy","Colonic carcinoma"],
["Intussusception","Pancreatitis","Torsion of ovarian cyst","Mesenteric infarction"]],
col_widths=[W/4, W/4, W/4, W/4]
))
story += [sp(6)]
story += [h2("10.3 Acute Pancreatitis"), sp(2)]
story += [
b("Severe epigastric pain radiating to back ('boring' - patient leans forward for relief)"),
b("Patient lies STILL (unlike ureteric colic where patient writhes)"),
b("Nausea, vomiting, abdominal distension, absent bowel sounds (ileus)"),
b("Grey Turner's sign (flanks) + Cullen's sign (periumbilical) = hemorrhagic pancreatitis"),
b("Epigastric tenderness with guarding; no board-like rigidity (unless complicated)"),
b("Investigation: serum amylase >3x ULN / lipase (more specific); CT (Balthazar score)"),
sp(4),
]
story += [h2("10.4 Intestinal Obstruction"), sp(2)]
story.append(make_table(
[["Feature","Mechanical Obstruction","Paralytic Ileus"],
["Pain","Colicky","Absent/dull"],
["Bowel sounds","High-pitched, tinkling (early); absent (late)","Absent"],
["Visible peristalsis","Yes (ladder pattern)","No"],
["Distension","Present","Present"],
["Cause","Adhesions, hernia, volvulus, intussusception","Post-op, peritonitis, metabolic"]],
col_widths=[W*0.28, W*0.36, W*0.36]
))
story += [sp(6)]
story += [h2("10.5 Perforation Peritonitis"), sp(2)]
story += [
b("Sudden onset severe pain → rapid generalized peritonitis"),
b("Board-like rigidity (involuntary), absent bowel sounds, rebound tenderness throughout"),
b("Obliteration of liver dullness = FREE GAS under diaphragm"),
b("Shallow rapid breathing (minimizes diaphragm movement)"),
b("Investigation: Erect CXR = AIR UNDER DIAPHRAGM (pneumoperitoneum)"),
sp(4),
]
story += [h2("10.6 Abdominal Tuberculosis"), sp(2)]
story += [
b("Insidious onset: fever, weight loss, anorexia, altered bowel habits"),
b("Doughy abdomen = characteristic feel (like rolling dough)"),
b("Exudative ascites (high protein, lymphocytes), umbilical/RIF mass"),
b("Ileocecal TB = most common site; shortening of iliopsoas (hip flexion deformity)"),
b("Diagnosis: Ascitic fluid ADA >40 IU/L, AFB, laparoscopy + biopsy"),
sp(4),
]
story += [h2("10.7 Abdominal Aortic Aneurysm (AAA)"), sp(2)]
story += [
b("Elderly male, hypertension, atherosclerosis"),
b("Expansile pulsating epigastric mass (pushes fingers APART laterally)"),
b("Width >3 cm (normal aorta <3 cm)"),
b("Bruit may be present; +/- abdominal pain"),
b("Ruptured AAA: sudden severe back/abdominal pain, collapse, hypotension = surgical emergency"),
b("Screening: USG; Definitive: CT angiography"),
sp(8), PageBreak()
]
# ===================== PART 11: DIFFERENTIAL DIAGNOSIS TABLES =====================
story += [h1("PART 11: DIFFERENTIAL DIAGNOSIS TABLES"), sp(4)]
story += [h2("11.1 Hepatomegaly DDx"), sp(2)]
story.append(make_table(
[["Cause","Key Features"],
["Viral hepatitis","Tender, smooth, elevated enzymes, jaundice"],
["Alcoholic liver disease","History, tender (acute); nodular (cirrhosis)"],
["HCC","Hard, nodular, bruit, AFP elevated"],
["Liver metastases","Rock-hard, craggy, irregular surface"],
["CCF","Tender, pulsatile, elevated JVP, edema"],
["Amyloidosis","Massive, smooth, firm"],
["Malaria","Tender, smooth, tropical history"],
["Riedel's lobe","Normal variant - tongue-like projection from right lobe"]],
col_widths=[W*0.38, W*0.62]
))
story += [sp(6)]
story += [h2("11.2 Splenomegaly DDx"), sp(2)]
story.append(make_table(
[["Condition","Key Feature"],
["CML","Massive; WBC >100,000; Philadelphia chromosome"],
["Kala-azar","Massive; tropical; fever + cachexia + splenomegaly"],
["Myelofibrosis","Massive; tear-drop cells; leukoerythroblastic picture"],
["HMS (hyperreactive malarial)","Massive; tropical; elevated IgM"],
["Thalassemia major","Young; pallor, jaundice, deformed face"],
["Lymphoma","Splenomegaly + lymphadenopathy"],
["Portal hypertension","Firm; ascites + varices"],
["Infective endocarditis","Murmur, fever, Osler nodes, Janeway lesions"],
["Typhoid","2nd week; relative bradycardia; rose spots"]],
col_widths=[W*0.35, W*0.65]
))
story += [sp(6)]
story += [h2("11.3 Ascites DDx"), sp(2)]
story.append(make_table(
[["Condition","SAAG","Protein","Other Features"],
["Cirrhosis","≥1.1","Low","Signs of CLD"],
["CCF","≥1.1","Low","Elevated JVP, edema"],
["Peritoneal TB","<1.1","High","Lymphocytes, ADA >40"],
["Malignancy","<1.1","High","Cytology positive"],
["Pancreatitis","<1.1","High","High amylase in fluid"],
["Nephrotic syndrome","<1.1","Low","Proteinuria, edema"],
["Budd-Chiari","≥1.1","High","Hepatomegaly, no cirrhosis"]],
col_widths=[W*0.3, W*0.15, W*0.15, W*0.4]
))
story += [sp(6)]
story += [h2("11.4 Regional Pain Differential Diagnosis"), sp(2)]
story.append(make_table(
[["Region","Common Causes"],
["RHC (right hypochondrium)","Cholecystitis, biliary colic, hepatitis, liver abscess, right basal pneumonia"],
["Epigastric","Peptic ulcer, pancreatitis, GERD, MI (inferior), aortic dissection"],
["LHC (left hypochondrium)","Splenic infarct/rupture, pancreatitis (tail), gastric pathology, left pneumonia"],
["RIF","Appendicitis, ileocecal TB, Crohn's, ovarian pathology (R), ureteric colic, mesenteric adenitis"],
["LIF","Sigmoid diverticulitis, sigmoid carcinoma, ovarian pathology (L), ureteric colic, constipation"]],
col_widths=[W*0.25, W*0.75]
))
story += [sp(8), PageBreak()]
story += [h2("11.5 Abdominal Masses by Region"), sp(2)]
story.append(make_table(
[["Region","Common Causes"],
["RHC","Liver, gallbladder, hepatic flexure Ca, right kidney"],
["Epigastric","Stomach, pancreas, liver (left lobe), AAA, lymph nodes"],
["LHC","Spleen, stomach, splenic flexure, left kidney, pancreatic tail"],
["RIF","Appendix mass, ileocecal TB, Crohn's, cecal carcinoma, right ovarian mass"],
["Umbilical","Lymph nodes, transverse colon, small bowel"],
["LIF","Sigmoid carcinoma, diverticular mass, left ovarian mass, fecal mass"],
["Hypogastric","Bladder, uterus, ovarian cyst, pregnancy"],
["Loin","Kidney, adrenal, retroperitoneal mass"]],
col_widths=[W*0.22, W*0.78]
))
story += [sp(8), PageBreak()]
# ===================== PART 12: OSCE =====================
story += [h1("PART 12: OSCE / CLINICAL EXAMINATION"), sp(4)]
story += [h2("12.1 Stepwise OSCE Sequence"), sp(2)]
steps = [
"Introduce yourself, wash hands, explain procedure, ask about pain",
"INSPECT (from sides, tangentially, from foot of bed): shape, symmetry, distension, scars, veins, umbilicus, masses, pulsations, peristalsis",
"AUSCULTATE (in acute abdomen - do this before palpation): bowel sounds x2 min; bruits (aortic, renal, hepatic, splenic)",
"PALPATE - Superficial: tenderness, guarding, rigidity",
"PALPATE - Deep: organomegaly (liver, spleen, kidney, GB, aorta, bladder); masses (SITS CMTD)",
"PERCUSS: general tympany/dullness; liver span; Traube's/Castell's; shifting dullness; fluid thrill",
"SPECIAL SIGNS as indicated (Murphy's, Blumberg's, Rovsing's, etc.)",
"HERNIAL ORIFICES: inguinal, femoral, umbilical (ask to cough/strain)",
"GENITALIA / PR / PV if clinically indicated",
"Thank patient, cover, wash hands",
"PRESENT FINDINGS to examiner (see format below)"
]
for i, step in enumerate(steps):
story.append(Paragraph(f"<b>{i+1}.</b> {step}", BULLET))
story += [sp(4)]
story += [h2("12.2 Presentation Format"), sp(2)]
story += [
p("<i>\"On abdominal examination, this [age/sex] patient had [general inspection findings]. Inspection revealed [specific findings]. On palpation, the abdomen was [soft/tender/rigid], with [organomegaly: X cm below costal margin in MCL, with Y surface and Z edge, moving with respiration]. Percussion revealed [liver span, shifting dullness +/-]. Auscultation revealed [bowel sounds]. In summary, this is consistent with [diagnosis] as evidenced by [key findings].\"</i>"),
sp(8), PageBreak()
]
# ===================== PART 13: VIVA QUESTIONS =====================
story += [h1("PART 13: VIVA QUESTIONS WITH MODEL ANSWERS"), sp(4)]
vivas = [
("Q1. What are the 5 Fs of abdominal distension?", "Fat, Fluid, Flatus, Feces, Fetus (+ Fibroid as 6th F)."),
("Q2. How do you differentiate spleen from left kidney on examination?", "Spleen: has a notch, cannot get above it, moves more with respiration, no ballottement, band of colonic resonance anterior to kidney but not spleen. Kidney: ballottable, can get above it, band of resonance anteriorly."),
("Q3. What is Courvoisier's law? What are its exceptions?", "\"If the GB is palpable and the patient is jaundiced, the cause is unlikely to be gallstones.\" Exceptions: double impaction of stones, Mirizzi syndrome, Ca gallbladder + CBD obstruction, mucocele + CBD stone."),
("Q4. What is Sister Mary Joseph's nodule?", "Hard periumbilical nodule = metastatic deposit from intra-abdominal malignancy (stomach, colon, pancreas, ovary) reaching umbilicus via round ligament or falciform ligament."),
("Q5. What is the mechanism of Kehr's sign?", "Blood under left diaphragm irritates diaphragmatic peritoneum (phrenic nerve C3,4,5), causing referred pain to left shoulder tip. Classic in splenic rupture."),
("Q6. What is Carnett's sign?", "Tenderness that persists/increases on tensing abdominal muscles (raising head) = abdominal WALL pain (positive). If it decreases = visceral/intra-abdominal cause (negative)."),
("Q7. What is the minimum ascites detected by each clinical sign?", "Puddle sign: 120 mL. Shifting dullness: ~1500 mL. Fluid thrill: ~3000 mL. USG: 10-20 mL."),
("Q8. What is Dance's sign?", "Palpable emptiness in the RIF due to cecum being drawn up into the RUQ in ileocolic intussusception. Associated with 'current jelly' (blood-stained mucus) stools in children <2 years."),
("Q9. What is the difference between Grey Turner's and Cullen's sign?", "Grey Turner's = bruising in FLANKS (retroperitoneal blood tracks laterally). Cullen's = PERIUMBILICAL blue discoloration (blood via falciform ligament). Both are delayed 24-48 hours. Both indicate severe hemorrhagic pancreatitis."),
("Q10. What obliterates liver dullness?", "Free gas (pneumoperitoneum) due to perforated hollow viscus - most commonly perforated peptic ulcer. Gas interposes between liver and diaphragm. Erect CXR is best initial investigation."),
("Q11. How do you grade splenomegaly?", "Grade 1: just palpable; Grade 2: up to umbilicus; Grade 3: right of umbilicus; Grade 4: massive (into pelvis)."),
("Q12. What is SAAG? How does it help?", "SAAG = Serum albumin minus Ascitic fluid albumin. ≥1.1 = portal hypertension (cirrhosis, CCF, Budd-Chiari). <1.1 = non-portal cause (TB, malignancy, pancreatitis, nephrotic)."),
("Q13. What causes a hepatic bruit?", "Hypervascularity of HCC (most specific). Also: hepatic artery aneurysm, AVM, alcoholic hepatitis."),
("Q14. What is Riedel's lobe?", "A normal anatomical variant - tongue-like downward projection from the right lobe of liver. Smooth, firm, moves with respiration, connected to liver. Important NOT to mistake for hepatomegaly or RIF mass."),
("Q15. How does appendicitis pain evolve?", "Initial central/periumbilical colicky pain (visceral T10 fibers) → pain migrates to RIF (somatic, parietal peritoneum involvement). This migration is pathognomonic."),
]
for q, a in vivas:
story.append(Paragraph(q, VIVA_Q))
story.append(Paragraph(a, VIVA_A))
story += [sp(8), PageBreak()]
# ===================== RAPID REVISION =====================
story += [h1("RAPID REVISION SECTION"), sp(4)]
story += [h2("50 Highest-Yield Facts"), sp(2)]
facts = [
"Normal liver span by percussion = 8-12 cm in right MCL",
"Spleen must be 2-3x enlarged before it becomes palpable",
"Murphy's sign = acute CHOLECYSTITIS (not gallstones per se)",
"Courvoisier's law: palpable GB + jaundice = malignancy, not stones",
"Sister Mary Joseph's nodule = periumbilical metastasis from GI/ovarian cancer",
"5 Fs of abdominal distension: Fat, Fluid, Flatus, Feces, Fetus",
"Shifting dullness detects ascites from >1500 mL",
"Fluid thrill detects tense ascites (>3000 mL typically)",
"Puddle sign detects as little as 120 mL of ascites",
"SAAG ≥1.1 = portal hypertension (cirrhosis, CCF, Budd-Chiari)",
"SAAG <1.1 = non-portal cause (TB, malignancy, pancreatitis)",
"Cullen's sign + Grey Turner's sign = hemorrhagic pancreatitis",
"Grey Turner's = FLANK bruising; Cullen's = PERIUMBILICAL bruising",
"Kehr's sign (left shoulder pain) = splenic rupture/left sub-diaphragmatic blood",
"Dance's sign (empty RIF) = ileocolic intussusception",
"Markle sign (heel drop pain) = peritonitis",
"Carnett's sign positive = abdominal wall pain, NOT visceral",
"Absent liver dullness = pneumoperitoneum (perforated viscus)",
"Massive splenomegaly: CML > Kala-azar > Myelofibrosis > HMS > Thalassemia > Gaucher's",
"Rovsing's sign: LIF pressure → RIF pain = appendicitis",
"Psoas sign = retrocecal appendicitis",
"Obturator sign = pelvic appendicitis",
"McBurney's point = 1/3 from ASIS to umbilicus (right side)",
"Alvarado score ≥7 = appendicectomy likely needed",
"Current jelly stools + Dance's sign = intussusception",
"Doughy abdomen = abdominal tuberculosis",
"Board-like rigidity = perforated peptic ulcer (or any perforation causing peritonitis)",
"ADA >40 IU/L in ascitic fluid = TB peritonitis",
"Succussion splash = gastric outlet obstruction (if >3 hrs post meal)",
"Venous hum at umbilicus = portal hypertension (Cruveilhier-Baumgarten)",
"Caput medusae: blood flows AWAY from umbilicus",
"IVC obstruction: lateral abdominal veins flow UPWARD (cephalad)",
"Tanyol's sign = umbilicus displaced DOWNWARD in ascites",
"Ovarian cyst: CENTRAL dullness, lateral resonance (opposite to ascites)",
"Renal angle tenderness = pyelonephritis / renal colic",
"Kidney can be ballotted; spleen cannot",
"Spleen has a palpable notch on medial border",
"Cannot get ABOVE the spleen; CAN get above the kidney",
"Traube's space obliteration = splenomegaly (most common) / left pleural effusion",
"Castell's sign: 8th-9th ICS AAL dullness = splenomegaly",
"Normal portal pressure: 5-10 mmHg; PHT >12 mmHg (varices at >10 mmHg)",
"Spider angiomata in SVC territory (>5 significant) = chronic liver disease",
"Asterixis (flapping tremor) = hepatic encephalopathy",
"Pulsatile liver = tricuspid regurgitation, CCF",
"Hepatic bruit = HCC (most specific)",
"Friction rub over liver = HCC, hepatic infarction, perihepatitis",
"Friction rub over spleen = splenic infarction",
"Riedel's lobe = normal variant (tongue-like right lobe projection)",
"Erect CXR = best initial test for pneumoperitoneum",
"Voluntary guarding relaxes with distraction; involuntary rigidity persists",
]
for i, f in enumerate(facts):
story.append(Paragraph(f"<b>{i+1}.</b> {f}", BULLET))
story += [sp(8), PageBreak()]
story += [h2("20 Mnemonics"), sp(2)]
mnemonics = [
("5 Fs", "Fat, Fluid, Flatus, Feces, Fetus (abdominal distension)"),
("ILPPA", "Inspect – Listen (Auscultate) – Percuss – Palpate – Assess (examination sequence)"),
("SCDS VERHF", "Shape, Contour, Distension, Scars, Veins, Eversion of umbilicus, Respiration, Hernias, Fistulae (inspection)"),
("SITS CMTD", "Site, Involvement, Tenderness, Size, Consistency, Mobility, Transillumination, Definition of edges (mass description)"),
("CCGMaTh", "CML, Chronic malaria, Gaucher's, Myelofibrosis, ala-azar (Kala-azar), Thalassemia (massive splenomegaly)"),
("SPACED", "Spider nevi, Palmar erythema, Asterixis, Caput medusae/Clubbing, Erythema (palmar), Dupuytren's (CLD signs)"),
("MALT CAP", "Malignancy, Amylase, Lymphoma, TB, Chylous, Autoimmune, Peritonitis (SAAG <1.1 causes)"),
("MANTREL", "Migration, Anorexia, Nausea/vomiting, Tenderness (RIF), Rebound, Elevated temp, Leukocytosis (Alvarado score)"),
("CCGMaTh", "For massive splenomegaly - CML tops the list in India"),
("MATICO (RIF DDx)", "Mesenteric adenitis, Appendicitis, TB ileocecal, Intussusception, Crohn's, Ovarian pathology"),
("Murphy → Cholecystitis; Courvoisier → Cancer", "Direct clinical associations"),
("GT is Going Too far (flanks)", "Grey Turner = flank; Cullen = central/umbilical"),
("Kehr → Left shoulder", "K = left side; splenic rupture"),
("3 Ps of portal HTN", "Portosystemic collaterals, Primary hypersplenism (cytopenia), Peritoneal fluid (ascites)"),
("ABCDE of CLD", "Asterixis, Bilirubin (jaundice), Caput medusae/Clubbing, Dupuytren's, Erythema (palmar)"),
("SAFE (Ascites)", "Shifting dullness, Ascites causes, Fluid thrill, Exudate vs Transudate by SAAG"),
("RUQ = Right to Complain", "Cholecystitis, hepatitis, hepatic abscess, peptic ulcer, right pneumonia"),
("P-FLAT (Portal HTN)", "Portal HTN → Fluid, Liver changes, Abdominal veins, Thrombocytopenia"),
("Dance = Empty RIF", "Ileocolic intussusception, current jelly stools, children <2 years"),
("Obliterated liver dullness = Free Gas = Surgery!", "Perforated viscus; erect CXR; urgent laparotomy"),
]
for i, (m, d) in enumerate(mnemonics):
story.append(Paragraph(f"<b>{i+1}. {m}:</b> {d}", BULLET))
story += [sp(8), PageBreak()]
story += [h2("Key Summary Boxes"), sp(4)]
story.append(make_table(
[["Top 5 EXAM FAVORITES (Always Asked)"],
["1. Courvoisier's law (mechanism + exceptions)"],
["2. Shifting dullness technique (step by step)"],
["3. Spleen vs. kidney differentiation (all 5 points)"],
["4. SAAG interpretation (≥1.1 vs <1.1)"],
["5. Massive splenomegaly causes (CCGMaTh)"]],
col_widths=[W], header_bg=colors.HexColor('#c0392b')
))
story += [sp(6)]
story.append(make_table(
[["Top 5 VIVA TRAPS (Common Mistakes)"],
["1. 'Is Riedel's lobe pathological?' - NO, it's a NORMAL variant"],
["2. 'What obliterates liver dullness?' - Free gas (perforation), NOT hepatomegaly"],
["3. 'Is Murphy's sign positive in gallstones?' - NO - it's for CHOLECYSTITIS"],
["4. 'Which direction in caput medusae?' - AWAY from umbilicus"],
["5. 'Minimum ascites for shifting dullness?' - 1500 mL (NOT 500 mL)"]],
col_widths=[W], header_bg=colors.HexColor('#27ae60')
))
story += [sp(6)]
story.append(make_table(
[["Clinical Approach: Abdomen Distended + Fluid Signs"],
["Step 1: Confirm ascites (shifting dullness / fluid thrill)"],
["Step 2: SAAG (serum albumin - ascitic albumin)"],
["Step 3: ≥1.1 → Look for cirrhosis, CCF, Budd-Chiari"],
["Step 4: <1.1 → Look for TB (ADA), malignancy (cytology), pancreatitis (amylase)"],
["Step 5: Clinical features to narrow diagnosis"]],
col_widths=[W], header_bg=colors.HexColor('#2c5282')
))
story += [sp(6)]
story.append(make_table(
[["Peritoneal Signs - Clinical Differentiation"],
["Perforated PU: board-like rigidity + absent liver dullness + absent bowel sounds"],
["Appendicitis: RIF tenderness + guarding + Rovsing's + Alvarado ≥7"],
["Pancreatitis: epigastric pain + ileus + Grey Turner's/Cullen's + amylase/lipase"],
["Cholecystitis: RUQ pain + Murphy's + guarding + fever"],
["Ruptured ectopic: Cullen's + Kehr's + Blumberg's + shock in young female"]],
col_widths=[W], header_bg=colors.HexColor('#8e44ad')
))
story += [sp(12)]
story.append(HRFlowable(width="100%", thickness=1, color=colors.HexColor('#1a3a5c')))
story += [sp(6)]
story.append(Paragraph("End of Notes | Orris Medical AI | July 2026", CAPTION))
story.append(Paragraph("Sources: S Das Manual of Clinical Surgery 13e · Sleisenger & Fordtran's GI & Liver Disease · Bailey & Love's Surgery 28e · Goldman-Cecil Medicine · Campbell-Walsh Urology · Yamada's Textbook of Gastroenterology 7e", CAPTION))
# BUILD PDF
doc.build(story)
print(f"PDF created: {OUTPUT}")