How to do ring invagination test Step wise manner

Reading File
Finding Sources
Searching the Web

ring invagination test intestinal atresia stepwise procedure

Finding Sources
Searching the Web

ring invagination test bowel patency neonatal surgery technique steps

Finding Sources
Finding Sources
Reading File
Finding Sources
Reading File
Reading File
Loading Image
Loading Image
Reading File
I now have all the information needed for a complete, step-by-step answer. Here is the full explanation:

Ring Invagination Test (for Inguinal Hernia)

The ring invagination test is a clinical examination technique used to palpate the superficial inguinal ring and the inguinal canal. It helps:
  • Confirm a diagnosis of inguinal hernia (cough impulse)
  • Differentiate indirect (oblique) from direct inguinal hernia
  • Confirm an empty inguinal canal in femoral hernia

Prerequisites

  • The hernia must be fully reduced before performing this test
  • Patient should be in the recumbent (lying down) position (preferred) - it is less painful and gives better results
  • Use the little finger to minimise discomfort (index finger may be used if inconvenient)
  • Use the right hand for the right side and left hand for the left side

Step-by-Step Technique

Step 1 - Position the patient Lay the patient supine (recumbent). Reduce the hernia first, either spontaneously or by taxis (gently squeezing the fundus back through the ring).
Step 2 - Begin invagination of scrotal skin Start at the bottom of the scrotum. Invaginate (push inward) the scrotal skin with your little finger, working upward. This "takes up slack" in the skin and gives your finger free play to travel higher.
Figs. 38.13 & 38.14 - Stage 1: Commencing invagination of scrotal skin from the bottom of the scrotum
Stage 2: Finger advanced further into the canal
Step 3 - Locate the pubic tubercle Push the invaginating finger upward until you can palpate the pubic tubercle as a bony landmark.
Step 4 - Enter the superficial inguinal ring Rotate the finger and push it further up into the superficial inguinal ring. The finger should be oriented so that:
  • The nail lies against the spermatic cord
  • The pulp of the finger faces the ring itself
Step 5 - Assess ring size A normal ring is a small triangular slit that admits only the tip of one finger. If more than one finger enters easily, the ring is abnormally large (though this alone does not always indicate hernia).
Step 6 - Note the direction the finger travels When the finger enters the ring, note the direction it is guided:
  • If the canal directs the finger upwards, backwards, and outwards (laterally) → suggests indirect (oblique) inguinal hernia
  • If the canal directs the finger directly backwards → suggests direct inguinal hernia
Step 7 - Rotate the finger and ask the patient to cough Rotate the finger so that the pulp now faces posteriorly (backwards). Ask the patient to cough.
  • If the cough impulse is felt on the tip of the fingerIndirect (oblique) hernia (sac comes down through the deep ring along the canal and hits the fingertip)
  • If the cough impulse is felt on the pulp of the fingerDirect hernia (sac pushes directly backwards through the posterior wall)
Step 8 - Normal response on coughing In a patient without hernia, the cough causes the two pillars of the superficial ring to approximate and squeeze the examining finger. No impulse of protruding bowel will be felt.

Summary Table: Interpretation

FindingIndirect (Oblique) HerniaDirect Hernia
Direction finger travelsUpward, backward, lateralDirectly backward
Cough impulse felt onTip of fingerPulp of finger
Ring occlusion testHernia does NOT appear (ring is occluded)Hernia appears medial to occluding finger

Additional Points

  • In femoral hernia, when you perform the invagination test, the inguinal canal is found to be empty - no impulse is felt. The hernia is below and lateral to the pubic tubercle, not in the canal.
  • This test must be done with utmost gentleness - rough handling can be painful and may rupture a thin sac.
  • This test is not reliable in children due to thick subcutaneous fat over the inguinal region.

Source: S. Das - A Manual on Clinical Surgery, 13th Edition, Chapter 38 (Inguinal Hernia examination)

More easy steps

Here is the ring invagination test broken down into the simplest possible steps:

Ring Invagination Test - Simple Steps


