Answer with proper mbbs Proff with diagrams PDF
mkdir -p /tmp/workspace/surgery-paper && ls /tmp/workspace/surgery-paper/
~/surgery-paper/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle, Polygon
from reportlab.graphics import renderPDF
from reportlab.platypus import Flowable
import io
# ── Output path ──────────────────────────────────────────────────────────────
OUTPUT = "/tmp/workspace/surgery-paper/Surgery_Paper_I_Answers.pdf"
# ── Document setup ────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=2*cm, leftMargin=2*cm,
topMargin=2*cm, bottomMargin=2*cm,
title="Surgery Paper I – Model Answers",
author="MBBS Final Prof"
)
W, H = A4
CW = W - 4*cm # content width
# ── Colour palette ────────────────────────────────────────────────────────────
DARK_BLUE = colors.HexColor("#1a3a5c")
MID_BLUE = colors.HexColor("#2e6da4")
LIGHT_BLUE = colors.HexColor("#d0e4f7")
ACCENT = colors.HexColor("#e8734a")
GREEN = colors.HexColor("#2e7d32")
LIGHT_GREEN = colors.HexColor("#e8f5e9")
YELLOW_BG = colors.HexColor("#fff9e6")
GREY = colors.HexColor("#607080")
LIGHT_GREY = colors.HexColor("#f0f4f8")
# ── Styles ────────────────────────────────────────────────────────────────────
SS = getSampleStyleSheet()
def make_style(name, parent="Normal", **kw):
s = ParagraphStyle(name, parent=SS[parent], **kw)
return s
S_COVER_TITLE = make_style("CoverTitle", fontName="Helvetica-Bold", fontSize=20,
textColor=DARK_BLUE, alignment=TA_CENTER, spaceAfter=6)
S_COVER_SUB = make_style("CoverSub", fontName="Helvetica", fontSize=13,
textColor=MID_BLUE, alignment=TA_CENTER, spaceAfter=4)
S_Q_HEADER = make_style("QHeader", fontName="Helvetica-Bold", fontSize=13,
textColor=colors.white, spaceAfter=4)
S_SECTION = make_style("Section", fontName="Helvetica-Bold", fontSize=11,
textColor=MID_BLUE, spaceAfter=3, spaceBefore=6)
S_BODY = make_style("Body", fontName="Helvetica", fontSize=10,
leading=15, spaceAfter=4, alignment=TA_JUSTIFY)
S_BULLET = make_style("Bullet", fontName="Helvetica", fontSize=10,
leading=14, leftIndent=14, bulletIndent=4,
spaceAfter=2)
S_SUB_BULLET = make_style("SubBullet", fontName="Helvetica", fontSize=9.5,
leading=13, leftIndent=28, bulletIndent=14,
spaceAfter=1)
S_TABLE_HDR = make_style("TableHdr", fontName="Helvetica-Bold", fontSize=9,
textColor=colors.white, alignment=TA_CENTER)
S_TABLE_CELL = make_style("TableCell", fontName="Helvetica", fontSize=9,
leading=12, alignment=TA_LEFT)
S_NOTE = make_style("Note", fontName="Helvetica-Oblique", fontSize=9,
textColor=GREY, spaceAfter=3)
S_MARKS = make_style("Marks", fontName="Helvetica-Bold", fontSize=9,
textColor=ACCENT, alignment=TA_LEFT)
S_LABEL = make_style("Label", fontName="Helvetica-BoldOblique", fontSize=9,
textColor=DARK_BLUE)
story = []
# ─────────────────────────────────────────────────────────────────────────────
# Helper utilities
# ─────────────────────────────────────────────────────────────────────────────
def q_banner(num, text, marks):
"""Coloured banner for each question."""
data = [[
Paragraph(f"Q{num}. {text}", S_Q_HEADER),
Paragraph(f"[{marks}]", S_MARKS)
]]
t = Table(data, colWidths=[CW - 2*cm, 2*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0),(-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (1,0), (1,0), "RIGHT"),
]))
return t
def section(text):
return Paragraph(text, S_SECTION)
def body(text):
return Paragraph(text, S_BODY)
def bullet(text, sub=False):
s = S_SUB_BULLET if sub else S_BULLET
return Paragraph(f"• {text}", s)
def note(text):
return Paragraph(f"<i>{text}</i>", S_NOTE)
def sp(h=4):
return Spacer(1, h)
def hr():
return HRFlowable(width="100%", thickness=0.5, color=LIGHT_BLUE, spaceAfter=4)
def box_table(rows, col_widths, header=True):
style = [
("GRID", (0,0), (-1,-1), 0.5, MID_BLUE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING",(0,0), (-1,-1), 6),
]
if header:
style += [
("BACKGROUND", (0,0), (-1,0), MID_BLUE),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 9),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_BLUE]),
]
else:
style += [
("ROWBACKGROUNDS", (0,0), (-1,-1), [colors.white, LIGHT_BLUE]),
("FONTSIZE", (0,0), (-1,-1), 9),
]
tbl = Table([[Paragraph(str(c), S_TABLE_CELL) for c in r] for r in rows],
colWidths=col_widths)
tbl.setStyle(TableStyle(style))
return tbl
# ─────────────────────────────────────────────────────────────────────────────
# ASCII/Vector diagram helpers
# ─────────────────────────────────────────────────────────────────────────────
class SimpleDiagram(Flowable):
"""Base class for inline SVG-style drawings."""
def __init__(self, width, height):
Flowable.__init__(self)
self.width = width
self.height = height
def wrap(self, *args):
return (self.width, self.height)
class WoundHealingDiagram(SimpleDiagram):
"""Timeline diagram for wound healing phases."""
def __init__(self):
super().__init__(CW, 110)
def draw(self):
c = self.canv
W, H = self.width, self.height
phases = [
("Haemostasis\n(0–hours)", 0.0, 0.15, ACCENT),
("Inflammation\n(1–4 days)", 0.15, 0.35, colors.HexColor("#e53935")),
("Proliferation\n(4–21 days)", 0.35, 0.75, MID_BLUE),
("Remodelling\n(21 days–2 yr)", 0.75, 1.0, GREEN),
]
bar_y = H * 0.55
bar_h = 28
for label, x0, x1, col in phases:
px = W * x0
pw = W * (x1 - x0)
c.setFillColor(col)
c.rect(px, bar_y, pw - 2, bar_h, fill=1, stroke=0)
lines = label.split("\n")
c.setFillColor(colors.white)
c.setFont("Helvetica-Bold", 7.5)
mid_x = px + pw / 2
c.drawCentredString(mid_x, bar_y + bar_h - 12, lines[0])
c.setFont("Helvetica", 6.5)
c.drawCentredString(mid_x, bar_y + 4, lines[1])
# Arrow
c.setStrokeColor(GREY)
c.setLineWidth(1)
c.line(0, bar_y - 8, W, bar_y - 8)
c.setFillColor(GREY)
c.polygon([W, bar_y - 8, W - 8, bar_y - 4, W - 8, bar_y - 12], fill=1, stroke=0)
c.setFont("Helvetica-Oblique", 8)
c.setFillColor(GREY)
c.drawCentredString(W / 2, bar_y - 20, "← Time →")
# Title
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(W / 2, H - 8, "PHASES OF WOUND HEALING")
class ShockDiagram(SimpleDiagram):
"""Simple cascade diagram for septic shock pathophysiology."""
def __init__(self):
super().__init__(CW, 220)
def _box(self, c, x, y, w, h, text, bg, fg=colors.white, font_size=8):
c.setFillColor(bg)
c.roundRect(x, y, w, h, 5, fill=1, stroke=0)
c.setFillColor(fg)
c.setFont("Helvetica-Bold", font_size)
lines = text.split("\n")
for i, ln in enumerate(reversed(lines)):
c.drawCentredString(x + w / 2, y + 6 + i * 11, ln)
def _arrow(self, c, x1, y1, x2, y2):
c.setStrokeColor(GREY)
c.setLineWidth(1.2)
c.line(x1, y1, x2, y2)
c.setFillColor(GREY)
# simple arrowhead
c.polygon([x2, y2, x2 - 5, y2 + 6, x2 + 5, y2 + 6], fill=1, stroke=0)
def draw(self):
c = self.canv
W, H = self.width, self.height
bw = 160
bh = 26
cx = W / 2
items = [
("Gram -ve / +ve Bacteria (LPS / LTA)", ACCENT),
("Macrophage activation → TNF-α, IL-1, IL-6", colors.HexColor("#e53935")),
("Vasodilation + ↑ Vascular Permeability", MID_BLUE),
("Distributive Shock\n(↓SVR, ↑CO early)", colors.HexColor("#7b1fa2")),
("Tissue Hypoxia → Lactic Acidosis", GREEN),
("MODS → Death (if untreated)", colors.HexColor("#b71c1c")),
]
start_y = H - 32
gap = 34
for i, (txt, col) in enumerate(items):
y = start_y - i * gap
self._box(c, cx - bw / 2, y, bw, bh, txt, col)
if i < len(items) - 1:
self._arrow(c, cx, y, cx, y - gap + bh + 1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(cx, H - 12, "PATHOPHYSIOLOGY OF SEPTIC SHOCK")
class BurnRuleNines(SimpleDiagram):
"""Rule of Nines body diagram."""
def __init__(self):
super().__init__(CW, 200)
def draw(self):
c = self.canv
W, H = self.width, self.height
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(W / 2, H - 12, "RULE OF NINES – BURN SURFACE AREA ESTIMATION")
# Front body (simple stick figure + labels)
bx = W / 2 - 60
# Head 9%
c.setFillColor(colors.HexColor("#ffd699"))
c.circle(bx + 60, H - 50, 18, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(bx + 60, H - 52, "9%")
c.setFont("Helvetica", 7)
c.drawCentredString(bx + 60, H - 63, "Head & Neck")
# Trunk 36%
c.setFillColor(colors.HexColor("#ffd699"))
c.rect(bx + 38, H - 115, 44, 55, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(bx + 60, H - 90, "36%")
c.setFont("Helvetica", 7)
c.drawCentredString(bx + 60, H - 100, "Trunk")
c.drawCentredString(bx + 60, H - 110, "(Ant 18% + Post 18%)")
# Arms 9% each
c.setFillColor(colors.HexColor("#ffd699"))
c.rect(bx + 10, H - 115, 26, 45, fill=1, stroke=1)
c.rect(bx + 84, H - 115, 26, 45, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 7.5)
c.drawCentredString(bx + 23, H - 95, "9%")
c.drawCentredString(bx + 97, H - 95, "9%")
c.setFont("Helvetica", 6.5)
c.drawCentredString(bx + 23, H - 105, "Arm")
c.drawCentredString(bx + 97, H - 105, "Arm")
# Legs 18% each
c.setFillColor(colors.HexColor("#ffd699"))
c.rect(bx + 26, H - 175, 28, 58, fill=1, stroke=1)
c.rect(bx + 66, H - 175, 28, 58, fill=1, stroke=1)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 8)
c.drawCentredString(bx + 40, H - 150, "18%")
c.drawCentredString(bx + 80, H - 150, "18%")
c.setFont("Helvetica", 7)
c.drawCentredString(bx + 40, H - 162, "Leg")
c.drawCentredString(bx + 80, H - 162, "Leg")
# Perineum 1%
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica", 7)
c.drawCentredString(bx + 60, H - 185, "Perineum = 1% TOTAL = 100%")
class ThyroidClassDiagram(SimpleDiagram):
"""Simple classification tree for thyroid carcinoma."""
def __init__(self):
super().__init__(CW, 170)
def draw(self):
c = self.canv
W, H = self.width, self.height
def box(x, y, w, h, text, bg):
c.setFillColor(bg)
c.roundRect(x, y, w, h, 4, fill=1, stroke=0)
c.setFillColor(colors.white)
c.setFont("Helvetica-Bold", 7.5)
lines = text.split("\n")
for i, ln in enumerate(reversed(lines)):
c.drawCentredString(x + w / 2, y + 5 + i * 10, ln)
def conn(x1, y1, x2, y2):
c.setStrokeColor(GREY)
c.setLineWidth(0.8)
c.line(x1, y1, x2, y2)
# Root
box(W/2-70, H-40, 140, 26, "THYROID CARCINOMA", DARK_BLUE)
root_bx = W/2
# 4 branches
children = [
("Papillary\n(80%)", 40, H-120, MID_BLUE),
("Follicular\n(10%)", 160, H-120, GREEN),
("Medullary\n(5–8%)", 280, H-120, ACCENT),
("Anaplastic\n(<1%)", 400, H-120, colors.HexColor("#b71c1c")),
]
for label, x, y, col in children:
box(x, y, 90, 26, label, col)
conn(root_bx, H-40, x + 45, y + 26)
# Sub-labels
sub = [
(40+45, H-155, "Most common\nExcellent prognosis"),
(160+45, H-155, "Follicular adenoma\nvs carcinoma: histology"),
(280+45, H-155, "Calcitonin ↑\nMEN 2A/2B"),
(400+45, H-155, "Very aggressive\nPoor prognosis"),
]
c.setFillColor(GREY)
c.setFont("Helvetica", 6.5)
for x, y, txt in sub:
for i, ln in enumerate(txt.split("\n")):
c.drawCentredString(x, y - i * 9, ln)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(W/2, H-8, "CLASSIFICATION OF THYROID CARCINOMA")
class SSIDiagram(SimpleDiagram):
"""CDC classification of SSI."""
def __init__(self):
super().__init__(CW, 130)
def draw(self):
c = self.canv
W, H = self.width, self.height
def box(x, y, w, h, text, bg):
c.setFillColor(bg)
c.roundRect(x, y, w, h, 4, fill=1, stroke=0)
c.setFillColor(colors.white)
c.setFont("Helvetica-Bold", 7.5)
lines = text.split("\n")
for i, ln in enumerate(reversed(lines)):
c.drawCentredString(x + w / 2, y + 4 + i * 10, ln)
box(W/2-70, H-30, 140, 22, "SURGICAL SITE INFECTION (SSI)", DARK_BLUE)
types = [
("Superficial\nIncisional", 20, H-90, MID_BLUE),
("Deep\nIncisional", 155, H-90, colors.HexColor("#1565c0")),
("Organ /\nSpace", 290, H-90, ACCENT),
]
for label, x, y, col in types:
box(x, y, 110, 26, label, col)
c.setStrokeColor(GREY)
c.setLineWidth(0.8)
c.line(W/2, H-30, x+55, y+26)
descs = [
(20+55, H-120, "Skin & subcutaneous\ntissue only"),
(155+55, H-120, "Fascia & muscle\nlayers"),
(290+55, H-120, "Any organ /\nspace opened"),
]
c.setFillColor(GREY)
c.setFont("Helvetica", 6.5)
for x, y, txt in descs:
for i, ln in enumerate(txt.split("\n")):
c.drawCentredString(x, y - i * 9, ln)
c.setFillColor(DARK_BLUE)
c.setFont("Helvetica-Bold", 9)
c.drawCentredString(W/2, H-8, "CDC CLASSIFICATION OF SSI")
# ─────────────────────────────────────────────────────────────────────────────
# COVER PAGE
# ─────────────────────────────────────────────────────────────────────────────
story.append(sp(30))
story.append(Paragraph("TEERTHANKER MAHAVEER MEDICAL COLLEGE", S_COVER_TITLE))
story.append(Paragraph("& RESEARCH CENTRE – MORADABAD (U.P.)", S_COVER_TITLE))
story.append(sp(8))
cover_line = HRFlowable(width="80%", thickness=2, color=MID_BLUE, spaceAfter=8)
story.append(cover_line)
story.append(Paragraph("3rd Prof Part II – Final MBBS", S_COVER_SUB))
story.append(Paragraph("General Surgery – Paper I", S_COVER_SUB))
story.append(Paragraph("Model Answers with Diagrams", make_style("CSub2", parent="Normal",
fontName="Helvetica-Bold", fontSize=15, textColor=ACCENT, alignment=TA_CENTER)))
story.append(sp(10))
story.append(HRFlowable(width="80%", thickness=2, color=MID_BLUE, spaceAfter=20))
info_data = [
["Examination:", "1st Terminal Examination, 8th Semester (Batch 2020)"],
["Date:", "04-04-2024"],
["Maximum Marks:", "100"],
["Duration:", "3 Hours (10:30 AM – 01:30 PM)"],
]
info_tbl = Table(info_data, colWidths=[4*cm, CW - 4*cm])
info_tbl.setStyle(TableStyle([
("FONTNAME", (0,0), (0,-1), "Helvetica-Bold"),
("FONTNAME", (1,0), (1,-1), "Helvetica"),
("FONTSIZE", (0,0), (-1,-1), 10),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
("ROWBACKGROUNDS", (0,0), (-1,-1), [LIGHT_BLUE, colors.white]),
("LEFTPADDING", (0,0), (-1,-1), 8),
("GRID", (0,0), (-1,-1), 0.4, MID_BLUE),
]))
story.append(info_tbl)
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────────
# Q1 – WOUND HEALING
# ─────────────────────────────────────────────────────────────────────────────
story.append(q_banner(1,
"Phases of Wound Healing | Classification of Surgical Wounds | Factors Affecting Wound Healing",
"3+3+4 = 10 Marks"))
story.append(sp(6))
story.append(WoundHealingDiagram())
story.append(sp(4))
story.append(section("A. PHASES OF WOUND HEALING (3 marks)"))
phases_data = [
["Phase", "Timing", "Key Events"],
["1. Haemostasis", "0 – few hours", "Vasoconstriction → platelet plug → coagulation cascade → fibrin clot formation"],
["2. Inflammation", "1 – 4 days", "Vasodilation; neutrophil (1–2 d) & macrophage (2–4 d) infiltration; phagocytosis; release of growth factors (PDGF, EGF, FGF)"],
["3. Proliferation (Granulation)", "4 – 21 days", "Fibroblast migration → collagen synthesis (Type III → Type I); angiogenesis; epithelialisation; wound contraction by myofibroblasts"],
["4. Remodelling (Maturation)", "21 days – 2 years", "Type III → Type I collagen replacement; tensile strength ↑ (max 80% of normal at 3 months); scar formation"],
]
story.append(box_table(phases_data, [2.5*cm, 2.5*cm, CW - 5*cm]))
story.append(sp(6))
story.append(section("B. CLASSIFICATION OF SURGICAL WOUNDS (3 marks)"))
story.append(body(
"The CDC/NRC wound classification is based on the degree of contamination and predicts SSI risk:"
))
wound_data = [
["Class", "Name", "Definition", "SSI Risk"],
["I", "Clean", "Elective, no hollow viscus entered, no inflammation. Primary closure.\nEx: herniorrhaphy, mastectomy", "1–2%"],
["II", "Clean-Contaminated","Hollow viscus entered under controlled conditions.\nEx: elective cholecystectomy, appendicectomy (non-inflamed)", "5–10%"],
["III", "Contaminated", "Open accidental wounds; gross GI spillage; acute inflammation (non-purulent).\nEx: fresh trauma, perforated appendix", "15–20%"],
["IV", "Dirty / Infected", "Old traumatic wound with devitalised tissue, faecal contamination, or perforated viscus.\nEx: faecal peritonitis, empyema", ">30%"],
]
story.append(box_table(wound_data, [1.2*cm, 3*cm, CW - 6*cm, 1.8*cm]))
story.append(sp(6))
story.append(section("C. FACTORS AFFECTING WOUND HEALING (4 marks)"))
story.append(body("<b>Local factors:</b>"))
local = [
"Blood supply (ischaemia is the most important local factor)",
"Wound infection / contamination",
"Foreign bodies, necrotic tissue",
"Wound tension and movement",
"Radiation injury – damages microvasculature and fibroblasts",
"Haematoma / seroma formation",
]
for f in local:
story.append(bullet(f))
story.append(body("<b>Systemic factors:</b>"))
systemic = [
"Malnutrition – deficiency of protein, Vitamin C (collagen synthesis), Zinc, Vitamin A",
"Diabetes mellitus – impaired leukocyte function, microangiopathy",
"Anaemia and hypoxia – reduce fibroblast proliferation",
"Jaundice – impairs collagen synthesis",
"Corticosteroids – inhibit inflammation and fibroblast activity",
"Chemotherapy / immunosuppression",
"Age – elderly patients heal more slowly",
"Obesity – poor vascularisation of adipose tissue",
]
for f in systemic:
story.append(bullet(f))
story.append(note("Reference: Bailey & Love's Short Practice of Surgery, 28th Ed."))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────────
# Q2 – BLOOD TRANSFUSION
# ─────────────────────────────────────────────────────────────────────────────
story.append(q_banner(2,
"Donor Criteria | Massive Blood Transfusion | Complications of Blood Transfusion",
"2.5+2.5+5 = 10 Marks"))
story.append(sp(6))
story.append(section("A. DONOR CRITERIA FOR BLOOD TRANSFUSION (2.5 marks)"))
donor_data = [
["Parameter", "Criterion"],
["Age", "18 – 65 years"],
["Weight", "> 45 kg"],
["Haemoglobin", "> 12.5 g/dL (females), > 13.5 g/dL (males)"],
["Blood pressure", "Systolic 100–180 mmHg; Diastolic 60–100 mmHg"],
["Pulse", "60–100 bpm, regular"],
["Donation interval","Whole blood: every 3 months (min 56 days)"],
["Exclusions", "HIV, HBsAg, HCV, syphilis, malaria, TB, recent surgery, pregnancy, medications (anticoagulants)"],
]
story.append(box_table(donor_data, [3.5*cm, CW - 3.5*cm]))
story.append(sp(6))
story.append(section("B. MASSIVE BLOOD TRANSFUSION (2.5 marks)"))
story.append(body(
"<b>Definition:</b> Transfusion of ≥10 units of packed RBCs within 24 hours, "
"OR replacement of the entire blood volume (approx. 70 mL/kg) within 24 hours, "
"OR transfusion of >4 units in 1 hour with ongoing haemorrhage."
))
story.append(body(
"<b>Damage Control Resuscitation (DCR) in massive haemorrhage:</b>"
))
mbt = [
"Target ratio: RBCs : FFP : Platelets = 1:1:1 (mimics whole blood)",
"Tranexamic acid – given as soon as possible (antifibrinolytic)",
"Cryoprecipitate – for hypofibrinogenaemia",
"Calcium gluconate – to counter citrate-induced hypocalcaemia",
"Warm all blood products to prevent hypothermia",
"Avoid crystalloids/colloids – worsen dilutional coagulopathy",
"Massive transfusion protocol (MTP) activation in trauma centres",
]
for m in mbt:
story.append(bullet(m))
story.append(sp(6))
story.append(section("C. COMPLICATIONS OF BLOOD TRANSFUSION (5 marks)"))
story.append(body("<b>I. Immunological (Immediate):</b>"))
imm = [
"Acute haemolytic reaction – ABO incompatibility; fever, rigors, loin pain, haemoglobinuria; can cause DIC and renal failure",
"Febrile non-haemolytic reaction – anti-leukocyte antibodies; fever 1°C rise, managed with paracetamol",
"Allergic (urticarial) reaction – IgE-mediated; rash, pruritus; managed with antihistamines",
"Anaphylaxis – rare; IgA deficiency in recipient",
"TRALI (Transfusion-Related Acute Lung Injury) – from anti-leukocyte antibodies in donor plasma (FFP)",
"TACO (Transfusion-Associated Circulatory Overload) – elderly / cardiac patients",
]
for i in imm:
story.append(bullet(i))
story.append(body("<b>II. Infectious:</b>"))
infect = [
"Bacterial (commonest in platelets) – Yersinia, Staphylococcus",
"Viral – HBV, HCV, HIV, CMV, EBV",
"Parasitic – Malaria, Chagas disease, Toxoplasmosis",
]
for i in infect:
story.append(bullet(i))
story.append(body("<b>III. Complications of Massive Transfusion:</b>"))
mass_comp = [
"Coagulopathy – dilutional",
"Hypocalcaemia – citrate (preservative) chelates Ca²⁺",
"Hyperkalaemia → Hypokalaemia (initially ↑K⁺ from stored blood, then ↓K⁺ as cells resume metabolism)",
"Hypothermia – cold blood",
"Metabolic alkalosis – citrate → bicarbonate",
"Iron overload – each unit contains ~250 mg elemental iron (chronic transfusions)",
"Microaggregate emboli – pulmonary microembolism",
]
for m in mass_comp:
story.append(bullet(m))
story.append(note("Reference: Bailey & Love's 28th Ed., Morgan & Mikhail's Clinical Anesthesiology 7th Ed."))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────────
# Q3 – SSI
# ─────────────────────────────────────────────────────────────────────────────
story.append(q_banner(3,
"SSI – Definition | Organisms | Classification | Prevention | Management",
"1+1+3+3+2 = 10 Marks"))
story.append(sp(6))
story.append(SSIDiagram())
story.append(sp(4))
story.append(section("A. DEFINITION (1 mark)"))
story.append(body(
"<b>Surgical Site Infection (SSI)</b> is an infection occurring within <b>30 days</b> of surgery "
"(or within <b>1 year</b> if implant is in place) and involves the incision, deep tissue, or organ/space "
"opened during the procedure. Defined by the CDC/NHSN criteria."
))
story.append(section("B. ORGANISMS CAUSING SSI (1 mark)"))
org_data = [
["Category", "Common Organisms"],
["Gram-positive", "Staphylococcus aureus (most common overall), MRSA, Streptococcus, Enterococcus"],
["Gram-negative", "E. coli, Klebsiella, Pseudomonas, Proteus, Enterobacter"],
["Anaerobes", "Bacteroides fragilis (colorectal surgery), Clostridium"],
["Fungi (rare)", "Candida (immunocompromised)"],
]
story.append(box_table(org_data, [3*cm, CW - 3*cm]))
story.append(sp(4))
story.append(section("C. CLASSIFICATION (3 marks)"))
story.append(body("<b>CDC Classification (1992) – 3 types:</b>"))
class_data = [
["Type", "Involves", "Time", "Criteria"],
["Superficial Incisional SSI",
"Skin + subcutaneous tissue",
"≤30 days",
"Purulent drainage, organisms isolated, pain/tenderness/swelling/redness and wound opened by surgeon"],
["Deep Incisional SSI",
"Fascia and muscle layers",
"≤30 days (≤1 yr if implant)",
"Purulent drainage from deep incision, spontaneous dehiscence, abscess on re-exploration"],
["Organ/Space SSI",
"Any organ or space opened during surgery",
"≤30 days (≤1 yr if implant)",
"Purulent drainage from drain, abscess or infection found on re-exploration, positive cultures"],
]
story.append(box_table(class_data, [3.5*cm, 3*cm, 2*cm, CW - 8.5*cm]))
story.append(sp(4))
story.append(section("D. PREVENTION (3 marks)"))
prev = [
"<b>Pre-operative:</b> treat remote infections, diabetes control, smoking cessation, MRSA decolonisation (mupirocin), antiseptic shower, correct skin preparation (alcoholic chlorhexidine), prophylactic antibiotics within 60 min before incision",
"<b>Intra-operative:</b> strict aseptic technique, careful haemostasis, minimal dead space, avoid excessive diathermy, normothermia, normoglycaemia, adequate oxygenation (FiO₂ 0.8)",
"<b>Post-operative:</b> clean dressing technique, blood glucose < 180 mg/dL, remove drains early, wound review at 48–72 hours",
"Minimally invasive / laparoscopic surgery reduces SSI rates",
"Avoid shaving (use clippers if necessary); surgical team hand hygiene",
]
for p in prev:
story.append(bullet(p))
story.append(section("E. MANAGEMENT (2 marks)"))
mgmt = [
"Open and drain wound (superficial SSI) – most important step",
"Wound swab for culture and sensitivity",
"Regular wound dressing with irrigation",
"Antibiotics: systemic only for deep SSI, spreading cellulitis, immunocompromised, or systemic sepsis",
"Negative pressure wound therapy (NPWT / VAC) for large wounds",
"Secondary closure or skin grafting once clean granulation tissue forms",
"Deep / organ-space SSI: image-guided or surgical drainage, IV antibiotics",
]
for m in mgmt:
story.append(bullet(m))
story.append(note("Reference: Bailey & Love's Short Practice of Surgery, 28th Ed., Chapter 5"))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────────
# Q4 – SHOCK
# ─────────────────────────────────────────────────────────────────────────────
story.append(q_banner(4,
"Definition of Shock | Types | Pathophysiology & Management of Septic Shock",
"1+2+3+4 = 10 Marks"))
story.append(sp(6))
story.append(section("A. DEFINITION OF SHOCK (1 mark)"))
story.append(body(
"Shock is a <b>life-threatening generalised form of acute circulatory failure</b> associated with "
"inadequate oxygen utilisation by the cells, resulting in cellular dysfunction and, if prolonged, "
"organ failure and death. (Singer et al., Intensive Care Med 2016)"
))
story.append(sp(4))
story.append(section("B. TYPES OF SHOCK (2 marks)"))
shock_data = [
["Type", "Mechanism", "CO", "SVR", "Examples"],
["Hypovolaemic", "↓ Preload due to volume loss", "↓", "↑", "Haemorrhage, burns, dehydration"],
["Cardiogenic", "↓ Pump function", "↓", "↑", "MI, arrhythmia, cardiac tamponade"],
["Distributive – Septic", "↓ SVR → maldistribution", "↑ (early)", "↓", "Gram-neg/pos sepsis"],
["Distributive – Anaphylactic", "Histamine → vasodilation", "↑", "↓", "Drug/bee sting allergy"],
["Distributive – Neurogenic", "Loss of sympathetic tone", "↑", "↓", "Spinal cord injury"],
["Obstructive", "↑ Afterload / obstruction", "↓", "↑", "PE, tension pneumothorax, cardiac tamponade"],
]
story.append(box_table(shock_data, [2.5*cm, 3.5*cm, 1*cm, 1*cm, CW - 8*cm]))
story.append(sp(6))
story.append(section("C. PATHOPHYSIOLOGY OF SEPTIC SHOCK (3 marks)"))
story.append(ShockDiagram())
story.append(sp(4))
patho_text = [
"Source: <b>Gram-negative bacteria</b> release LPS (lipopolysaccharide); Gram-positives release LTA/peptidoglycan",
"These activate <b>macrophages via TLR4</b> → massive cytokine release (TNF-α, IL-1, IL-6, IL-8)",
"Cytokines cause: (a) widespread vasodilation (↓SVR), (b) ↑ vascular permeability, (c) myocardial depression",
"Early (warm shock): ↑CO, ↓SVR, warm extremities, bounding pulse – often missed",
"Late (cold shock): ↓CO, ↑SVR, multi-organ dysfunction",
"Endothelial damage → DIC (disseminated intravascular coagulation)",
"Mitochondrial dysfunction → impaired cellular oxygen utilisation → lactic acidosis",
"MODS (multi-organ dysfunction syndrome) → death if untreated",
]
for p in patho_text:
story.append(bullet(p))
story.append(section("D. MANAGEMENT OF SEPTIC SHOCK (4 marks)"))
story.append(body("<b>Surviving Sepsis Campaign 'Hour-1 Bundle' (2018):</b>"))
bundle = [
"Measure lactate – resuscitate to normalise (target lactate < 2 mmol/L)",
"Blood cultures × 2 sets before antibiotics",
"Broad-spectrum IV antibiotics within 1 hour of recognition",
"IV crystalloid 30 mL/kg if hypotensive / lactate ≥ 4 mmol/L",
"Vasopressors (Noradrenaline = first line) if MAP < 65 mmHg",
]
for b in bundle:
story.append(bullet(b))
story.append(body("<b>Additional management:</b>"))
additional = [
"Source control – drain abscess, remove infected device, surgical debridement",
"Oxygen therapy / mechanical ventilation if SpO₂ < 92%",
"Corticosteroids – Hydrocortisone 200 mg/day IV if refractory to vasopressors",
"Tight glycaemic control (< 180 mg/dL)",
"DVT prophylaxis (LMWH) + stress ulcer prophylaxis (PPI)",
"Renal replacement therapy if AKI develops",
"Monitor: urine output > 0.5 mL/kg/hr, CVP 8–12 mmHg, MAP ≥ 65 mmHg",
]
for a in additional:
story.append(bullet(a))
story.append(note("Reference: Schwartz's Principles of Surgery, 11th Ed.; Surviving Sepsis Campaign 2021 Guidelines"))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────────
# Q5 – BURN CASE (MEDICOLEGAL)
# ─────────────────────────────────────────────────────────────────────────────
story.append(q_banner(5,
"25-year-old Woman with 25% Burn – Medicolegal Case",
"2+2+6 = 10 Marks"))
story.append(sp(6))
story.append(section("a. WILL YOU INFORM THE POLICE? (2 marks)"))
story.append(body(
"<b>YES. This is a Medico-Legal Case (MLC) and MUST be reported to police.</b>"
))
police_reasons = [
"Under Section 39 CrPC (now BNSS), every doctor is legally obligated to inform police of injuries caused by fire, assault, or suspicious circumstances",
"Patient's consent is <b>NOT required</b> to report an MLC – the duty to report overrides personal wishes",
"This case involves <b>domestic violence / dowry harassment</b>, which is punishable under IPC Sections 498A, 304B (Dowry Death attempt), Section 326 (grievous hurt)",
"Protection of Women from Domestic Violence Act (PWDVA 2005) mandates protection",
"Failure to report = professional misconduct + potential criminal liability for the doctor",
"The patient's claim that she 'set herself on fire' must be evaluated critically – history from husband's family, wound pattern, and clinical features may suggest otherwise",
]
for r in police_reasons:
story.append(bullet(r))
story.append(section("b. DELAY TREATMENT OR START TREATMENT? (2 marks)"))
story.append(body(
"<b>Start treatment IMMEDIATELY – DO NOT delay for police.</b>"
))
treatment_first = [
"Medical emergency takes absolute priority over medicolegal formalities",
"Police can be informed simultaneously while starting treatment",
"Document everything meticulously in MLC register (time, history, injury description, who accompanied patient)",
"Take photographs before first dressing if possible (medicolegal evidence)",
"Preserve clothes as forensic evidence",
]
for t in treatment_first:
story.append(bullet(t))
story.append(section("c. HOW WILL YOU MANAGE THIS CASE? (6 marks)"))
story.append(BurnRuleNines())
story.append(sp(4))
story.append(body("<b>IMMEDIATE RESUSCITATION (ABCs):</b>"))
abc = [
"<b>Airway:</b> assess for inhalation injury (singed nasal hair, hoarse voice, carbonaceous sputum) → early intubation if suspected",
"<b>Breathing:</b> 100% O₂ via face mask",
"<b>Circulation:</b> 2 large-bore IV cannulas, draw bloods (CBC, electrolytes, RFT, LFT, coagulation, blood group), ECG monitoring",
]
for a in abc:
story.append(bullet(a))
story.append(body("<b>FLUID RESUSCITATION – Parkland Formula:</b>"))
story.append(body(
"Total fluid (in 24 hours) = <b>4 mL × weight (kg) × %TBSA burn</b><br/>"
"For 25% burns in a ~55 kg woman: 4 × 55 × 25 = <b>5500 mL Ringer's Lactate</b><br/>"
"→ Give first <b>half (2750 mL) in the first 8 hours</b> (from time of injury)<br/>"
"→ Give second <b>half (2750 mL) over next 16 hours</b><br/>"
"Monitor urine output: target <b>0.5–1 mL/kg/hr</b>"
))
story.append(sp(4))
story.append(body("<b>WOUND MANAGEMENT:</b>"))
wound_mgmt = [
"Cool running water for 20 min (only if < 3 hours from injury) – NOT ice",
"Remove jewellery and loose clothing",
"Wound assessment: depth (superficial/partial/full thickness), extent (Rule of Nines)",
"Silver sulphadiazine dressing or modern silver-containing dressings",
"Tetanus prophylaxis (toxoid ± immunoglobulin based on history)",
"Analgesia – IV morphine titrated to pain",
"Nutritional support – high protein, high calorie (nasogastric feeds early in >20% burns)",
]
for w in wound_mgmt:
story.append(bullet(w))
story.append(body("<b>MEDICOLEGAL DOCUMENTATION:</b>"))
mlc = [
"Register as MLC – note time of registration, name, age, address",
"Record history in the patient's own words (verbatim) in inverted commas",
"Describe wounds: size, shape, colour, margins, presence of soot/kerosene smell",
"Inform police: written intimation, duty officer to be informed",
"Counselling and referral to social worker / psychiatric support",
"Legal protection under PWDVA 2005 – contact protection officer",
]
for m in mlc:
story.append(bullet(m))
story.append(note("Reference: Schwartz's Principles of Surgery 11th Ed.; Current Surgical Therapy 14th Ed."))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────────
# Q6 – SHORT NOTES
# ─────────────────────────────────────────────────────────────────────────────
story.append(q_banner(6, "Short Notes (any 4 × 5 marks each)", "4×5 = 20 Marks"))
story.append(sp(6))
# 6a – Refeeding Syndrome
story.append(section("a. REFEEDING SYNDROME (5 marks)"))
story.append(body(
"<b>Definition:</b> A life-threatening metabolic complication occurring when nutrition (enteral or parenteral) "
"is reintroduced to a severely malnourished or starved patient."
))
story.append(body("<b>Pathophysiology:</b>"))
story.append(body(
"During starvation → body uses fat and protein → intracellular electrolyte depletion (phosphate, potassium, magnesium). "
"On refeeding → carbohydrates → ↑Insulin → drives glucose + electrolytes into cells → "
"<b>acute hypophosphataemia</b> (most characteristic) + hypokalaemia + hypomagnesaemia."
))
story.append(body("<b>Risk factors (NICE criteria):</b>"))
risk = [
"BMI < 16 kg/m² OR unintentional weight loss > 15% in 3–6 months OR no intake > 10 days OR low electrolytes pre-feeding",
"Two or more: BMI < 18.5, weight loss > 10% in 3–6 months, intake < 5 days, alcohol abuse",
]
for r in risk:
story.append(bullet(r))
story.append(body("<b>Clinical features:</b> Arrhythmias, muscle weakness (respiratory failure, rhabdomyolysis), seizures, cardiac failure, oedema, altered consciousness."))
story.append(body("<b>Management:</b>"))
re_mgmt = [
"Start feeding at 10 kcal/kg/day – increase slowly over 4–7 days",
"Correct phosphate, potassium, magnesium BEFORE feeding",
"IV/oral thiamine 200–300 mg/day BEFORE and during refeeding (Wernicke's prevention)",
"Restrict sodium and fluid; close monitoring of electrolytes daily",
"Multivitamins and trace elements",
]
for r in re_mgmt:
story.append(bullet(r))
story.append(hr())
# 6b – TPN
story.append(section("b. TOTAL PARENTERAL NUTRITION (TPN) (5 marks)"))
story.append(body(
"<b>Definition:</b> Intravenous delivery of all nutritional requirements (calories, protein, fat, electrolytes, vitamins, trace elements) bypassing the GI tract."
))
story.append(body("<b>Indications:</b>"))
tpn_ind = [
"Short bowel syndrome", "Intestinal obstruction", "Severe IBD with bowel rest",
"Enterocutaneous fistula", "Prolonged ileus", "Severe pancreatitis (if enteral route failed)",
"Pre-operative nutritional support in severely malnourished patients",
]
for t in tpn_ind:
story.append(bullet(t))
story.append(body("<b>Components of TPN solution:</b>"))
story.append(body(
"• Carbohydrates: 50–70% of calories (glucose 25–35% solution)<br/>"
"• Lipids: 20–30% of calories (prevents essential fatty acid deficiency)<br/>"
"• Amino acids: 1.2–2 g/kg/day (nitrogen source)<br/>"
"• Electrolytes: Na⁺, K⁺, Cl⁻, phosphate, magnesium, calcium<br/>"
"• Vitamins: B-complex, A, C, D, E, K<br/>"
"• Trace elements: Zinc, Copper, Selenium, Manganese"
))
story.append(body("<b>Complications of TPN:</b>"))
tpn_comp = [
"<b>Catheter-related:</b> Infection (CLABSI), pneumothorax, haemothorax, air embolism, thrombosis",
"<b>Metabolic:</b> Hyperglycaemia (most common), hypoglycaemia (on stopping), hypertriglyceridaemia, electrolyte disturbances",
"<b>Hepatic:</b> Fatty liver (steatosis) → cholestasis → IFALD (intestinal failure-associated liver disease)",
"<b>GI:</b> Intestinal atrophy (villous atrophy from disuse), bacterial translocation",
"<b>Refeeding syndrome</b> on initiation",
]
for t in tpn_comp:
story.append(bullet(t))
story.append(hr())
# 6c – Abdominal Compartment Syndrome
story.append(section("c. ABDOMINAL COMPARTMENT SYNDROME (ACS) (5 marks)"))
story.append(body(
"<b>Definition:</b> Sustained intra-abdominal pressure (IAP) > 20 mmHg associated with new organ dysfunction/failure. "
"Intra-abdominal hypertension (IAH) = IAP > 12 mmHg."
))
story.append(body("<b>Normal IAP:</b> 0–5 mmHg (critically ill: up to 12 mmHg acceptable)."))
story.append(body("<b>Causes:</b>"))
acs_causes = [
"Massive fluid resuscitation (most common – post-trauma, burns)",
"Haemoperitoneum", "Ileus / bowel obstruction", "Pancreatitis", "Retroperitoneal haematoma",
"Tight abdominal closure after bowel oedema",
]
for c in acs_causes:
story.append(bullet(c))
story.append(body("<b>Pathophysiology:</b>"))
story.append(body(
"↑IAP → ↓ venous return (IVC compression) → ↓CO → renal vein compression → AKI → "
"diaphragm elevation → ↑ airway pressure → respiratory failure → hepatic/gut ischaemia → MODS."
))
story.append(body("<b>Measurement:</b> Indirect – intravesical (bladder) pressure via Foley catheter using manometer. Measured at end-expiration in supine position."))
story.append(body("<b>Management:</b>"))
acs_mgmt = [
"Medical: NGT decompression, prokinetics, body positioning (30° head elevation), sedation/analgesia, diuretics/renal replacement, percutaneous catheter drainage",
"Surgical: Decompressive <b>laparotomy</b> (midline incision) = gold standard for ACS unresponsive to medical management",
"Temporary abdominal closure (TAC): Bogotá bag, Vacuum-Assisted Closure (VAC), Wittmann patch",
"Definitive closure once oedema resolves (serial washouts)",
]
for a in acs_mgmt:
story.append(bullet(a))
story.append(hr())
# 6d – Buerger's Disease
story.append(section("d. BUERGER'S DISEASE (Thromboangiitis Obliterans) (5 marks)"))
story.append(body(
"<b>Definition:</b> A progressive, non-atherosclerotic, segmental inflammatory disease affecting "
"small and medium arteries, veins, and nerves of upper and lower extremities. "
"First described by <b>Leo Buerger in 1908</b>."
))
buerger_data = [
["Feature", "Details"],
["Aetiology", "Unknown; TOBACCO use is essential for diagnosis and progression"],
["Demographics", "Young male smokers, age 20–40 years; more common in Asia"],
["Pathology", "Segmental thrombosis with dense PMN infiltration, microabscesses, giant cells; end-stage: organised thrombus + vessel fibrosis"],
["Presentation", "Foot/hand claudication → rest pain → ischaemic ulcers on digits; migratory superficial phlebitis (16%)"],
["Angiography", "'Skip' lesions, corkscrew collaterals, disease distal to popliteal/brachial artery"],
]
story.append(box_table(buerger_data, [3*cm, CW - 3*cm]))
story.append(body("<b>Management:</b>"))
buerger_mgmt = [
"<b>Strict smoking cessation</b> – most important and only disease-modifying treatment",
"Calcium channel blockers (nifedipine) for vasospasm",
"Prostacyclin analogues (iloprost) for critical ischaemia",
"Antiplatelet therapy (aspirin/clopidogrel)",
"Wound care and infection control for ulcers",
"Sympathectomy – lumbar for lower limb ischaemia",
"Spinal cord stimulation for pain",
"Amputation – if gangrene develops (31% limb loss in 15 years if smoking continues)",
"Bypass surgery has limited role (no distal target vessel usually available)",
]
for b in buerger_mgmt:
story.append(bullet(b))
story.append(hr())
# 6e – Phylloides Tumour
story.append(section("e. PHYLLOIDES TUMOUR (5 marks)"))
story.append(body(
"<b>Definition:</b> A rare fibroepithelial breast tumour (1–2% of all breast tumours) with stromal hypercellularity. "
"Name derived from Greek 'phullon' = leaf (leaf-like architecture on histology). "
"Also spelled Phyllodes."
))
phyllo_data = [
["Feature", "Details"],
["Age", "35–55 years (older than fibroadenoma)"],
["Presentation","Large, rapidly growing, painless breast lump; can be huge (>10 cm); "
"overlying skin may be stretched/shiny; dilated veins"],
["Histology", "Biphasic: epithelial lined clefts + hypercellular stroma; leaf-like projections"],
["Classification","Benign (50%), Borderline (25%), Malignant (25%) – WHO 2019 classification based on stromal cellularity, atypia, mitoses, margins"],
["Investigations","Ultrasound (heterogeneous, lobulated), Mammography, Core needle biopsy (FNA insufficient – stromal component needed)"],
["Metastases", "Haematogenous (lungs most common); lymph node metastases rare (even in malignant variant)"],
]
story.append(box_table(phyllo_data, [3*cm, CW - 3*cm]))
story.append(body("<b>Management:</b>"))
phyllo_mgmt = [
"Wide local excision with <b>1 cm clear margins</b> – treatment of choice for all grades",
"Simple mastectomy if tumour is large relative to breast size or margins cannot be achieved",
"Axillary dissection is NOT routinely required (LN metastases rare)",
"Radiotherapy – considered for malignant phyllodes with close/positive margins",
"Chemotherapy – limited role; used for metastatic malignant phyllodes",
"Regular follow-up: recurrence rate ~10–25% (local recurrence most common)",
"Prognosis: Benign excellent; Malignant 60–80% 5-year survival",
]
for p in phyllo_mgmt:
story.append(bullet(p))
story.append(note("References: Bailey & Love's 28th Ed.; Schwartz's Principles of Surgery 11th Ed.; Current Surgical Therapy 14th Ed."))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────────
# Q7 – THYROID CARCINOMA
# ─────────────────────────────────────────────────────────────────────────────
story.append(q_banner(7,
"Classification of Thyroid Carcinoma | Clinical Features, Histopathology & Management of Papillary Thyroid Carcinoma",
"2+1+2+5 = 10 Marks"))
story.append(sp(6))
story.append(section("A. CLASSIFICATION OF THYROID CARCINOMA (2 marks)"))
story.append(ThyroidClassDiagram())
story.append(sp(4))
thyroid_class_data = [
["Type", "Frequency", "Cell of Origin", "Key Features"],
["Papillary Carcinoma (PTC)", "80%", "Follicular cell", "Most common; lymph node mets; best prognosis; RET/PTC rearrangement; nuclear 'Orphan Annie eye'"],
["Follicular Carcinoma", "10%", "Follicular cell", "Capsular/vascular invasion required; blood-borne mets (lung, bone); Hürthle cell variant"],
["Medullary Carcinoma (MTC)", "5–8%", "Parafollicular C-cell", "Calcitonin ↑↑; amyloid deposits; MEN 2A & 2B; worst prognosis among differentiated"],
["Anaplastic (Undifferentiated)","<1%", "Follicular cell", "Rapidly fatal; rigid hard neck mass; mean survival 3–6 months; no cure"],
["Lymphoma", "<1%", "B lymphocytes", "Background Hashimoto's; responds to chemoradiation"],
]
story.append(box_table(thyroid_class_data, [3*cm, 1.5*cm, 2.5*cm, CW - 7*cm]))
story.append(sp(6))
story.append(section("B. PAPILLARY THYROID CARCINOMA (PTC)"))
story.append(section(" i. Clinical Features (1 mark)"))
ptc_clinical = [
"Most commonly presents as a <b>painless solitary thyroid nodule</b>",
"May present as <b>cervical lymphadenopathy</b> (metastatic LN) – even before primary is palpable ('lateral aberrant thyroid')",
"Palpable hard nodule in thyroid lobe; may be fixed to surrounding structures in advanced disease",
"Dysphagia, dyspnoea, hoarseness (RLN involvement) in locally advanced disease",
"Distant metastases (lung, bone) – uncommon but may be initial presentation",
"Associated with: <b>previous neck irradiation</b>, Hashimoto's thyroiditis, familial adenomatous polyposis (FAP)",
"PTC microcarcinoma (< 10 mm) – often incidental finding on imaging or surgery",
]
for p in ptc_clinical:
story.append(bullet(p))
story.append(section(" ii. Histopathology (2 marks)"))
story.append(body("<b>Gross:</b>"))
story.append(bullet("Irregular, non-encapsulated, infiltrating tumour"))
story.append(bullet("Cut surface: papillary projections, may show calcification (psammoma bodies)"))
story.append(body("<b>Microscopy (characteristic features):</b>"))
histo = [
"<b>'Orphan Annie eye' nuclei</b> – empty-appearing ('ground glass') nuclei with central clearing",
"<b>Nuclear grooves</b> and nuclear pseudo-inclusions (invaginations of cytoplasm)",
"<b>Papillary architecture</b> – fibrovascular cores lined by tumour cells",
"<b>Psammoma bodies</b> – concentric calcified structures (50% of PTC); pathognomonic when found in neck lymph nodes",
"Multifocality common (up to 85%)",
"Molecular: <b>BRAF V600E mutation</b> (most common, 60%), RET/PTC rearrangements, RAS mutations",
]
for h in histo:
story.append(bullet(h))
story.append(section(" iii. Management (5 marks)"))
story.append(body("<b>INVESTIGATION:</b>"))
invest = [
"TFTs (TSH, T3, T4) – usually euthyroid",
"Ultrasound thyroid – characteristics of malignancy: hypoechoic, irregular margins, microcalcifications, taller-than-wide",
"FNAC (Fine Needle Aspiration Cytology) – Bethesda classification",
"CT neck/chest for local invasion and pulmonary metastases",
"Laryngoscopy to assess vocal cord mobility (RLN)",
]
for i in invest:
story.append(bullet(i))
story.append(body("<b>SURGICAL TREATMENT:</b>"))
surg = [
"<b>Total thyroidectomy</b> – preferred for tumours > 1 cm, bilateral disease, positive LN, prior neck irradiation",
"<b>Lobectomy + isthmusectomy</b> – acceptable for low-risk, unilateral PTC microcarcinoma < 1 cm",
"<b>Central neck dissection</b> (Level VI) – if clinically positive nodes",
"Lateral neck dissection (Levels II–V) – for lateral cervical LN involvement",
"Protect <b>RLN and parathyroids</b> (or autotransplant); risk of hypoparathyroidism",
]
for s in surg:
story.append(bullet(s))
story.append(body("<b>POST-OPERATIVE MANAGEMENT:</b>"))
post_op = [
"<b>Radioiodine (I-131) ablation</b> – after total thyroidectomy; ablates residual thyroid tissue and micrometastases; indicated for intermediate/high-risk PTC",
"<b>TSH suppression therapy</b> – LT4 (thyroxine) to keep TSH < 0.1 mU/L (reduces stimulation of any residual tumour)",
"<b>Thyroglobulin</b> monitoring – tumour marker for recurrence (should be undetectable after total thyroidectomy + RAI)",
"Neck ultrasound 6–12 monthly for first 2 years",
"Whole body scan if Tg rises",
]
for p in post_op:
story.append(bullet(p))
story.append(body("<b>PROGNOSIS:</b>"))
story.append(body(
"Excellent – 10-year survival > 95% for low-risk PTC. Younger age, small tumour, no extrathyroid extension = favourable. "
"Staging: AJCC 8th Ed. – all patients < 55 years are Stage I or II regardless of nodal involvement."
))
story.append(note("Reference: Bailey & Love's Short Practice of Surgery, 28th Ed.; Robbins Basic Pathology 10th Ed.; Scott-Brown's Otorhinolaryngology"))
# ─────────────────────────────────────────────────────────────────────────────
# BUILD
# ─────────────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF generated: {OUTPUT}")
cd /tmp/workspace/surgery-paper && python generate_pdf.py 2>&1
~/surgery-paper/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/surgery-paper/generate_pdf.py'
"c.polygon(" in ~/surgery-paper
~/surgery-paper/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/surgery-paper/generate_pdf.py'
cd /tmp/workspace/surgery-paper && python generate_pdf.py 2>&1
ls -lh /tmp/workspace/surgery-paper/Surgery_Paper_I_Answers.pdf