Long case 1. Inguinal hernia 2. Thyroid swelling 3. Breast carcinoma 4. Peripheral vascular disease 5. Varicose veins 6. Optional- lump abdomen, cervical lymphadenopathy, parotid swelling Short cases 1. Swelling - lipoma, sebaceous cyst, abscess, dermoid cyst, lymph node, any hernia, any other swelling. 2. Ulcer 3. Hydrocele Case clinical proforma s and viva questions related in surgery final year mbbs
| Feature | Venous | Ischaemic | Neuropathic |
|---|---|---|---|
| Site | Medial gaiter area, above medial malleolus | Tips of toes, lateral malleolus, heel, pressure points | Plantar surface of foot, metatarsal heads |
| Pain | Mild/moderate | Very severe | Painless |
| Edge | Sloping | Punched out | Punched out |
| Floor | Granulation tissue | Necrotic/pale | Callus around |
| Surrounding skin | Pigmentation, eczema, lipodermatosclerosis | Cold, pale/cyanotic, trophic changes | Normal temperature; callus, neuropathic signs |
| Pulses | Normal | Absent/diminished | Normal |
| Sensation | Normal | Reduced if combined | Absent |
Individual case proforma pdf format
mkdir -p /tmp/workspace/surgery-proformas && ls /tmp/workspace/surgery-proformas/
~/surgery-proformas/generate_proformas.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 pypdf import PdfWriter, PdfReader
import os
OUTPUT_DIR = "/tmp/workspace/surgery-proformas"
# ─── Colour palette ────────────────────────────────────────────────────────────
DARK_BLUE = colors.HexColor("#1A3A5C")
MED_BLUE = colors.HexColor("#2E6DA4")
LIGHT_BLUE = colors.HexColor("#D6E8F7")
ACCENT = colors.HexColor("#E8F4FC")
HEADER_BG = colors.HexColor("#0D2B45")
BOX_BG = colors.HexColor("#F0F7FF")
LINE_COLOR = colors.HexColor("#2E6DA4")
TEXT_COLOR = colors.HexColor("#1A1A2E")
WHITE = colors.white
GOLD = colors.HexColor("#C8973A")
W, H = A4
# ─── Style helpers ─────────────────────────────────────────────────────────────
def make_styles():
base = getSampleStyleSheet()
styles = {}
styles["title"] = ParagraphStyle(
"title", fontSize=16, fontName="Helvetica-Bold",
textColor=WHITE, alignment=TA_CENTER,
spaceAfter=2, leading=20
)
styles["subtitle"] = ParagraphStyle(
"subtitle", fontSize=10, fontName="Helvetica",
textColor=colors.HexColor("#B8D4F0"), alignment=TA_CENTER,
spaceAfter=0
)
styles["section"] = ParagraphStyle(
"section", fontSize=11, fontName="Helvetica-Bold",
textColor=WHITE, spaceAfter=0, leading=14
)
styles["sub_section"] = ParagraphStyle(
"sub_section", fontSize=10, fontName="Helvetica-Bold",
textColor=MED_BLUE, spaceAfter=3, leading=13, spaceBefore=4
)
styles["body"] = ParagraphStyle(
"body", fontSize=9, fontName="Helvetica",
textColor=TEXT_COLOR, leading=13, spaceAfter=2, alignment=TA_LEFT
)
styles["bullet"] = ParagraphStyle(
"bullet", fontSize=9, fontName="Helvetica",
textColor=TEXT_COLOR, leading=12, spaceAfter=1,
leftIndent=12, bulletIndent=2
)
styles["viva_q"] = ParagraphStyle(
"viva_q", fontSize=9, fontName="Helvetica",
textColor=TEXT_COLOR, leading=12, spaceAfter=1,
leftIndent=18, bulletIndent=2
)
styles["field_label"] = ParagraphStyle(
"field_label", fontSize=8.5, fontName="Helvetica-Bold",
textColor=DARK_BLUE, leading=11, spaceAfter=0
)
styles["footer"] = ParagraphStyle(
"footer", fontSize=7.5, fontName="Helvetica",
textColor=colors.grey, alignment=TA_CENTER
)
return styles
# ─── Reusable building blocks ──────────────────────────────────────────────────
def header_table(title, subtitle, styles):
"""Dark header banner."""
data = [
[Paragraph(title, styles["title"])],
[Paragraph(subtitle, styles["subtitle"])],
]
t = Table(data, colWidths=[W - 4*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), HEADER_BG),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
("ROUNDEDCORNERS", [6]),
]))
return t
def section_header(text, styles):
"""Blue section banner."""
data = [[Paragraph(text, styles["section"])]]
t = Table(data, colWidths=[W - 4*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
return t
def info_row(fields, styles):
"""Horizontal row of labelled fields with write-in boxes."""
col_w = (W - 4*cm) / len(fields)
headers = [Paragraph(f, styles["field_label"]) for f in fields]
boxes = ["_" * 28] * len(fields)
t = Table([headers, boxes], colWidths=[col_w]*len(fields))
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BLUE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0C8E0")),
("FONTSIZE", (0,1), (-1,1), 8),
("FONTNAME", (0,1), (-1,1), "Helvetica"),
("TEXTCOLOR", (0,1), (-1,1), colors.white),
]))
return t
def write_box(label, lines=2, styles=None):
"""A labelled write-in area."""
height = lines * 14
data = [
[Paragraph(label, styles["field_label"])],
[" "],
]
t = Table(data, colWidths=[W - 4*cm], rowHeights=[14, height])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BLUE),
("BACKGROUND", (0,1), (-1,1), BOX_BG),
("BOX", (0,0), (-1,-1), 0.8, MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
return t
def checklist_table(items, cols=2, styles=None):
"""Grid of checkbox items."""
rows = [items[i:i+cols] for i in range(0, len(items), cols)]
col_w = (W - 4*cm) / cols
table_data = []
for row in rows:
padded = row + [""] * (cols - len(row))
table_data.append([Paragraph("☐ " + c, styles["bullet"]) for c in padded])
t = Table(table_data, colWidths=[col_w]*cols)
t.setStyle(TableStyle([
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 4),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#CCDDEE")),
("BACKGROUND", (0,0), (-1,-1), BOX_BG),
]))
return t
def viva_box(questions, styles):
"""Numbered viva questions in a shaded box."""
items = []
for i, q in enumerate(questions, 1):
items.append(Paragraph(f"{i}. {q}", styles["viva_q"]))
items.append(Spacer(1, 1))
data = [[items]]
t = Table(data, colWidths=[W - 4*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#FFF8E8")),
("BOX", (0,0), (-1,-1), 1, GOLD),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
return t
def sp(n=4):
return Spacer(1, n)
def hr(styles):
return HRFlowable(width="100%", thickness=0.5, color=LINE_COLOR, spaceAfter=3, spaceBefore=3)
# ═══════════════════════════════════════════════════════════════════════════════
# CASE 1 – INGUINAL HERNIA
# ═══════════════════════════════════════════════════════════════════════════════
def build_inguinal_hernia(styles):
story = []
story.append(header_table(
"CLINICAL CASE PROFORMA", "INGUINAL HERNIA | Surgery – Final Year MBBS", styles))
story.append(sp(8))
# Biodata
story.append(section_header("PATIENT BIODATA", styles)); story.append(sp(4))
story.append(info_row(["Name", "Age", "Sex", "IP/OP No."], styles)); story.append(sp(3))
story.append(info_row(["Occupation", "Address", "Date", "Examiner"], styles)); story.append(sp(6))
# Chief Complaint
story.append(section_header("CHIEF COMPLAINT", styles)); story.append(sp(4))
story.append(write_box("Swelling in the groin since _____ | Side: R / L / Bilateral", 2, styles)); story.append(sp(4))
# HPI
story.append(section_header("HISTORY OF PRESENT ILLNESS", styles)); story.append(sp(4))
story.append(Paragraph("Swelling Characteristics", styles["sub_section"]))
story.append(checklist_table([
"Gradual onset", "Sudden onset", "Progressive increase",
"Reducible spontaneously", "Reducible manually", "Irreducible",
"Appears on straining/coughing", "Descends to scrotum",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Associated Symptoms", styles["sub_section"]))
story.append(checklist_table([
"Pain (colicky = obstruction)", "Vomiting", "Constipation",
"Inability to pass flatus", "Burning/dragging sensation", "No symptoms",
"Urinary symptoms (BPH)", "H/o previous reduction",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Precipitating Factors", styles["sub_section"]))
story.append(checklist_table([
"Heavy lifting / manual labour", "Chronic cough (TB, COPD, smoking)",
"Constipation / straining at stool", "BPH / urethral stricture",
"Ascites", "Previous abdominal surgery", "Pregnancy", "Obesity",
], 2, styles)); story.append(sp(4))
story.append(write_box("Duration / Progression / Other HPI notes:", 2, styles)); story.append(sp(6))
# Past / Family / Personal History
story.append(section_header("PAST / FAMILY / PERSONAL HISTORY", styles)); story.append(sp(4))
story.append(checklist_table([
"Previous hernia surgery", "Previous abdominal surgery",
"H/o trauma", "Diabetes mellitus",
"Smoking / tobacco", "Family H/o hernia",
"Occupational H/o heavy work", "No relevant history",
], 2, styles)); story.append(sp(4))
# Examination
story.append(section_header("GENERAL & SYSTEMIC EXAMINATION", styles)); story.append(sp(4))
story.append(info_row(["Built/Nutrition", "Anaemia", "Jaundice", "Cyanosis"], styles)); story.append(sp(3))
story.append(info_row(["Pulse (bpm)", "BP (mmHg)", "Temp (°F)", "RR"], styles)); story.append(sp(3))
story.append(checklist_table([
"Chronic cough present (respiratory)", "Ascites (abdominal)",
"Bladder distension", "Organomegaly", "Normal systemic exam",
], 2, styles)); story.append(sp(6))
story.append(section_header("LOCAL EXAMINATION", styles)); story.append(sp(4))
story.append(Paragraph("Inspection", styles["sub_section"]))
story.append(checklist_table([
"Above inguinal ligament", "Below inguinal ligament (femoral?)",
"Extends into scrotum", "Unilateral – Right", "Unilateral – Left", "Bilateral",
"Skin: Normal", "Skin: Erythematous (strangulation)",
"Cough impulse visible", "No visible impulse",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Palpation", styles["sub_section"]))
story.append(checklist_table([
"Warm / not warm", "Tender / non-tender",
"Reducible", "Irreducible",
"Positive cough impulse", "Negative cough impulse",
"Deep ring occlusion test: positive (indirect)", "Deep ring occlusion test: negative (direct)",
"Above & lateral to pubic tubercle (indirect)", "Above & medial to pubic tubercle (direct)",
"Testis palpable separately", "Testis not separately palpable",
"Relation to scrotal contents: separate / continuous",
"Resonant on percussion (bowel)", "Dull on percussion (omentum)",
], 2, styles)); story.append(sp(3))
story.append(write_box("Invagination test findings / Additional palpation notes:", 2, styles)); story.append(sp(4))
# Diagnosis box
story.append(section_header("PROVISIONAL DIAGNOSIS", styles)); story.append(sp(4))
story.append(write_box(
"Right / Left | Direct / Indirect | Reducible / Irreducible / Obstructed / Strangulated | Inguinal Hernia", 2, styles))
story.append(sp(4))
story.append(write_box("Differential Diagnoses:", 2, styles)); story.append(sp(4))
# Investigations
story.append(section_header("INVESTIGATIONS", styles)); story.append(sp(4))
story.append(checklist_table([
"Hb, TLC, DLC, Platelet", "Blood glucose (fasting/PP)",
"Renal function tests (BUN, Creatinine)", "Coagulation profile (PT, aPTT)",
"Chest X-ray (PA view)", "ECG (if age >40 or cardiac risk)",
"USG abdomen/groin (if doubt)", "Spirometry (if chronic cough)",
"Urine routine/microscopy", "Blood grouping & cross-match",
], 2, styles)); story.append(sp(4))
story.append(write_box("Investigation findings / Reports:", 3, styles)); story.append(sp(6))
# Management
story.append(section_header("MANAGEMENT PLAN", styles)); story.append(sp(4))
story.append(Paragraph("Conservative (if unfit for surgery)", styles["sub_section"]))
story.append(checklist_table([
"Truss (temporary, elderly/high-risk)", "Treat precipitating cause (cough, BPH, constipation)",
"Weight reduction advice", "Avoid heavy lifting",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Surgical Options", styles["sub_section"]))
story.append(checklist_table([
"Herniotomy (paediatric)", "Herniorrhaphy (tissue repair)",
"Bassini's repair", "Shouldice repair",
"Lichtenstein mesh repair (preferred)", "TAPP (laparoscopic)",
"TEP (laparoscopic)", "Emergency surgery (obstruction/strangulation)",
], 2, styles)); story.append(sp(3))
story.append(write_box("Pre-op preparation / Surgical plan / Post-op notes:", 3, styles)); story.append(sp(6))
# Viva
story.append(section_header("VIVA QUESTIONS", styles)); story.append(sp(4))
viva_qs = [
"Describe the boundaries of Hesselbach's triangle.",
"What are the walls, contents and openings of the inguinal canal?",
"How do you differentiate direct from indirect inguinal hernia clinically?",
"Describe the deep ring occlusion test.",
"How do you differentiate inguinal hernia from femoral hernia?",
"What is the difference between irreducible, obstructed, and strangulated hernia?",
"What is Richter's hernia? Maydl's hernia? Littre's hernia?",
"What is the Lichtenstein tension-free mesh repair? Describe its steps.",
"What are the advantages of laparoscopic repair (TAPP vs TEP)?",
"What are the complications of hernia repair?",
"What is herniotomy vs herniorrhaphy vs hernioplasty?",
"Why is inguinal hernia more common on the right side?",
"What is a sliding hernia? What are the special concerns?",
"What is the processus vaginalis? Its role in indirect hernia?",
"What is Ogilvie's sign?",
]
story.append(viva_box(viva_qs, styles))
story.append(sp(6))
story.append(Paragraph(
"Sources: Bailey & Love 28th Ed | Pye's Surgical Handicraft 22nd Ed | Current Surgical Therapy 14th Ed",
styles["footer"]))
return story
# ═══════════════════════════════════════════════════════════════════════════════
# CASE 2 – THYROID SWELLING
# ═══════════════════════════════════════════════════════════════════════════════
def build_thyroid(styles):
story = []
story.append(header_table(
"CLINICAL CASE PROFORMA", "THYROID SWELLING (GOITRE) | Surgery – Final Year MBBS", styles))
story.append(sp(8))
story.append(section_header("PATIENT BIODATA", styles)); story.append(sp(4))
story.append(info_row(["Name", "Age", "Sex", "IP/OP No."], styles)); story.append(sp(3))
story.append(info_row(["Occupation", "Residence (Endemic?)", "Date", "Examiner"], styles)); story.append(sp(6))
story.append(section_header("CHIEF COMPLAINT", styles)); story.append(sp(4))
story.append(write_box("Swelling in front of neck since _____ | Other complaints:", 2, styles)); story.append(sp(6))
story.append(section_header("HISTORY OF PRESENT ILLNESS", styles)); story.append(sp(4))
story.append(Paragraph("Swelling Details", styles["sub_section"]))
story.append(checklist_table([
"Gradual onset", "Rapid increase in size (alarming – malignancy)",
"Diffuse swelling", "Single nodule", "Multiple nodules",
"Moves on swallowing", "Does NOT move on swallowing",
"Changes with menstruation", "Change in size with iodine intake",
"H/o pain (sudden = haemorrhage; continuous = malignancy/thyroiditis)",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Compressive Symptoms", styles["sub_section"]))
story.append(checklist_table([
"Dysphagia (oesophageal compression)", "Dyspnoea (tracheal compression)",
"Stridor", "Hoarseness of voice (RLN compression)",
"Facial congestion on raising arms (Pemberton – retrosternal)",
"No compressive symptoms",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Thyroid Status – Thyrotoxicosis", styles["sub_section"]))
story.append(checklist_table([
"Palpitations / tachycardia", "Weight loss despite good appetite",
"Heat intolerance / excessive sweating", "Tremors of hands",
"Diarrhoea", "Menstrual irregularity / oligomenorrhoea",
"Irritability / anxiety", "Exophthalmos / lid lag",
"Pretibial myxoedema", "Goitre with bruit",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Thyroid Status – Hypothyroidism", styles["sub_section"]))
story.append(checklist_table([
"Weight gain / obesity", "Cold intolerance",
"Constipation", "Lethargy / fatigue",
"Dry skin / hair loss / brittle nails", "Bradycardia",
"Periorbital puffiness", "Delayed reflexes",
"Myxoedema voice (hoarse, croaky)", "Menorrhagia",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Risk Factors / Past History", styles["sub_section"]))
story.append(checklist_table([
"Dietary iodine deficiency / endemic area", "Goitrogen intake (cabbage, cassava)",
"Previous thyroid surgery", "Neck irradiation (papillary Ca risk)",
"Family H/o thyroid cancer (MEN2 – medullary)", "Antithyroid drugs / lithium / amiodarone",
"Family H/o Hashimoto's / Graves'", "H/o radioiodine therapy",
], 2, styles)); story.append(sp(6))
story.append(section_header("GENERAL EXAMINATION (Thyroid Status Assessment)", styles)); story.append(sp(4))
story.append(info_row(["Pulse (rate/rhythm)", "BP", "Temp", "BMI"], styles)); story.append(sp(3))
story.append(checklist_table([
"Tremor (fine, outstretched hands)", "Warm moist palms (thyrotoxicosis)",
"Exophthalmos", "Lid lag (von Graefe's sign)",
"Lid retraction (Dalrymple's sign)", "Chemosis / ophthalmoplegia (Graves')",
"Pretibial myxoedema", "Thyroid acropachy",
"Periorbital puffiness (hypothyroid)", "Delayed relaxation of reflexes",
], 2, styles)); story.append(sp(6))
story.append(section_header("LOCAL EXAMINATION", styles)); story.append(sp(4))
story.append(Paragraph("Inspection", styles["sub_section"]))
story.append(checklist_table([
"Midline swelling", "Lateral (lobe) swelling",
"Diffuse enlargement", "Solitary nodule",
"Multinodular", "Moves on swallowing (cardinal sign)",
"Moves on tongue protrusion (thyroglossal cyst)", "Visible dilated veins",
"Skin: normal / erythematous / scar",
"Pemberton's sign: positive (retrosternal) / negative",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Palpation (Stand behind patient)", styles["sub_section"]))
story.append(checklist_table([
"Temperature: warm (thyroiditis) / normal",
"Tenderness: present (thyroiditis, haemorrhage) / absent",
"Surface: smooth / nodular / irregular",
"Consistency: soft / firm / hard / rubbery",
"Solitary nodule / multinodular",
"Moves on deglutition",
"Can you get BELOW the swelling? No = retrosternal extension",
"Trachea: midline / deviated",
"Berry's sign: absent carotid pulse (malignant infiltration)",
"Cervical lymph nodes (anterior / posterior / supraclavicular)",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Percussion / Auscultation", styles["sub_section"]))
story.append(checklist_table([
"Retrosternal dullness on percussion", "Bruit on auscultation (Graves' / hypervascular)",
"No bruit", "No retrosternal dullness",
], 2, styles)); story.append(sp(4))
story.append(section_header("PROVISIONAL DIAGNOSIS", styles)); story.append(sp(4))
story.append(write_box(
"Type: Simple / MNG / Toxic / Solitary Nodule / Thyroiditis / Malignant | Status: Euthyroid / Toxic / Hypothyroid", 2, styles))
story.append(sp(4))
story.append(write_box("Features suggesting malignancy:", 2, styles)); story.append(sp(4))
story.append(section_header("INVESTIGATIONS", styles)); story.append(sp(4))
story.append(checklist_table([
"TSH (first-line thyroid test)", "Free T3, Free T4",
"Anti-TPO antibodies (Hashimoto's)", "Anti-TSH receptor antibodies (Graves')",
"Thyroglobulin (post-thyroidectomy monitoring)", "Calcitonin (medullary Ca)",
"Serum calcium (post-op monitoring)", "CEA (medullary Ca)",
"Ultrasound neck (TIRADS classification)", "FNAC (Bethesda classification)",
"Thyroid scan (Tc-99m / I-123): hot vs cold nodule", "X-ray neck (tracheal deviation)",
"CT neck/chest (retrosternal extension, mediastinal nodes)", "Indirect laryngoscopy (vocal cord mobility)",
"24-h urine catecholamines (phaeochromocytoma in MEN2)", "Core biopsy (if FNAC inconclusive)",
], 2, styles)); story.append(sp(4))
story.append(write_box("Investigation findings:", 3, styles)); story.append(sp(6))
story.append(section_header("MANAGEMENT PLAN", styles)); story.append(sp(4))
story.append(checklist_table([
"Medical: antithyroid drugs (carbimazole / PTU)", "Radioiodine therapy (I-131)",
"Beta-blocker (symptom control in thyrotoxicosis)", "Levothyroxine replacement (hypothyroid / post-op)",
"Hemithyroidectomy / lobectomy (solitary nodule / hemithyroid disease)",
"Total thyroidectomy (bilateral MNG, thyroid Ca, Graves' failing medical)",
"Subtotal thyroidectomy (bilateral MNG – historical)", "Neck dissection (if lymph nodes involved)",
"Radioiodine ablation (post-total thyroidectomy for well-differentiated Ca)",
"Pre-op: euthyroid state, Lugol's iodine (7–10 days), laryngoscopy",
], 2, styles)); story.append(sp(3))
story.append(write_box("Detailed management plan / surgical notes:", 3, styles)); story.append(sp(6))
story.append(section_header("VIVA QUESTIONS", styles)); story.append(sp(4))
viva_qs = [
"What is the cardinal sign of a thyroid swelling? Explain why.",
"What is Pemberton's sign? When is it positive?",
"What is Berry's sign? What does it indicate?",
"Classify thyroid carcinoma. Which is most common? Worst prognosis?",
"What is papillary thyroid carcinoma – its mode of spread?",
"What is medullary carcinoma? Its genetic basis (MEN2, RET proto-oncogene)?",
"What is Grave's disease? Hashimoto's thyroiditis? De Quervain's thyroiditis?",
"What is the Bethesda classification for FNAC of thyroid?",
"What is a cold vs hot nodule on thyroid scan? Which is more likely malignant?",
"What are the complications of thyroidectomy?",
"What is thyroid storm? How do you manage it?",
"What is the pre-operative preparation for a thyrotoxic patient?",
"What structures are at risk during thyroidectomy?",
"What is the WHO grading of goitre?",
"What is Lugol's iodine – when is it used and what does it do?",
]
story.append(viva_box(viva_qs, styles))
story.append(sp(6))
story.append(Paragraph(
"Sources: Bailey & Love 28th Ed | Pye's Surgical Handicraft 22nd Ed | Schwartz's Principles of Surgery 11th Ed",
styles["footer"]))
return story
# ═══════════════════════════════════════════════════════════════════════════════
# CASE 3 – BREAST CARCINOMA
# ═══════════════════════════════════════════════════════════════════════════════
def build_breast(styles):
story = []
story.append(header_table(
"CLINICAL CASE PROFORMA", "BREAST CARCINOMA | Surgery – Final Year MBBS", styles))
story.append(sp(8))
story.append(section_header("PATIENT BIODATA", styles)); story.append(sp(4))
story.append(info_row(["Name", "Age", "IP/OP No.", "Examiner"], styles)); story.append(sp(3))
story.append(info_row(["Marital Status", "Menopausal Status", "Parity", "Date"], styles)); story.append(sp(6))
story.append(section_header("CHIEF COMPLAINT", styles)); story.append(sp(4))
story.append(write_box("Lump in breast since _____ | Side: Right / Left | Quadrant: UO / UI / LO / LI / Central", 2, styles)); story.append(sp(6))
story.append(section_header("HISTORY OF PRESENT ILLNESS", styles)); story.append(sp(4))
story.append(Paragraph("Lump Characteristics", styles["sub_section"]))
story.append(checklist_table([
"Gradual onset", "Rapid increase in size",
"Painless (usual)", "Painful (inflammatory carcinoma)",
"Single lump", "Multiple lumps",
"Skin dimpling noticed", "Skin redness / warmth",
"Peau d'orange skin", "Ulceration",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Nipple / Axilla", styles["sub_section"]))
story.append(checklist_table([
"Nipple retraction (recent-onset)", "Nipple discharge",
"Blood-stained discharge", "Eczema of nipple (Paget's)",
"Axillary lump / swelling", "Arm swelling / lymphoedema",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Risk Factor Assessment", styles["sub_section"]))
story.append(checklist_table([
"Nulliparity / first child after 35 yrs", "Early menarche (<12 yrs)",
"Late menopause (>55 yrs)", "OCP / HRT use",
"H/o atypical hyperplasia / DCIS / previous Ca breast",
"Family H/o breast Ca (mother/sister/daughter)",
"BRCA1 / BRCA2 known carrier", "Chest wall radiation history",
"Breastfeeding history (protective)", "Obesity / sedentary lifestyle",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Metastatic Symptoms", styles["sub_section"]))
story.append(checklist_table([
"Backache / bone pain (bone mets)", "Dyspnoea (lung / pleural mets)",
"Jaundice / RUQ pain (liver mets)", "Headache / seizures (brain mets)",
"Weight loss / anorexia", "No systemic symptoms",
], 2, styles)); story.append(sp(6))
story.append(section_header("LOCAL EXAMINATION", styles)); story.append(sp(4))
story.append(Paragraph("Inspection – 4 positions (arms at side | hands on hips | arms raised | leaning forward)", styles["sub_section"]))
story.append(checklist_table([
"Symmetry: normal / asymmetry",
"Skin dimpling (Cooper's ligament tethering)",
"Peau d'orange (dermal lymphatic obstruction)",
"Skin ulceration / satellite nodules",
"Nipple retraction / Paget's eczema",
"Blood-stained / serous nipple discharge",
"Erythema / warmth (inflammatory Ca)",
"Dilated superficial veins",
"Visible axillary swelling",
"Previous scar / surgical changes",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Palpation of Lump (Supine, hand behind head)", styles["sub_section"]))
story.append(info_row(["Quadrant", "Size (cm)", "Shape", "Surface"], styles)); story.append(sp(3))
story.append(checklist_table([
"Hard consistency", "Firm consistency",
"Irregular shape / surface", "Ill-defined margin",
"Mobile (early)", "Fixed to skin",
"Fixed to pectoral fascia / muscle (check with arm on hip vs raised)",
"Fixed to chest wall (deep fixity)",
"Skin fixity: positive pinch test",
"Nipple discharge on squeeze: blood-stained",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Lymph Node Examination", styles["sub_section"]))
story.append(checklist_table([
"Axillary: Level I (anterior/pectoral) – mobile", "Axillary: Level I – fixed",
"Axillary: Level II (central)", "Axillary: Level III (apical/infraclavicular)",
"Supraclavicular nodes", "Cervical nodes",
"Contralateral axilla", "Bilateral supraclavicular",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Systemic Examination for Metastasis", styles["sub_section"]))
story.append(checklist_table([
"Spine: tenderness on percussion",
"Ribs: tenderness (bone mets)",
"Liver: hepatomegaly",
"Lung: dullness / effusion",
"Neurological examination",
], 2, styles)); story.append(sp(4))
story.append(section_header("STAGING (TNM)", styles)); story.append(sp(4))
data = [
[Paragraph("T Stage", styles["field_label"]), Paragraph("N Stage", styles["field_label"]),
Paragraph("M Stage", styles["field_label"]), Paragraph("Overall Stage", styles["field_label"])],
[Paragraph("T1 (<2cm) / T2 (2-5cm)\nT3 (>5cm) / T4 (skin/wall/inflam)", styles["body"]),
Paragraph("N0 / N1 (mobile axillary)\nN2 (fixed) / N3 (infra/supraclav)", styles["body"]),
Paragraph("M0 / M1", styles["body"]),
Paragraph("I / IIA / IIB\nIIIA / IIIB / IIIC / IV", styles["body"])],
]
t = Table(data, colWidths=[(W-4*cm)/4]*4)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BLUE),
("GRID", (0,0), (-1,-1), 0.5, MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
]))
story.append(t); story.append(sp(6))
story.append(section_header("INVESTIGATIONS", styles)); story.append(sp(4))
story.append(checklist_table([
"TRIPLE ASSESSMENT: Clinical + Imaging + Pathology",
"Mammogram (BIRADS 1-6 classification)", "USG breast (young patients / dense breast)",
"FNAC / Core needle biopsy (Tru-cut)", "ER / PR / HER2 receptor status",
"Ki-67 (proliferation index)", "Hb, CBC, LFT, RFT",
"X-ray chest (lung/pleural mets)", "USG abdomen (liver mets)",
"Bone scan (bone mets – if symptomatic)", "MRI breast (young / high-risk / implants)",
"PET-CT (staging in advanced disease)",
], 2, styles)); story.append(sp(4))
story.append(write_box("Investigation results / Receptor status:", 3, styles)); story.append(sp(6))
story.append(section_header("MANAGEMENT PLAN", styles)); story.append(sp(4))
story.append(checklist_table([
"Wide local excision + SLNB (BCS – early disease)",
"Modified radical mastectomy (Patey's) + ALND",
"Simple mastectomy + SLNB",
"Neoadjuvant chemotherapy (locally advanced / inflammatory)",
"Adjuvant chemotherapy (CMF / AC-T / docetaxel-based)",
"Adjuvant radiotherapy (post-BCS / post-mastectomy T3/T4/N+)",
"Hormonal therapy: Tamoxifen (pre-menopause) / Aromatase inhibitor (post-menopause)",
"Trastuzumab (Herceptin) – if HER2 positive",
"Sentinel lymph node biopsy technique",
"Reconstruction: immediate / delayed",
], 2, styles)); story.append(sp(3))
story.append(write_box("Detailed management / operative plan:", 3, styles)); story.append(sp(6))
story.append(section_header("VIVA QUESTIONS", styles)); story.append(sp(4))
viva_qs = [
"What is the lymphatic drainage of the breast? Levels of axillary nodes?",
"What are the ligaments of Cooper? How do they cause skin dimpling?",
"What is peau d'orange? What causes it?",
"What is Paget's disease of the nipple?",
"What is inflammatory carcinoma of the breast?",
"What is the triple assessment in breast disease?",
"What is the BIRADS classification in mammography?",
"What is the Bethesda / B-classification in breast pathology?",
"Classify breast carcinoma histologically (most common type?)",
"What is DCIS vs LCIS? What is their significance?",
"What is breast conserving surgery – indications and contraindications?",
"What is Patey's operation? What structures are preserved vs removed?",
"What is sentinel lymph node biopsy and how is it performed?",
"What is the significance of ER/PR/HER2 receptor status in management?",
"What are BRCA1 and BRCA2 mutations and how are carriers managed?",
]
story.append(viva_box(viva_qs, styles))
story.append(sp(6))
story.append(Paragraph(
"Sources: Bailey & Love 28th Ed | Schwartz's Principles of Surgery 11th Ed",
styles["footer"]))
return story
# ═══════════════════════════════════════════════════════════════════════════════
# CASE 4 – PERIPHERAL VASCULAR DISEASE
# ═══════════════════════════════════════════════════════════════════════════════
def build_pvd(styles):
story = []
story.append(header_table(
"CLINICAL CASE PROFORMA", "PERIPHERAL VASCULAR DISEASE | Surgery – Final Year MBBS", styles))
story.append(sp(8))
story.append(section_header("PATIENT BIODATA", styles)); story.append(sp(4))
story.append(info_row(["Name", "Age", "Sex", "IP/OP No."], styles)); story.append(sp(3))
story.append(info_row(["Occupation", "Smoking (pack-years)", "Date", "Examiner"], styles)); story.append(sp(6))
story.append(section_header("CHIEF COMPLAINT", styles)); story.append(sp(4))
story.append(write_box("Pain in lower limb / Ulcer / Gangrene of foot since _____ | Side: R / L / Bilateral", 2, styles)); story.append(sp(6))
story.append(section_header("HISTORY OF PRESENT ILLNESS", styles)); story.append(sp(4))
story.append(Paragraph("Intermittent Claudication", styles["sub_section"]))
story.append(checklist_table([
"Calf pain on walking (SFA disease)", "Thigh pain (iliac disease)",
"Buttock / hip pain (aortoiliac – Leriche)", "Pain starts after ___ metres (claudication distance)",
"Relieved within minutes of rest", "Worsens progressively over months",
"Bilateral claudication", "Unilateral – Right / Left",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Rest Pain", styles["sub_section"]))
story.append(checklist_table([
"Continuous burning pain at rest", "Worse at night (disturbs sleep)",
"Hangs leg out of bed / walks to relieve",
"Relieved by dependency (foot down)",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Tissue Loss", styles["sub_section"]))
story.append(checklist_table([
"Ulcer on toe / heel / pressure point",
"Dry gangrene (mummification, clear demarcation)",
"Wet gangrene (infected, spreading, foul odour)",
"Black discolouration of toe / foot",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Risk Factors (ATHEROSCLEROSIS)", styles["sub_section"]))
story.append(checklist_table([
"Smoking (most important modifiable RF)", "Diabetes mellitus",
"Hypertension", "Hyperlipidaemia / dyslipidaemia",
"Obesity", "Family history of vascular disease",
"Sedentary lifestyle", "Hypercoagulable state",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Systemic Atherosclerosis (other territories)", styles["sub_section"]))
story.append(checklist_table([
"Coronary: angina / MI / CABG / angioplasty", "Cerebrovascular: TIA / stroke",
"Renal: CKD / hypertension", "Impotence (Leriche syndrome: aortoiliac)",
"Abdominal aortic aneurysm", "Carotid artery disease",
], 2, styles)); story.append(sp(6))
story.append(section_header("LOCAL EXAMINATION", styles)); story.append(sp(4))
story.append(Paragraph("Inspection", styles["sub_section"]))
story.append(checklist_table([
"Pallor (acute / chronic ischaemia)", "Dependent rubor",
"Cyanosis", "Trophic changes: thin shiny skin",
"Hair loss over limb", "Nail: dystrophic / thickened / ridged",
"Muscle wasting", "Venous guttering on elevation",
"Ulcer (site / size / edge / base)", "Dry gangrene: clear demarcation line",
"Wet gangrene: spreading / foul odour", "Buerger's angle < 20° (severe ischaemia)",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Palpation", styles["sub_section"]))
story.append(checklist_table([
"Temperature: cool / cold (compare both limbs)", "Capillary refill time: >2 seconds",
"Sensation: diminished / absent",
"Aorta: palpable / pulsatile expansile (AAA)",
"Femoral pulse: present / diminished / absent",
"Popliteal pulse: present / absent",
"Dorsalis pedis pulse: present / absent",
"Posterior tibial pulse: present / absent",
"Buerger's test: positive (angle of pallor: ___°; reactive hyperaemia on dependency)",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Auscultation", styles["sub_section"]))
story.append(checklist_table([
"Femoral bruit", "Aortic bruit",
"No bruit", "Carotid bruit",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("ABPI Measurement", styles["sub_section"]))
story.append(info_row(["Right Ankle BP", "Left Ankle BP", "Brachial BP", "Right ABPI"], styles)); story.append(sp(3))
story.append(info_row(["Left ABPI", "Interpretation", "Fontaine Stage", "Rutherford Grade"], styles)); story.append(sp(4))
story.append(section_header("FONTAINE CLASSIFICATION", styles)); story.append(sp(4))
data = [
[Paragraph("Stage I", styles["field_label"]),
Paragraph("Stage IIa", styles["field_label"]),
Paragraph("Stage IIb", styles["field_label"]),
Paragraph("Stage III", styles["field_label"]),
Paragraph("Stage IV", styles["field_label"])],
[Paragraph("Asymptomatic", styles["body"]),
Paragraph("Claudication\n>150 m", styles["body"]),
Paragraph("Claudication\n<150 m", styles["body"]),
Paragraph("Rest pain", styles["body"]),
Paragraph("Tissue loss\n(ulcer/gangrene)", styles["body"])],
]
t = Table(data, colWidths=[(W-4*cm)/5]*5)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BLUE),
("GRID", (0,0), (-1,-1), 0.5, MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 4),
("ALIGN", (0,0), (-1,-1), "CENTER"),
]))
story.append(t); story.append(sp(6))
story.append(section_header("INVESTIGATIONS", styles)); story.append(sp(4))
story.append(checklist_table([
"CBC, ESR, CRP", "Blood glucose / HbA1c",
"Lipid profile (LDL, HDL, TG, TC)", "Renal function tests",
"Coagulation profile", "ECG / Echo (cardiac status pre-op)",
"ABPI (ankle-brachial pressure index)", "Duplex ultrasound (anatomy + flow)",
"CT angiography (gold standard for planning)", "MR angiography",
"Digital subtraction angiography (DSA – if intervention planned)", "Transcutaneous pO2 (TcPO2)",
], 2, styles)); story.append(sp(4))
story.append(write_box("Investigation findings / Imaging summary:", 3, styles)); story.append(sp(6))
story.append(section_header("MANAGEMENT PLAN", styles)); story.append(sp(4))
story.append(checklist_table([
"Risk factor modification: STOP SMOKING (most important)",
"Antiplatelet: Aspirin 75mg / Clopidogrel 75mg",
"Statin therapy (atorvastatin 40-80mg)",
"ACE inhibitor / ARB (vascular protection)",
"Exercise rehabilitation programme",
"Cilostazol (claudication – phosphodiesterase inhibitor)",
"Percutaneous transluminal angioplasty (PTA) ± stenting",
"Surgical bypass: aorto-bifemoral / femoropopliteal / femodistal",
"Endarterectomy (carotid / femoral)",
"Embolectomy (Fogarty catheter – acute ischaemia)",
"Fasciotomy (if compartment syndrome / reperfusion)",
"Amputation: below-knee (Burgess flap) / above-knee / ray amputation",
], 2, styles)); story.append(sp(3))
story.append(write_box("Detailed management plan:", 3, styles)); story.append(sp(6))
story.append(section_header("VIVA QUESTIONS", styles)); story.append(sp(4))
viva_qs = [
"What is intermittent claudication? Differentiate vascular from neurogenic claudication.",
"What is Leriche syndrome? Describe its classic triad.",
"Describe Buerger's test and its interpretation.",
"What is the ABPI? How is it measured? Interpret values: >1.0 / 0.5-0.9 / <0.5 / <0.3.",
"What are the 6 P's of acute limb ischaemia?",
"What are trophic changes? List all of them.",
"What is critical limb ischaemia (CLI)? Define it.",
"What is Buerger's disease (TAO)? How does it differ from atherosclerotic PVD?",
"Classify gangrene. Distinguish wet from dry gangrene.",
"What is the management of acute limb ischaemia?",
"What is a Fogarty catheter and how is embolectomy done?",
"What are the principles of below-knee vs above-knee amputation?",
"What is a fasciotomy? When is it indicated?",
"What conduits are used for bypass surgery? Which is preferred and why?",
"What is the diabetic foot? How does neuropathic differ from ischaemic ulcer?",
]
story.append(viva_box(viva_qs, styles))
story.append(sp(6))
story.append(Paragraph(
"Sources: Bailey & Love 28th Ed | Grainger & Allison's Diagnostic Radiology",
styles["footer"]))
return story
# ═══════════════════════════════════════════════════════════════════════════════
# CASE 5 – VARICOSE VEINS
# ═══════════════════════════════════════════════════════════════════════════════
def build_varicose_veins(styles):
story = []
story.append(header_table(
"CLINICAL CASE PROFORMA", "VARICOSE VEINS | Surgery – Final Year MBBS", styles))
story.append(sp(8))
story.append(section_header("PATIENT BIODATA", styles)); story.append(sp(4))
story.append(info_row(["Name", "Age", "Sex", "IP/OP No."], styles)); story.append(sp(3))
story.append(info_row(["Occupation (standing?)", "Parity", "Date", "Examiner"], styles)); story.append(sp(6))
story.append(section_header("CHIEF COMPLAINT", styles)); story.append(sp(4))
story.append(write_box("Dilated tortuous veins in leg since _____ | Side: R / L / Bilateral", 2, styles)); story.append(sp(6))
story.append(section_header("HISTORY OF PRESENT ILLNESS", styles)); story.append(sp(4))
story.append(Paragraph("Venous Symptoms", styles["sub_section"]))
story.append(checklist_table([
"Aching / heaviness in leg", "Throbbing / burning sensation",
"Cramps (especially nocturnal)", "Swelling of ankle / leg",
"Itching over veins", "All symptoms worse on standing / end of day",
"Relieved by elevation", "Relieved by compression hosiery",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Complications", styles["sub_section"]))
story.append(checklist_table([
"Superficial thrombophlebitis (pain, redness, hardness along vein)",
"Haemorrhage from varicosity", "Venous ulcer (above medial malleolus)",
"Skin pigmentation (haemosiderin)", "Eczema / dermatitis",
"Lipodermatosclerosis (brawny induration)", "Atrophie blanche",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Risk Factors", styles["sub_section"]))
story.append(checklist_table([
"Family history (strong predisposition)", "Prolonged standing (occupation)",
"Multiple pregnancies", "Obesity / high BMI",
"Previous DVT (post-thrombotic syndrome)", "Pelvic mass (secondary varicosities)",
"Chronic constipation / straining", "Age >35 years",
], 2, styles)); story.append(sp(3))
story.append(write_box("Previous treatment: sclerotherapy / surgery / compression / none:", 2, styles)); story.append(sp(6))
story.append(section_header("LOCAL EXAMINATION (Patient STANDING)", styles)); story.append(sp(4))
story.append(Paragraph("Inspection", styles["sub_section"]))
story.append(checklist_table([
"GSV distribution (medial thigh & leg)", "SSV distribution (posterolateral leg / popliteal fossa)",
"Bilateral varicosities", "Skin pigmentation (haemosiderin – medial ankle)",
"Eczema / dermatitis", "Lipodermatosclerosis",
"Atrophie blanche (white scarring)", "Corona phlebectatica (ankle flare)",
"Active venous ulcer: site – medial gaiter area",
"Healed ulcer / scar", "Previous surgery scars",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Palpation", styles["sub_section"]))
story.append(checklist_table([
"Warm over varicosities", "Tenderness (thrombophlebitis)",
"Saphena varix at SFJ: soft, reducible, cough impulse, disappears lying down",
"Tap test (Schwartz): impulse transmitted up incompetent column",
"Varicosities along GSV territory", "Varicosities along SSV territory",
"Perforator sites: Dodd's (mid-thigh) / Boyd's (below knee) / Cockett's (post-tibial)",
"Groin: DDx – lymph node / femoral hernia / saphena varix",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Tourniquet / Trendelenburg Test", styles["sub_section"]))
story.append(checklist_table([
"Elevation empties veins: Yes / No",
"Tourniquet at upper thigh: veins remain empty (SFJ controlled = SFJ incompetence)",
"Tourniquet at upper thigh: veins fill from below (perforator incompetence)",
"Release tourniquet: sudden filling from above (SFJ incompetent)",
"Multiple tourniquet test (Ochsner-Mahorner): perforator level identified",
], 1, styles)); story.append(sp(3))
story.append(Paragraph("Doppler Examination", styles["sub_section"]))
story.append(checklist_table([
"Reflux at SFJ on Valsalva/cough: Present / Absent",
"Reflux at SPJ: Present / Absent",
"Handheld Doppler (HHDD) at SFJ/SPJ",
"Duplex ultrasound: saphenous vein diameter / reflux duration / DVT excluded",
], 1, styles)); story.append(sp(4))
story.append(section_header("CEAP CLASSIFICATION", styles)); story.append(sp(4))
data = [
[Paragraph("C0", styles["field_label"]), Paragraph("C1", styles["field_label"]),
Paragraph("C2", styles["field_label"]), Paragraph("C3", styles["field_label"]),
Paragraph("C4", styles["field_label"]), Paragraph("C5", styles["field_label"]),
Paragraph("C6", styles["field_label"])],
[Paragraph("No visible disease", styles["body"]),
Paragraph("Telangiec-tasia", styles["body"]),
Paragraph("Varicose veins", styles["body"]),
Paragraph("Oedema", styles["body"]),
Paragraph("Skin changes", styles["body"]),
Paragraph("Healed ulcer", styles["body"]),
Paragraph("Active ulcer", styles["body"])],
["☐", "☐", "☐", "☐", "☐", "☐", "☐"],
]
t = Table(data, colWidths=[(W-4*cm)/7]*7)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BLUE),
("GRID", (0,0), (-1,-1), 0.5, MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("FONTSIZE", (0,2), (-1,2), 12),
]))
story.append(t); story.append(sp(6))
story.append(section_header("INVESTIGATIONS", styles)); story.append(sp(4))
story.append(checklist_table([
"Duplex ultrasound (gold standard: anatomy, reflux, DVT)",
"Handheld Doppler (reflux at SFJ/SPJ)",
"CBC, coagulation profile (pre-op)",
"Venography (rarely – complex cases)",
], 2, styles)); story.append(sp(4))
story.append(write_box("Duplex findings / Investigation results:", 2, styles)); story.append(sp(6))
story.append(section_header("MANAGEMENT PLAN", styles)); story.append(sp(4))
story.append(checklist_table([
"Conservative: weight loss, avoid prolonged standing, leg elevation",
"Compression hosiery (Class I-III)",
"Foam sclerotherapy (UGFS – small/recurrent varicosities)",
"Endovenous Laser Ablation (EVLA)",
"Radiofrequency Ablation (RFA / VNUS closure)",
"High ligation and stripping (HLS): ligation of SFJ + stripping of GSV",
"Stab avulsion / phlebectomy (tributaries)",
"Management of venous ulcer: 4-layer compression bandage (Charing Cross)",
"Skin grafting (for large non-healing ulcer)",
"Management of superficial thrombophlebitis: NSAIDs + compression",
], 2, styles)); story.append(sp(3))
story.append(write_box("Operative plan / Procedure notes:", 3, styles)); story.append(sp(6))
story.append(section_header("VIVA QUESTIONS", styles)); story.append(sp(4))
viva_qs = [
"Describe the anatomy of the great saphenous vein (GSV) – its course and tributaries.",
"What is the saphenofemoral junction (SFJ) and which tributaries drain into it?",
"What are perforating veins? Name the important ones (Dodd's, Boyd's, Cockett's).",
"Describe the Trendelenburg test – performance and interpretation.",
"What is the Schwartz (tap) test?",
"What is a saphena varix? How is it differentiated from a femoral hernia?",
"What is the CEAP classification? Classify the case presented.",
"What are the complications of varicose veins?",
"What is lipodermatosclerosis? What is atrophie blanche?",
"What is May-Thurner syndrome?",
"What is EVLA? How does it work? Advantages over surgery?",
"What is high ligation and stripping? Describe the procedure step by step.",
"What is the management of a venous leg ulcer?",
"What is the post-thrombotic syndrome?",
"What are the complications of varicose vein surgery?",
]
story.append(viva_box(viva_qs, styles))
story.append(sp(6))
story.append(Paragraph(
"Sources: Bailey & Love 28th Ed | Gray's Anatomy for Students",
styles["footer"]))
return story
# ═══════════════════════════════════════════════════════════════════════════════
# CASE 6 – HYDROCELE
# ═══════════════════════════════════════════════════════════════════════════════
def build_hydrocele(styles):
story = []
story.append(header_table(
"CLINICAL CASE PROFORMA", "HYDROCELE | Surgery – Final Year MBBS (Short Case)", styles))
story.append(sp(8))
story.append(section_header("PATIENT BIODATA", styles)); story.append(sp(4))
story.append(info_row(["Name", "Age", "Sex", "IP/OP No."], styles)); story.append(sp(3))
story.append(info_row(["Address (tropical?)", "Occupation", "Date", "Examiner"], styles)); story.append(sp(6))
story.append(section_header("CHIEF COMPLAINT", styles)); story.append(sp(4))
story.append(write_box("Scrotal swelling since _____ | Side: Right / Left / Bilateral", 2, styles)); story.append(sp(6))
story.append(section_header("HISTORY OF PRESENT ILLNESS", styles)); story.append(sp(4))
story.append(checklist_table([
"Gradual onset, painless (primary hydrocele)", "Painful (secondary hydrocele)",
"Increases in size over time", "Fluctuates in size (congenital – reduces at night)",
"H/o trauma to scrotum", "H/o fever / UTI / epididymo-orchitis",
"H/o testicular torsion", "H/o TB (genital TB)",
"H/o travel to tropics (filariasis – Wuchereria bancrofti)",
"H/o malignancy / weight loss", "No other urological symptoms",
"Difficulty in walking (large hydrocele)", "H/o previous aspiration / surgery",
], 2, styles)); story.append(sp(6))
story.append(section_header("LOCAL EXAMINATION", styles)); story.append(sp(4))
story.append(Paragraph("Inspection", styles["sub_section"]))
story.append(checklist_table([
"Unilateral scrotal swelling", "Bilateral scrotal swelling",
"Skin: normal / thickened (filarial)", "Skin: erythematous (secondary / infected)",
"Translucency test (pen torch): brilliant transillumination",
"Does NOT transilluminate (haematocele / tumour?)",
"Penis buried (large bilateral hydrocele)",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Palpation", styles["sub_section"]))
story.append(checklist_table([
"Can you get ABOVE the swelling? YES (scrotal) / NO (inguinoscrotal = hernia)",
"Fluctuation test: POSITIVE",
"Transillumination: brilliant (clear fluid) / negative (blood / pus)",
"Temperature: normal / warm (secondary)",
"Tenderness: absent (primary) / present (secondary)",
"Testis palpable separately posteriorly: YES / NO",
"Consistency: soft, fluctuant, tense",
"Cough impulse: ABSENT (distinguishes from hernia)",
"Reducibility: NOT reducible",
"Epididymis palpable: normal / thickened / tender",
"Associated testicular mass (secondary hydrocele → exclude tumour)",
], 2, styles)); story.append(sp(4))
story.append(section_header("TYPES OF HYDROCELE", styles)); story.append(sp(4))
data = [
[Paragraph("Type", styles["field_label"]),
Paragraph("Feature", styles["field_label"]),
Paragraph("Get Above", styles["field_label"]),
Paragraph("Present", styles["field_label"])],
[Paragraph("Primary Vaginal", styles["body"]),
Paragraph("Idiopathic adult, surrounds testis", styles["body"]),
Paragraph("Yes", styles["body"]), "☐"],
[Paragraph("Secondary", styles["body"]),
Paragraph("Due to testicular pathology (tumor/orchitis/TB/torsion)", styles["body"]),
Paragraph("Yes", styles["body"]), "☐"],
[Paragraph("Congenital", styles["body"]),
Paragraph("Patent processus vaginalis, reduces at night", styles["body"]),
Paragraph("No (inguinoscrotal)", styles["body"]), "☐"],
[Paragraph("Infantile", styles["body"]),
Paragraph("Obliterated at deep ring; cord + tunica filled", styles["body"]),
Paragraph("No", styles["body"]), "☐"],
[Paragraph("Encysted (cord)", styles["body"]),
Paragraph("Cystic swelling along spermatic cord / inguinal canal", styles["body"]),
Paragraph("Yes (separate from testis)", styles["body"]), "☐"],
]
t = Table(data, colWidths=[(W-4*cm)*0.22, (W-4*cm)*0.48, (W-4*cm)*0.18, (W-4*cm)*0.12])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BLUE),
("GRID", (0,0), (-1,-1), 0.5, MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("ALIGN", (2,0), (-1,-1), "CENTER"),
("FONTSIZE", (3,1), (3,-1), 14),
]))
story.append(t); story.append(sp(6))
story.append(section_header("DIFFERENTIAL DIAGNOSIS OF SCROTAL SWELLING", styles)); story.append(sp(4))
data = [
[Paragraph("Condition", styles["field_label"]),
Paragraph("Transillumination", styles["field_label"]),
Paragraph("Cough Impulse", styles["field_label"]),
Paragraph("Can Get Above", styles["field_label"]),
Paragraph("Reducible", styles["field_label"])],
["Hydrocele", "Brilliant +++", "Absent", "Yes", "No"],
["Inguinal hernia", "Absent", "Present", "No", "Yes"],
["Epididymal cyst", "Present +", "Absent", "Yes", "No"],
["Varicocele", "Absent", "Absent", "Yes (barely)", "No"],
["Testicular tumour", "Absent", "Absent", "Yes", "No"],
["Haematocele", "Absent", "Absent", "Yes", "No"],
["Epididymo-orchitis", "Absent/±", "Absent", "Yes", "No"],
]
col_w = (W-4*cm) / 5
t = Table(data, colWidths=[col_w*1.3, col_w*1.1, col_w*0.9, col_w*0.9, col_w*0.8])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BLUE),
("GRID", (0,0), (-1,-1), 0.5, MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
("FONTSIZE", (0,0), (-1,-1), 8),
("BACKGROUND", (0,1), (-1,-1), BOX_BG),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BOX_BG, colors.white]),
]))
story.append(t); story.append(sp(6))
story.append(section_header("INVESTIGATIONS", styles)); story.append(sp(4))
story.append(checklist_table([
"Ultrasound scrotum (mandatory: exclude testicular tumour)",
"CBC, urine routine (if secondary cause suspected)",
"Testicular tumour markers: AFP, β-hCG, LDH",
"Microfilaria (blood smear: nocturnal – Wuchereria bancrofti)",
"CXR (if TB suspected)", "Mantoux test (if TB suspected)",
], 2, styles)); story.append(sp(4))
story.append(write_box("Investigation findings:", 2, styles)); story.append(sp(6))
story.append(section_header("MANAGEMENT", styles)); story.append(sp(4))
story.append(checklist_table([
"Conservative (small, asymptomatic – observe)",
"Aspiration (temporary, recurrence high – use only as diagnostic / high-risk patients)",
"Jaboulay's procedure (eversion of sac – large thin-walled hydrocele)",
"Lord's plication (plicate sac without eversion – smaller hydrocele)",
"Excision of sac (thick-walled / loculated / old hydrocele)",
"Treat underlying cause (secondary hydrocele)",
"Diethylcarbamazine (DEC) for filarial hydrocele (medical)",
], 2, styles)); story.append(sp(3))
story.append(write_box("Operative plan / Treatment decision:", 2, styles)); story.append(sp(6))
story.append(section_header("VIVA QUESTIONS", styles)); story.append(sp(4))
viva_qs = [
"Define hydrocele. What is the tunica vaginalis?",
"What is the processus vaginalis? Its embryological significance in hydrocele.",
"Classify hydrocele with features of each type.",
"How do you differentiate hydrocele from an inguinal hernia clinically?",
"What is the transillumination test? What is the underlying principle?",
"Why is ultrasound mandatory in hydrocele?",
"What surgical procedures are used for hydrocele? Compare Jaboulay vs Lord's.",
"What is a secondary hydrocele? List its causes.",
"What is filarial hydrocele? Which parasite? How is it treated?",
"What is a varicocele? How is it differentiated from hydrocele?",
"What is the significance of a right-sided varicocele?",
"What is testicular torsion? How is it differentiated from epididymo-orchitis?",
"What are testicular tumour markers? Name the types of testicular tumours.",
"What is a spermatocele? How is it differentiated from hydrocele?",
"What are the complications of hydrocele surgery?",
]
story.append(viva_box(viva_qs, styles))
story.append(sp(6))
story.append(Paragraph(
"Sources: Bailey & Love 28th Ed | Campbell Walsh Wein Urology",
styles["footer"]))
return story
# ═══════════════════════════════════════════════════════════════════════════════
# CASE 7 – ULCER (Short Case)
# ═══════════════════════════════════════════════════════════════════════════════
def build_ulcer(styles):
story = []
story.append(header_table(
"CLINICAL CASE PROFORMA", "ULCER | Surgery – Final Year MBBS (Short Case)", styles))
story.append(sp(8))
story.append(section_header("PATIENT BIODATA", styles)); story.append(sp(4))
story.append(info_row(["Name", "Age", "Sex", "IP/OP No."], styles)); story.append(sp(3))
story.append(info_row(["Occupation", "DM / PVD / Neuropathy", "Date", "Examiner"], styles)); story.append(sp(6))
story.append(section_header("CHIEF COMPLAINT", styles)); story.append(sp(4))
story.append(write_box("Non-healing wound / ulcer on _____ since _____", 2, styles)); story.append(sp(6))
story.append(section_header("HISTORY OF PRESENT ILLNESS", styles)); story.append(sp(4))
story.append(checklist_table([
"Sudden onset (trauma, acute ischaemia)", "Gradual, insidious onset",
"Painless (neuropathic / Marjolin's)", "Very painful (ischaemic)",
"Mildly painful (venous)", "Spreading / increasing in size",
"Healing slowly", "Non-healing > 6 weeks",
"Discharge: serous / purulent / haemorrhagic / offensive",
"Previous similar ulcer / healed",
"H/o DM (neuropathic + ischaemic foot)", "H/o PVD / claudication",
"H/o varicose veins / DVT (venous ulcer)", "H/o TB (TB ulcer)",
"H/o malignancy (Marjolin's ulcer in old scar / burn)",
"H/o syphilis / STI (syphilitic ulcer)",
], 2, styles)); story.append(sp(6))
story.append(section_header("LOCAL EXAMINATION OF ULCER", styles)); story.append(sp(4))
story.append(Paragraph("Inspection", styles["sub_section"]))
story.append(info_row(["Site", "Size (cm x cm)", "Shape", "Number"], styles)); story.append(sp(3))
story.append(Paragraph("Edge (tick the type)", styles["sub_section"]))
story.append(checklist_table([
"Sloping edge (healing ulcer – granulation tissue sloping up to edge)",
"Undermined edge (TB – caseous destruction undercuts skin)",
"Punched-out edge (ischaemic / syphilitic / pressure)",
"Raised, everted, rolled edge (SCC – malignant ulcer)",
"Raised, beaded/pearly/rolled edge (BCC – rodent ulcer)",
"Irregular edge (traumatic / mixed)",
], 1, styles)); story.append(sp(3))
story.append(Paragraph("Floor (Base)", styles["sub_section"]))
story.append(checklist_table([
"Healthy red granulation tissue (healing)",
"Pale granulation (poorly vascularized / anaemic)",
"Slough – yellow / grey (necrotic tissue)",
"Black eschar (full thickness necrosis)",
"Exposed bone / tendon",
"Pale indurated base (malignancy / fibrous)",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Surrounding Skin", styles["sub_section"]))
story.append(checklist_table([
"Pigmentation (haemosiderin – venous)", "Lipodermatosclerosis (venous)",
"Eczema / dermatitis (venous)", "Atrophic / thin / shiny skin (ischaemic)",
"Callus / hyperkeratosis (neuropathic)", "Warmth / erythema (infective)",
"Loss of hair (ischaemic trophic change)", "Satellite ulcers / nodules",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("Palpation", styles["sub_section"]))
story.append(checklist_table([
"Temperature: warm (venous/infective) / cold (ischaemic)",
"Tenderness: severe (ischaemic) / mild (venous) / absent (neuropathic)",
"Base: soft / indurated (malignancy / fibrosis)",
"Edge: soft / firm / indurated (malignant = hard, everted)",
"Probe to bone: positive (osteomyelitis)",
"Regional lymph nodes: enlarged (infective / malignant)",
"Peripheral pulses: present / absent (ischaemic type)",
"Sensation: normal / reduced (neuropathic type)",
], 2, styles)); story.append(sp(4))
story.append(section_header("ULCER COMPARISON TABLE", styles)); story.append(sp(4))
headers = ["Feature", "Venous", "Ischaemic", "Neuropathic"]
rows = [
["Site", "Medial gaiter, above med. malleolus", "Toe tips, heel, lateral malleolus", "Plantar surface, metatarsal heads"],
["Pain", "Mild-moderate", "Very severe", "Painless"],
["Edge", "Sloping", "Punched-out", "Punched-out + callus"],
["Floor", "Granulation tissue", "Necrotic / pale", "Callus at margins"],
["Surr. skin", "Pigment, eczema, LDS", "Cold, shiny, trophic", "Normal temp; callus"],
["Pulses", "Normal", "Absent / reduced", "Normal"],
["Sensation", "Normal", "Reduced", "Absent"],
["ABPI", ">0.9", "<0.5", "Normal (>0.9)"],
]
col_w = [(W-4*cm)*0.16, (W-4*cm)*0.28, (W-4*cm)*0.28, (W-4*cm)*0.28]
data = [[Paragraph(h, styles["field_label"]) for h in headers]]
for row in rows:
data.append([Paragraph(cell, styles["body"]) for cell in row])
t = Table(data, colWidths=col_w)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BLUE),
("GRID", (0,0), (-1,-1), 0.5, MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BOX_BG, colors.white]),
("FONTSIZE", (0,0), (-1,-1), 8),
]))
story.append(t); story.append(sp(6))
story.append(section_header("INVESTIGATIONS", styles)); story.append(sp(4))
story.append(checklist_table([
"CBC, ESR, CRP (infection markers)", "Blood glucose / HbA1c",
"ABPI (ischaemic component)", "Duplex USG (venous / arterial)",
"Wound swab C&S (infecting organism)", "Biopsy (if malignancy suspected)",
"X-ray of underlying bone (osteomyelitis)", "Skin punch biopsy (TB / atypical)",
"Venography (venous disease)",
], 2, styles)); story.append(sp(4))
story.append(write_box("Investigation findings:", 2, styles)); story.append(sp(6))
story.append(section_header("MANAGEMENT PLAN", styles)); story.append(sp(4))
story.append(checklist_table([
"Venous ulcer: 4-layer compression bandage (Charing Cross), leg elevation, skin graft",
"Ischaemic ulcer: vascular reconstruction / angioplasty / amputation",
"Neuropathic (diabetic): offloading (total contact cast), wound care, glycaemic control",
"Infective ulcer: wound debridement + systemic antibiotics",
"Malignant ulcer (SCC/BCC): wide local excision / Mohs surgery / radiotherapy",
"TB ulcer: anti-TB therapy (HRZE regimen)",
"Wound debridement, dressing (appropriate type)",
"Skin grafting (split-thickness / full-thickness)",
"Vacuum-assisted closure (VAC) / negative pressure wound therapy",
"Nutritional support (high-protein diet, Vitamin C, Zinc)",
], 2, styles)); story.append(sp(3))
story.append(write_box("Management plan for this case:", 3, styles)); story.append(sp(6))
story.append(section_header("VIVA QUESTIONS", styles)); story.append(sp(4))
viva_qs = [
"Define an ulcer. What is the difference between an ulcer, a sinus, and a fistula?",
"Classify ulcers by cause, edge, and healing status.",
"What is a Marjolin's ulcer? Where does it occur? What is its histology?",
"What is a rodent ulcer (BCC)? Describe its edge.",
"What are the types of ulcer edge? What does each indicate?",
"Compare venous, ischaemic, and neuropathic ulcers.",
"What is the management of a venous leg ulcer?",
"What is a 4-layer compression bandage (Charing Cross)?",
"What is the management of a diabetic foot ulcer?",
"What are the principles of wound healing (primary, secondary, tertiary intention)?",
"What is granulation tissue? What cells form it?",
"What is slough vs eschar?",
"What is vacuum-assisted closure (VAC therapy)?",
"What is skin grafting? Difference between SSG and FSG?",
"What is a Buruli ulcer? What organism causes it?",
]
story.append(viva_box(viva_qs, styles))
story.append(sp(6))
story.append(Paragraph(
"Sources: Bailey & Love 28th Ed | Schwartz's Principles of Surgery 11th Ed",
styles["footer"]))
return story
# ═══════════════════════════════════════════════════════════════════════════════
# CASE 8 – SWELLING (Lipoma / Sebaceous Cyst / Dermoid / Abscess / Lymph Node)
# ═══════════════════════════════════════════════════════════════════════════════
def build_swelling(styles):
story = []
story.append(header_table(
"CLINICAL CASE PROFORMA", "SWELLING (SHORT CASE) | Surgery – Final Year MBBS", styles))
story.append(sp(8))
story.append(section_header("PATIENT BIODATA", styles)); story.append(sp(4))
story.append(info_row(["Name", "Age", "Sex", "IP/OP No."], styles)); story.append(sp(3))
story.append(info_row(["Site of Swelling", "Duration", "Date", "Examiner"], styles)); story.append(sp(6))
story.append(section_header("UNIVERSAL SWELLING EXAMINATION PROFORMA", styles)); story.append(sp(4))
story.append(Paragraph("History", styles["sub_section"]))
story.append(checklist_table([
"Gradual onset", "Sudden onset",
"Slowly progressive", "Rapidly increasing",
"Painful", "Painless",
"Discharge from surface", "H/o trauma at site",
"H/o fever / systemic illness", "H/o malignancy elsewhere",
"Change in size with posture", "Fluctuation in size over time",
], 2, styles)); story.append(sp(4))
story.append(Paragraph("INSPECTION", styles["sub_section"]))
story.append(info_row(["Site", "Size (approx.)", "Shape", "Number"], styles)); story.append(sp(3))
story.append(checklist_table([
"Skin: normal over swelling", "Skin: stretched / thinned",
"Skin: erythematous / warm (abscess)", "Skin: punctum present (sebaceous cyst)",
"Skin: attached to swelling", "Skin: freely mobile over swelling",
"Transillumination: positive (cystic/fluid)", "Transillumination: negative",
"Pulsation visible", "No pulsation",
"Peristalsis visible (bowel hernia)", "Veins dilated over swelling",
], 2, styles)); story.append(sp(3))
story.append(Paragraph("PALPATION – Systematic", styles["sub_section"]))
story.append(checklist_table([
"Temperature: warm (inflammatory/vascular) / normal",
"Tenderness: present / absent",
"Surface: smooth / lobulated / irregular",
"Margin/Edge: well-defined / ill-defined",
"Consistency: soft / firm / hard / rubbery",
"Fluctuation test (2-finger, 2-planes): POSITIVE (fluid) / NEGATIVE",
"Transillumination test: POSITIVE (clear fluid) / NEGATIVE",
"Compressibility (disappears on pressure, reappears – haemangioma) YES / NO",
"Reducibility (goes into cavity – hernia): YES / NO",
"Pulsatility: Expansile (aneurysm) / Transmitted / None",
"Skin relation: skin attached / freely moveable over swelling",
"Slip sign (lipoma): slips under finger like butter / absent",
"Deep relation: fixed to deep fascia / muscle / bone",
"Lymph nodes: regional enlarged / normal",
], 1, styles)); story.append(sp(4))
story.append(section_header("DIFFERENTIAL DIAGNOSIS GRID", styles)); story.append(sp(4))
headers = ["Feature", "Lipoma", "Sebaceous Cyst", "Dermoid Cyst", "Abscess", "Lymph Node"]
rows = [
["Site", "Anywhere (subcutaneous)", "Hair-bearing areas, scalp, face, scrotum", "Lines of fusion (ext. angular, midline nose)", "Any site", "Nodal drainage area"],
["Skin attached", "No", "YES (fixed to skin)", "No (fixed to periosteum)", "Erythematous", "No"],
["Punctum", "Absent", "PRESENT", "Absent", "Pointing/sinus", "Absent"],
["Fluctuation", "Pseudo (soft)", "Tense / ±", "Positive (doughy)", "POSITIVE", "Firm / soft"],
["Transillumination", "Negative (fat)", "Negative", "Negative (doughy)", "Negative", "Negative"],
["Slip sign", "POSITIVE", "Absent", "Absent", "Absent", "Absent"],
["Tenderness", "Absent", "Absent unless infected", "Absent", "PRESENT (severe)", "Varies"],
["Consistency", "Soft, pseudofluctuant, lobulated", "Pastry-like, tense", "Doughy, cystic", "Fluctuant, hot", "Firm / rubbery / hard"],
["Treatment", "Excision (symptomatic)", "Excision with sac + punctum", "Excision (dermoid intact)", "I & D", "Treat cause / excision biopsy"],
]
col_w = [(W-4*cm)*0.13] + [(W-4*cm)*0.174]*5
data = [[Paragraph(h, styles["field_label"]) for h in headers]]
for row in rows:
data.append([Paragraph(cell, styles["body"]) for cell in row])
t = Table(data, colWidths=col_w)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BLUE),
("GRID", (0,0), (-1,-1), 0.5, MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 3),
("ROWBACKGROUNDS", (0,1), (-1,-1), [BOX_BG, colors.white]),
("FONTSIZE", (0,0), (-1,-1), 7.5),
]))
story.append(t); story.append(sp(6))
story.append(section_header("INVESTIGATIONS", styles)); story.append(sp(4))
story.append(checklist_table([
"FNAC (lymph node, soft tissue, suspected malignancy)", "Core biopsy / excision biopsy",
"Ultrasound (define depth, cystic vs solid, lymph node architecture)",
"MRI (deep-seated / retroperitoneal lipoma / soft tissue tumour)",
"X-ray (if bony involvement / dermoid pressure erosion)",
"CBC, ESR, CRP (abscess / lymphadenopathy)", "Mantoux test (if TB lymphadenopathy)",
"Blood culture (if systemic sepsis)", "Wound C&S (abscess)",
], 2, styles)); story.append(sp(6))
story.append(section_header("VIVA QUESTIONS", styles)); story.append(sp(4))
viva_qs = [
"Describe the systematic examination of a swelling (10 steps of palpation).",
"What is the fluctuation test? How is it performed? What does it indicate?",
"What is the transillumination test? Give examples of conditions where it is positive.",
"What is the slip sign of lipoma?",
"What is Dercum's disease (multiple painful lipomas)?",
"What is a sebaceous cyst? Is it really a sebaceous cyst? What is the correct name?",
"Why is the punctum pathognomonic of a sebaceous cyst?",
"What is a cock's peculiar tumour?",
"What are the types of dermoid cyst? What does it contain?",
"How does a dermoid cyst differ from a sebaceous cyst? (3 key differences)",
"What is a sequestration dermoid? Name its sites.",
"What is a cold abscess? How does it differ from a pyogenic abscess?",
"What is a collar stud abscess?",
"What are Reed-Sternberg cells? What is Hodgkin's lymphoma?",
"What is Virchow's node (Troisier's sign)?",
]
story.append(viva_box(viva_qs, styles))
story.append(sp(6))
story.append(Paragraph(
"Sources: Bailey & Love 28th Ed | Pye's Surgical Handicraft 22nd Ed",
styles["footer"]))
return story
# ═══════════════════════════════════════════════════════════════════════════════
# PDF BUILDER
# ═══════════════════════════════════════════════════════════════════════════════
def build_pdf(filename, story_fn, styles):
path = os.path.join(OUTPUT_DIR, filename)
doc = SimpleDocTemplate(
path, pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=1.5*cm, bottomMargin=2*cm
)
doc.build(story_fn(styles))
print(f" Created: {path}")
return path
if __name__ == "__main__":
styles = make_styles()
files = []
print("Building individual proforma PDFs...")
files.append(build_pdf("01_Inguinal_Hernia_Proforma.pdf", build_inguinal_hernia, styles))
files.append(build_pdf("02_Thyroid_Swelling_Proforma.pdf", build_thyroid, styles))
files.append(build_pdf("03_Breast_Carcinoma_Proforma.pdf", build_breast, styles))
files.append(build_pdf("04_Peripheral_Vascular_Disease_Proforma.pdf", build_pvd, styles))
files.append(build_pdf("05_Varicose_Veins_Proforma.pdf", build_varicose_veins, styles))
files.append(build_pdf("06_Hydrocele_Proforma.pdf", build_hydrocele, styles))
files.append(build_pdf("07_Ulcer_Proforma.pdf", build_ulcer, styles))
files.append(build_pdf("08_Swelling_Short_Case_Proforma.pdf", build_swelling, styles))
# Merge all into one master PDF
print("\nMerging into master PDF...")
writer = PdfWriter()
for f in files:
reader = PdfReader(f)
for page in reader.pages:
writer.add_page(page)
master_path = os.path.join(OUTPUT_DIR, "00_SURGERY_PROFORMAS_COMPLETE.pdf")
with open(master_path, "wb") as out:
writer.write(out)
print(f" Master PDF: {master_path}")
print("\nAll done!")
cd /tmp/workspace/surgery-proformas && python generate_proformas.py 2>&1
| # | Case | |
|---|---|---|
| 1 | Inguinal Hernia | 01 Inguinal Hernia Proforma PDF Document · PDF |
| 2 | Thyroid Swelling | 02 Thyroid Swelling Proforma PDF Document · PDF |
| 3 | Breast Carcinoma | 03 Breast Carcinoma Proforma PDF Document · PDF |
| 4 | Peripheral Vascular Disease | 04 Peripheral Vascular Disease Proforma PDF Document · PDF |
| 5 | Varicose Veins | 05 Varicose Veins Proforma PDF Document · PDF |
| 6 | Hydrocele | 06 Hydrocele Proforma PDF Document · PDF |
| 7 | Ulcer | 07 Ulcer Proforma PDF Document · PDF |
| 8 | Swelling (Short Case) | 08 Swelling Short Case Proforma PDF Document · PDF |
00 SURGERY PROFORMAS COMPLETE
PDF Document · PDF