Before You Start

  • Reduce the hernia first (push it back in)
  • Patient lies down (supine/recumbent)
  • Use your little finger (less painful)
  • Right hand → Right side | Left hand → Left side

The Steps

Step 1 - Start at the bottom of the scrotum Place your little finger at the base (bottom) of the scrotum on the affected side.
Step 2 - Push the scrotal skin inward and upward Invaginate (fold/push) the loose scrotal skin inward like a sleeve, moving your finger upward. This gives your finger enough reach.
Step 3 - Find the pubic tubercle Keep pushing up until your finger touches the hard bony bump - that is the pubic tubercle. This is your landmark.
Step 4 - Enter the superficial inguinal ring From the pubic tubercle, rotate your finger and gently push it into the opening just above - this is the superficial (external) inguinal ring.
Position: Nail faces the spermatic cord. Pulp faces the ring.
Step 5 - Feel the ring size
  • Normal = admits only the fingertip (small triangular slit)
  • Abnormal = more than one finger fits easily
Step 6 - Note which way the canal guides your finger
  • Goes upward + backward + outward = indirect hernia track
  • Goes straight backward = direct hernia track
Step 7 - Rotate finger, then ask patient to cough Turn your finger so the pulp faces backward. Tell the patient to cough.
Step 8 - Feel where the impulse hits
Impulse felt on...Means...
Tip of fingerIndirect hernia
Pulp of fingerDirect hernia
No impulse, canal emptyFemoral hernia
Finger gets squeezed (no impulse)Normal - no hernia

The Key Memory Trick

"TIP = Indirect" (T for Tip, I for Indirect) The sac travels the long indirect route down the canal and taps the fingertip. Direct hernia punches straight back into the pulp (the flat face of your finger).

That is the entire test in 8 steps. The core action is: push scrotal skin up → enter the ring with your little finger → feel direction + cough impulse.

Create a quick reference guide on hernia examination

Asking for Preferences
Finding Sources
Reading File
Reading File
Finding Sources
Reading File
Reading File
Reading File
Running Command

mkdir -p /tmp/workspace/hernia-guide && ls /tmp/workspace/

Writing File

~/hernia-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_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import PageBreak

OUTPUT = "/tmp/workspace/hernia-guide/Hernia_Examination_Quick_Reference.pdf"

# ── Colour palette ──────────────────────────────────────────────────────────
NAVY      = colors.HexColor("#1a3a5c")
TEAL      = colors.HexColor("#0e7c7b")
AMBER     = colors.HexColor("#e07b00")
LIGHT_BG  = colors.HexColor("#f0f4f8")
HIGHLIGHT = colors.HexColor("#fff3cd")
RED_ALERT = colors.HexColor("#c0392b")
GREEN_OK  = colors.HexColor("#1e7e34")
WHITE     = colors.white
LIGHT_TEAL= colors.HexColor("#e6f5f5")
LIGHT_AMBER=colors.HexColor("#fff8e6")

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    topMargin=15*mm, bottomMargin=15*mm,
    leftMargin=15*mm, rightMargin=15*mm,
    title="Hernia Examination Quick Reference Guide",
    author="Orris Medical"
)

styles = getSampleStyleSheet()

# Custom styles
def S(name, **kw):
    return ParagraphStyle(name, **kw)

title_style = S("Title2", fontSize=22, textColor=WHITE, alignment=TA_CENTER,
                fontName="Helvetica-Bold", spaceAfter=4)
subtitle_style = S("Sub2", fontSize=11, textColor=colors.HexColor("#cfe8f3"),
                   alignment=TA_CENTER, fontName="Helvetica", spaceAfter=2)

section_header = S("SH", fontSize=13, textColor=WHITE, fontName="Helvetica-Bold",
                   alignment=TA_LEFT, spaceAfter=2, spaceBefore=4,
                   backColor=TEAL, leftIndent=6, rightIndent=6,
                   borderPad=4)

sub_section = S("SSH", fontSize=11, textColor=NAVY, fontName="Helvetica-Bold",
                spaceAfter=3, spaceBefore=5)

body_style = S("Body2", fontSize=9, fontName="Helvetica", leading=14,
               spaceAfter=2, textColor=colors.HexColor("#2c2c2c"))

bullet_style = S("Bull", fontSize=9, fontName="Helvetica", leading=13,
                 leftIndent=12, bulletIndent=4, spaceAfter=1,
                 textColor=colors.HexColor("#2c2c2c"))

bold_bullet = S("BoldBull", fontSize=9, fontName="Helvetica-Bold", leading=13,
                leftIndent=12, bulletIndent=4, spaceAfter=1, textColor=NAVY)

note_style = S("Note", fontSize=8.5, fontName="Helvetica-Oblique",
               textColor=colors.HexColor("#555555"), leading=12,
               leftIndent=8, spaceAfter=2)

alert_style = S("Alert", fontSize=9, fontName="Helvetica-Bold",
                textColor=RED_ALERT, leading=12, spaceAfter=2)

footer_style = S("Footer", fontSize=7.5, textColor=colors.HexColor("#888888"),
                 alignment=TA_CENTER, fontName="Helvetica-Oblique")

def section_box(title):
    """Returns a coloured section header table."""
    t = Table([[Paragraph(title, S("SHi", fontSize=12, textColor=WHITE,
                                    fontName="Helvetica-Bold", spaceAfter=0))]],
              colWidths=[180*mm])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), TEAL),
        ("TOPPADDING",  (0,0), (-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
    ]))
    return t

def amber_box(title):
    t = Table([[Paragraph(title, S("AH", fontSize=11, textColor=WHITE,
                                    fontName="Helvetica-Bold", spaceAfter=0))]],
              colWidths=[180*mm])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), AMBER),
        ("TOPPADDING",  (0,0), (-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
    ]))
    return t

def navy_box(title):
    t = Table([[Paragraph(title, S("NH", fontSize=12, textColor=WHITE,
                                    fontName="Helvetica-Bold", spaceAfter=0))]],
              colWidths=[180*mm])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), NAVY),
        ("TOPPADDING",  (0,0), (-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
    ]))
    return t

story = []

# ─────────────────────────────────────────────────────────────────────────────
# TITLE BANNER
# ─────────────────────────────────────────────────────────────────────────────
title_table = Table(
    [[Paragraph("HERNIA EXAMINATION", title_style)],
     [Paragraph("Quick Reference Guide", subtitle_style)],
     [Paragraph("Source: S. Das — A Manual on Clinical Surgery, 13th Edition", 
                S("src", fontSize=8.5, textColor=colors.HexColor("#a8d4e8"),
                  alignment=TA_CENTER, fontName="Helvetica-Oblique", spaceAfter=0))]],
    colWidths=[180*mm]
)
title_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), NAVY),
    ("TOPPADDING",  (0,0), (0,0), 14),
    ("BOTTOMPADDING",(0,2),(0,2), 12),
    ("ALIGN", (0,0), (-1,-1), "CENTER"),
]))
story.append(title_table)
story.append(Spacer(1, 6*mm))

# ─────────────────────────────────────────────────────────────────────────────
# ROW 1: History + Inspection (side by side)
# ─────────────────────────────────────────────────────────────────────────────

def make_cell_content(items):
    """items: list of (bold_label, text) or (None, text)"""
    paras = []
    for label, text in items:
        if label:
            paras.append(Paragraph(f"<b>{label}</b> {text}", body_style))
        else:
            paras.append(Paragraph(text, body_style))
    return paras

# --- HISTORY CELL ---
hist_items = [
    ("Onset:", "Started on straining/coughing/lifting?"),
    ("Where first?", "Groin → scrotum = Inguinal; Below groin → up = Femoral"),
    ("Size at onset:", "Reaches scrotum at onset = Congenital sac"),
    ("Reduces lying down?", "Direct hernia → auto-reduces; Indirect → needs manual reduction"),
    ("Systemic:", "Colicky pain + vomiting + distension + constipation → Obstruction"),
    ("Causes:", "Chronic cough, constipation, BPH (straining factors)"),
]
hist_paras = [Paragraph("<b>• " + l + "</b> " + t, body_style) for l, t in hist_items]

hist_cell = [
    Table([[Paragraph("HISTORY", S("CH", fontSize=11, textColor=WHITE,
                                    fontName="Helvetica-Bold"))]],
          colWidths=[85*mm],
          style=TableStyle([("BACKGROUND",(0,0),(-1,-1),TEAL),
                             ("TOPPADDING",(0,0),(-1,-1),4),
                             ("BOTTOMPADDING",(0,0),(-1,-1),4),
                             ("LEFTPADDING",(0,0),(-1,-1),6)])),
] + hist_paras

# --- INSPECTION CELL ---
insp_items = [
    ("Shape:", "Inguinal = pear-shaped (can extend to scrotum); Femoral = spherical (retort-shaped)"),
    ("Position:", "Inguinal = above & medial to pubic tubercle; Femoral = below & lateral"),
    ("Skin:", "Normal = uncomplicated; Red = strangulated; Pigmented streaks = truss use"),
    ("Cough impulse:", "Visible expansion/bulge synchronous with cough = hernia"),
    ("Peristalsis:", "Visible peristalsis only in recurrent inguinal hernia (thin skin)"),
    ("Penis position:", "Pushed to opposite side in large inguinoscrotal hernia"),
]
insp_paras = [Paragraph("<b>• " + l + "</b> " + t, body_style) for l, t in insp_items]

insp_cell = [
    Table([[Paragraph("INSPECTION", S("CH2", fontSize=11, textColor=WHITE,
                                       fontName="Helvetica-Bold"))]],
          colWidths=[85*mm],
          style=TableStyle([("BACKGROUND",(0,0),(-1,-1),TEAL),
                             ("TOPPADDING",(0,0),(-1,-1),4),
                             ("BOTTOMPADDING",(0,0),(-1,-1),4),
                             ("LEFTPADDING",(0,0),(-1,-1),6)])),
] + insp_paras

two_col = Table(
    [[hist_cell, insp_cell]],
    colWidths=[89*mm, 89*mm],
    spaceBefore=0
)
two_col.setStyle(TableStyle([
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 2),
    ("RIGHTPADDING",(0,0), (-1,-1), 2),
    ("BACKGROUND", (0,0), (0,0), LIGHT_BG),
    ("BACKGROUND", (1,0), (1,0), LIGHT_BG),
    ("BOX", (0,0), (0,0), 0.5, colors.HexColor("#aaaaaa")),
    ("BOX", (1,0), (1,0), 0.5, colors.HexColor("#aaaaaa")),
]))
story.append(two_col)
story.append(Spacer(1, 4*mm))

# ─────────────────────────────────────────────────────────────────────────────
# PALPATION — KEY TESTS
# ─────────────────────────────────────────────────────────────────────────────
story.append(section_box("PALPATION — KEY EXAMINATION TESTS"))
story.append(Spacer(1, 3*mm))

# Test 1: Cough impulse
story.append(Paragraph("1.  Impulse on Coughing", sub_section))
story.append(Paragraph(
    "Ask patient to cough while placing a flat hand over the swelling. "
    "<b>Expansile impulse</b> (swelling expands outward on cough) = diagnostic of hernia. "
    "Absence does not exclude hernia if neck is blocked by adhesions.", body_style))
story.append(Spacer(1, 2*mm))

# Test 2: Reducibility
story.append(Paragraph("2.  Reducibility (Taxis)", sub_section))
palpation_data = [
    ["Step", "Action"],
    ["1", "Patient lies supine. Ask to flex, adduct & internally rotate the affected thigh."],
    ["2", "Gently hold the fundus of the sac with one hand."],
    ["3", "Apply even pressure squeezing contents toward and through the superficial ring."],
    ["4", "Gurgling on reduction = enterocele (intestine). Omentocele: last part resists."],
    ["5", "If unreducible → Irreducible / Obstructed / Strangulated hernia."],
]
t = Table(palpation_data, colWidths=[12*mm, 166*mm])
t.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), AMBER),
    ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
    ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE",   (0,0), (-1,-1), 9),
    ("ALIGN",      (0,0), (0,-1), "CENTER"),
    ("VALIGN",     (0,0), (-1,-1), "TOP"),
    ("GRID",       (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_BG]),
    ("TOPPADDING",  (0,0), (-1,-1), 4),
    ("BOTTOMPADDING",(0,0),(-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(t)
story.append(Spacer(1, 3*mm))

# Test 3: Consistency
story.append(Paragraph("3.  Consistency of the Hernia", sub_section))
consist_data = [
    ["Consistency", "Contents", "Type"],
    ["Doughy / Granular", "Omentum", "Omentocele / Epiplocele"],
    ["Elastic / Resonant", "Intestine", "Enterocele"],
    ["Tense + Tender", "Compromised bowel", "Strangulated hernia ⚠"],
]
tc = Table(consist_data, colWidths=[45*mm, 55*mm, 78*mm])
tc.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
    ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE",   (0,0), (-1,-1), 9),
    ("ALIGN",      (0,0), (-1,-1), "LEFT"),
    ("VALIGN",     (0,0), (-1,-1), "MIDDLE"),
    ("GRID",       (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_BG, HIGHLIGHT]),
    ("TOPPADDING",  (0,0), (-1,-1), 4),
    ("BOTTOMPADDING",(0,0),(-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(tc)
story.append(Spacer(1, 3*mm))

# Test 4: Relation to testis
story.append(Paragraph("4.  Relation to Testis & Spermatic Cord", sub_section))
story.append(Paragraph(
    "In <b>inguinal hernia</b>: hernia lies in <i>front and sides</i> of the cord — testis is incorporated. "
    "You cannot get above the swelling. "
    "In <b>scrotal swelling</b>: you can get above the swelling and feel normal cord above it.", body_style))
story.append(Spacer(1, 4*mm))

# ─────────────────────────────────────────────────────────────────────────────
# RING INVAGINATION TEST
# ─────────────────────────────────────────────────────────────────────────────
story.append(section_box("RING INVAGINATION TEST (After reducing hernia)"))
story.append(Spacer(1, 3*mm))

inv_data = [
    ["Step", "Action", "Purpose"],
    ["PRE", "Reduce hernia first. Patient supine. Use little finger (R hand → R side).", "Setup"],
    ["1", "Start at bottom of scrotum. Invaginate scrotal skin inward and upward.", "Gain reach"],
    ["2", "Push finger up to touch the pubic tubercle (bony landmark).", "Locate landmark"],
    ["3", "Rotate finger and push into the superficial inguinal ring.\nNail faces cord. Pulp faces ring.", "Enter ring"],
    ["4", "Assess ring size. Normal = admits fingertip only.\nIf >1 finger fits = dilated ring.", "Size"],
    ["5", "Note direction the canal guides your finger:\n• Upward + backward + outward = Indirect track\n• Directly backward = Direct track", "Type of hernia"],
    ["6", "Rotate finger: pulp faces posteriorly. Ask patient to cough.", "Cough test"],
    ["7", "Feel where impulse hits:\n• TIP of finger = Indirect (oblique) hernia\n• PULP of finger = Direct hernia\n• Canal empty = Femoral hernia\n• Finger squeezed, no impulse = Normal", "Interpretation"],
]
ti = Table(inv_data, colWidths=[12*mm, 100*mm, 66*mm])
ti.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), AMBER),
    ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
    ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE",   (0,0), (-1,-1), 8.5),
    ("ALIGN",      (0,0), (0,-1), "CENTER"),
    ("VALIGN",     (0,0), (-1,-1), "TOP"),
    ("GRID",       (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_TEAL, WHITE, LIGHT_TEAL, WHITE, LIGHT_TEAL, WHITE, HIGHLIGHT]),
    ("TOPPADDING",  (0,0), (-1,-1), 4),
    ("BOTTOMPADDING",(0,0),(-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(ti)
story.append(Spacer(1, 4*mm))

# ─────────────────────────────────────────────────────────────────────────────
# RING OCCLUSION TEST
# ─────────────────────────────────────────────────────────────────────────────
story.append(section_box("RING OCCLUSION TEST (Confirmatory)"))
story.append(Spacer(1, 3*mm))

story.append(Paragraph(
    "Performed in <b>standing position</b> after reducing hernia. Press thumb firmly over the <b>deep inguinal ring</b> "
    "(½ inch above midpoint of inguinal ligament — mid-inguinal point). Ask patient to cough.",
    body_style))
story.append(Spacer(1, 2*mm))

occ_data = [
    ["Result on Coughing", "Interpretation"],
    ["No bulge appears", "Indirect (oblique) hernia — sac cannot exit through occluded deep ring"],
    ["Bulge appears MEDIAL to thumb", "Direct hernia — exits through posterior wall, not through deep ring"],
    ["Bulge appears BELOW inguinal ligament", "Femoral hernia — occluding the ring has no effect"],
]
to2 = Table(occ_data, colWidths=[70*mm, 108*mm])
to2.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
    ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE",   (0,0), (-1,-1), 9),
    ("ALIGN",      (0,0), (-1,-1), "LEFT"),
    ("VALIGN",     (0,0), (-1,-1), "MIDDLE"),
    ("GRID",       (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [LIGHT_BG, HIGHLIGHT, LIGHT_TEAL]),
    ("TOPPADDING",  (0,0), (-1,-1), 5),
    ("BOTTOMPADDING",(0,0),(-1,-1), 5),
    ("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(to2)
story.append(Spacer(1, 4*mm))

# ─────────────────────────────────────────────────────────────────────────────
# DIFFERENTIATION TABLE
# ─────────────────────────────────────────────────────────────────────────────
story.append(section_box("DIFFERENTIAL DIAGNOSIS: INDIRECT vs DIRECT vs FEMORAL"))
story.append(Spacer(1, 3*mm))

diff_data = [
    ["Feature", "Indirect (Oblique)", "Direct", "Femoral"],
    ["Age", "Any age", "> 40 yrs", "> 50 yrs (F > M)"],
    ["Sex", "M >> F", "M >> F", "F > M (2:1)"],
    ["Position\n(re: pubic tubercle)", "Above & medial", "Above & medial", "Below & lateral"],
    ["Shape", "Pear-shaped,\ndown to scrotum", "Spherical, rarely\ninto scrotum", "Retort-shaped\n(bulb turns upward)"],
    ["Reduces lying down?", "Manual reduction\nneeded (indirect)", "Auto-reduces\nimmediately", "May need manual\nreduction"],
    ["Invagination test\n(impulse felt on...)", "TIP of finger", "PULP of finger", "Canal EMPTY"],
    ["Ring occlusion test", "Hernia controlled\n(no bulge)", "Bulge appears\nMEDIAL to thumb", "Not controlled\n(below ring)"],
    ["Strangulation risk", "Moderate", "Low", "HIGH (rigid canal)"],
    ["Neck of sac", "Lateral to inferior\nepigastric artery", "Medial to inferior\nepigastric artery", "Below inguinal\nligament"],
]
td = Table(diff_data, colWidths=[42*mm, 46*mm, 46*mm, 44*mm])
td.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
    ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTNAME",   (0,1), (0,-1), "Helvetica-Bold"),
    ("BACKGROUND", (0,1), (0,-1), colors.HexColor("#e8edf2")),
    ("FONTSIZE",   (0,0), (-1,-1), 8.5),
    ("ALIGN",      (0,0), (-1,-1), "CENTER"),
    ("VALIGN",     (0,0), (-1,-1), "MIDDLE"),
    ("GRID",       (0,0), (-1,-1), 0.4, colors.HexColor("#aaaaaa")),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_BG, WHITE, LIGHT_BG, WHITE, LIGHT_BG, WHITE, LIGHT_BG, WHITE, LIGHT_BG]),
    # Highlight strangulation row
    ("BACKGROUND", (3,8), (3,8), colors.HexColor("#fde8e8")),
    ("TEXTCOLOR",  (3,8), (3,8), RED_ALERT),
    ("FONTNAME",   (3,8), (3,8), "Helvetica-Bold"),
    ("TOPPADDING",  (0,0), (-1,-1), 4),
    ("BOTTOMPADDING",(0,0),(-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 4),
]))
story.append(td)
story.append(Spacer(1, 4*mm))

# ─────────────────────────────────────────────────────────────────────────────
# STRANGULATION / COMPLICATIONS — ALERT BOX
# ─────────────────────────────────────────────────────────────────────────────
story.append(amber_box("⚠  STRANGULATION — DO NOT MISS"))
story.append(Spacer(1, 2*mm))

strang_data = [
    ["Sign / Symptom", "Detail"],
    ["Tense, tender, irreducible lump", "Tense = diagnostic of strangulation"],
    ["Skin overlying = RED / INFLAMED", "Cellulitis over hernia sac"],
    ["Colicky abdominal pain + vomiting", "Signs of intestinal obstruction"],
    ["Faecal vomiting", "Late, ominous sign — indicates low obstruction"],
    ["Absent cough impulse", "Strangulated sac — blocked neck"],
    ["Femoral hernia strangulates MOST often", "Rigid walls of femoral canal"],
]
ts = Table(strang_data, colWidths=[75*mm, 103*mm])
ts.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), RED_ALERT),
    ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
    ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE",   (0,0), (-1,-1), 9),
    ("ALIGN",      (0,0), (-1,-1), "LEFT"),
    ("VALIGN",     (0,0), (-1,-1), "MIDDLE"),
    ("GRID",       (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, colors.HexColor("#fff0f0"), WHITE,
                                         colors.HexColor("#fff0f0"), WHITE, colors.HexColor("#fde8e8")]),
    ("TOPPADDING",  (0,0), (-1,-1), 4),
    ("BOTTOMPADDING",(0,0),(-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(ts)
story.append(Spacer(1, 4*mm))

# ─────────────────────────────────────────────────────────────────────────────
# PERCUSSION & AUSCULTATION
# ─────────────────────────────────────────────────────────────────────────────
perc_insp = Table(
    [[
        # Percussion
        [
            Table([[Paragraph("PERCUSSION", S("PCH", fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]],
                  colWidths=[85*mm],
                  style=TableStyle([("BACKGROUND",(0,0),(-1,-1),TEAL),("TOPPADDING",(0,0),(-1,-1),4),
                                    ("BOTTOMPADDING",(0,0),(-1,-1),4),("LEFTPADDING",(0,0),(-1,-1),6)])),
            Paragraph("• <b>Resonant</b> → Enterocele (intestine)", body_style),
            Paragraph("• <b>Dull</b> → Omentocele / Extraperitoneal fat", body_style),
            Paragraph("• <b>Upper dull + lower resonant</b> → Mixed contents", body_style),
        ],
        # Auscultation
        [
            Table([[Paragraph("AUSCULTATION", S("ACH", fontSize=11, textColor=WHITE, fontName="Helvetica-Bold"))]],
                  colWidths=[85*mm],
                  style=TableStyle([("BACKGROUND",(0,0),(-1,-1),TEAL),("TOPPADDING",(0,0),(-1,-1),4),
                                    ("BOTTOMPADDING",(0,0),(-1,-1),4),("LEFTPADDING",(0,0),(-1,-1),6)])),
            Paragraph("• <b>Bowel sounds present</b> → Enterocele (live bowel)", body_style),
            Paragraph("• <b>Bowel sounds absent</b> → Strangulated / Omentocele", body_style),
            Paragraph("• Always auscultate before reducing obstructed hernia", body_style),
        ]
    ]],
    colWidths=[89*mm, 89*mm]
)
perc_insp.setStyle(TableStyle([
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING", (0,0), (-1,-1), 2),
    ("RIGHTPADDING",(0,0),(-1,-1), 2),
    ("BACKGROUND", (0,0), (0,0), LIGHT_BG),
    ("BACKGROUND", (1,0), (1,0), LIGHT_BG),
    ("BOX", (0,0), (0,0), 0.5, colors.HexColor("#aaaaaa")),
    ("BOX", (1,0), (1,0), 0.5, colors.HexColor("#aaaaaa")),
]))
story.append(perc_insp)
story.append(Spacer(1, 4*mm))

# ─────────────────────────────────────────────────────────────────────────────
# MEMORY AIDS
# ─────────────────────────────────────────────────────────────────────────────
story.append(navy_box("MEMORY AIDS"))
story.append(Spacer(1, 2*mm))

mem_data = [
    ["Mnemonic / Rule", "What it means"],
    ["TIP = Indirect", "Cough impulse on fingertip during invagination test = Indirect hernia\n(long oblique path taps the tip)"],
    ["PULP = Direct", "Cough impulse on pulp of finger = Direct hernia (punches straight back)"],
    ["EMPTY canal = Femoral", "Invagination test finds empty inguinal canal in femoral hernia"],
    ["TWO CLASSICAL SIGNS of hernia", "① Expansile impulse on coughing  ② Reducibility"],
    ["Femoral strangulates FIRST", "Rigid femoral canal → earliest strangulation among all hernias"],
    ["Inguinal > Femoral in WOMEN too", "Even in women, inguinal hernia is commoner than femoral"],
]
tm = Table(mem_data, colWidths=[60*mm, 118*mm])
tm.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
    ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTNAME",   (0,1), (0,-1), "Helvetica-Bold"),
    ("TEXTCOLOR",  (0,1), (0,-1), TEAL),
    ("FONTSIZE",   (0,0), (-1,-1), 9),
    ("ALIGN",      (0,0), (-1,-1), "LEFT"),
    ("VALIGN",     (0,0), (-1,-1), "TOP"),
    ("GRID",       (0,0), (-1,-1), 0.4, colors.HexColor("#cccccc")),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, LIGHT_BG, WHITE, LIGHT_BG, WHITE, LIGHT_BG]),
    ("TOPPADDING",  (0,0), (-1,-1), 4),
    ("BOTTOMPADDING",(0,0),(-1,-1), 5),
    ("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(tm)
story.append(Spacer(1, 5*mm))

# ─────────────────────────────────────────────────────────────────────────────
# FOOTER
# ─────────────────────────────────────────────────────────────────────────────
story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#aaaaaa")))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
    "Orris Medical  |  Hernia Examination Quick Reference Guide  |  "
    "Based on S. Das — Manual on Clinical Surgery, 13th Ed.  |  For educational use only",
    footer_style))

# ─────────────────────────────────────────────────────────────────────────────
# BUILD
# ─────────────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUTPUT}")
Running Command

cd /tmp/workspace/hernia-guide && python generate_pdf.py

Your quick reference guide is ready. Download it here:

Hernia Examination Quick Reference

PDF Document · PDF


What's inside the guide (single A4 page):
SectionContents
HistoryOnset, position, reducibility, obstruction symptoms, precipitating causes
InspectionShape, skin changes, cough impulse, peristalsis, penis position
Palpation - Key TestsTaxis (reduction), consistency, relation to testis/cord
Ring Invagination TestFull 7-step table with purpose of each step
Ring Occlusion TestConfirmatory test with 3-way result interpretation
Differential Diagnosis TableIndirect vs Direct vs Femoral - 10 features compared side by side
Strangulation AlertRed-flagged warning box with all signs
Percussion & AuscultationResonant/dull findings, bowel sounds
Memory AidsTIP = Indirect, PULP = Direct, EMPTY = Femoral, and more
All content sourced from S. Das - A Manual on Clinical Surgery, 13th Edition.
This is a shared conversation. Sign in to Orris to start your own chat.