Amputation Long case with examination Definition And viva
"Properly planned amputation is a form of reconstruction which can return a patient to the community fully mobile in a relatively short period of time."
- Pye's Surgical Handicraft, 22nd Ed.
| Indication | % |
|---|---|
| Complications of diabetes mellitus | 60-80% |
| Non-diabetic infection with ischaemia | 15-25% |
| Ischaemia without infection | 5-10% |
| Chronic osteomyelitis | <5% |
| Trauma, malignancy, frostbite | <5% |

| Complication | Details |
|---|---|
| Haemorrhage | Primary (operative), reactionary (24-48 h), secondary (infection, >10 days) |
| Wound infection | Common; risk higher in ischaemic patients |
| Wound dehiscence | Failure of skin flap viability |
| DVT/PE | Major risk; DVT prophylaxis essential |
| Phantom limb sensation | Almost universal - awareness of absent limb |
| Complication | Details |
|---|---|
| Phantom limb pain | Distinct from sensation; burning, cramping; treated with gabapentin, amitriptyline, mirror therapy |
| Neuroma | Painful nodule in scar from nerve end regeneration |
| Bony spur | Periosteal new bone formation causing pain in prosthesis |
| Fixed flexion deformity | Hip flexion (AKA), knee flexion (BKA); prevents prosthetic fitting |
| Stump ulceration | From prosthetic socket pressure |
| Skin problems | Folliculitis, eczema, verrucous hyperplasia |
| Re-amputation | ~30-50% within 5 years for vascular causes |
| Osteomyelitis | Rare; presents with sinus |
| Psychological issues | Depression, PTSD, body image |
| Level | Energy increase vs normal walking |
|---|---|
| Transmetatarsal | Minimal |
| Syme | ~10% increase |
| Below-knee (BKA) | 30-60% increase |
| Above-knee (AKA) | 60-100% increase |
| Bilateral AKA | Rarely ambulatory |
| BKA | AKA | |
|---|---|---|
| Level | 14 cm below knee | 25-30 cm below greater trochanter |
| Technique | Burgess long posterior flap | Sagittal flap / equal anterior-posterior |
| Weight-bearing surface | Patellar tendon + tibial flares | Ischial tuberosity |
| Ambulation rate (vascular) | ~75% | ~40% |
| Energy cost | +30-60% | +60-100% |
| Knee | Preserved | Lost |
Create a detailed PDF guide for quick exam revision on amputation
ls -la /home/daytona/workspace/ 2>/dev/null && mkdir -p /home/daytona/workspace/amputation-guide
~/amputation-guide/generate_pdf.py
#!/usr/bin/env python3
"""
Amputation - Surgical Long Case & Exam Revision Guide PDF Generator
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, HRFlowable, KeepTogether
)
from reportlab.platypus.flowables import Flowable
from reportlab.lib.colors import HexColor
import os
# ── Color Palette ─────────────────────────────────────────────────────────────
DARK_NAVY = HexColor('#0D1B2A')
NAVY = HexColor('#1B3A5C')
TEAL = HexColor('#0E7C7B')
TEAL_LIGHT = HexColor('#E6F4F1')
RED = HexColor('#C0392B')
RED_LIGHT = HexColor('#FDEDEC')
AMBER = HexColor('#E67E22')
AMBER_LIGHT = HexColor('#FEF9E7')
GREEN = HexColor('#1A7A4A')
GREEN_LIGHT = HexColor('#E9F7EF')
PURPLE = HexColor('#6C3483')
PURPLE_LIGHT = HexColor('#F5EEF8')
GREY_DARK = HexColor('#2C3E50')
GREY_MID = HexColor('#7F8C8D')
GREY_LIGHT = HexColor('#F2F3F4')
WHITE = HexColor('#FFFFFF')
ORANGE = HexColor('#D35400')
OUTPUT_PATH = '/home/daytona/workspace/amputation-guide/Amputation_Exam_Revision_Guide.pdf'
# ── Custom Flowables ───────────────────────────────────────────────────────────
class ColorBar(Flowable):
def __init__(self, width, height, color):
super().__init__()
self.width = width
self.height = height
self.color = color
def draw(self):
self.canv.setFillColor(self.color)
self.canv.rect(0, 0, self.width, self.height, fill=1, stroke=0)
class SectionDivider(Flowable):
def __init__(self, width, left_color, right_color, height=4):
super().__init__()
self.width = width
self.left_color = left_color
self.right_color = right_color
self.height = height
def draw(self):
self.canv.setFillColor(self.left_color)
self.canv.rect(0, 0, self.width * 0.6, self.height, fill=1, stroke=0)
self.canv.setFillColor(self.right_color)
self.canv.rect(self.width * 0.6, 0, self.width * 0.4, self.height, fill=1, stroke=0)
# ── Style Definitions ──────────────────────────────────────────────────────────
def build_styles():
base = getSampleStyleSheet()
styles = {
'cover_title': ParagraphStyle('cover_title',
fontName='Helvetica-Bold', fontSize=30,
textColor=WHITE, leading=36,
spaceAfter=8, alignment=TA_CENTER),
'cover_subtitle': ParagraphStyle('cover_subtitle',
fontName='Helvetica', fontSize=14,
textColor=HexColor('#BDC3C7'), leading=18,
spaceAfter=6, alignment=TA_CENTER),
'cover_tag': ParagraphStyle('cover_tag',
fontName='Helvetica-Bold', fontSize=11,
textColor=TEAL, leading=14,
spaceAfter=4, alignment=TA_CENTER),
'section_header': ParagraphStyle('section_header',
fontName='Helvetica-Bold', fontSize=15,
textColor=WHITE, leading=20,
spaceBefore=2, spaceAfter=2,
leftIndent=8),
'subsection': ParagraphStyle('subsection',
fontName='Helvetica-Bold', fontSize=12,
textColor=NAVY, leading=16,
spaceBefore=8, spaceAfter=4),
'body': ParagraphStyle('body',
fontName='Helvetica', fontSize=9.5,
textColor=GREY_DARK, leading=14,
spaceAfter=4, alignment=TA_JUSTIFY),
'body_bold': ParagraphStyle('body_bold',
fontName='Helvetica-Bold', fontSize=9.5,
textColor=GREY_DARK, leading=14, spaceAfter=3),
'bullet': ParagraphStyle('bullet',
fontName='Helvetica', fontSize=9.5,
textColor=GREY_DARK, leading=13,
leftIndent=14, firstLineIndent=-10,
spaceAfter=2),
'bullet2': ParagraphStyle('bullet2',
fontName='Helvetica', fontSize=9,
textColor=GREY_DARK, leading=12,
leftIndent=26, firstLineIndent=-10,
spaceAfter=2),
'key_point': ParagraphStyle('key_point',
fontName='Helvetica-Bold', fontSize=10,
textColor=NAVY, leading=14,
leftIndent=10, spaceAfter=2),
'callout_text': ParagraphStyle('callout_text',
fontName='Helvetica', fontSize=9.5,
textColor=GREY_DARK, leading=14,
leftIndent=6),
'callout_title': ParagraphStyle('callout_title',
fontName='Helvetica-Bold', fontSize=10,
textColor=NAVY, leading=14,
leftIndent=6, spaceAfter=2),
'viva_q': ParagraphStyle('viva_q',
fontName='Helvetica-Bold', fontSize=10,
textColor=NAVY, leading=14,
leftIndent=4, spaceAfter=2),
'viva_a': ParagraphStyle('viva_a',
fontName='Helvetica', fontSize=9.5,
textColor=GREY_DARK, leading=13,
leftIndent=12, spaceAfter=6, alignment=TA_JUSTIFY),
'table_header': ParagraphStyle('table_header',
fontName='Helvetica-Bold', fontSize=9,
textColor=WHITE, leading=12, alignment=TA_CENTER),
'table_cell': ParagraphStyle('table_cell',
fontName='Helvetica', fontSize=9,
textColor=GREY_DARK, leading=12),
'table_cell_bold': ParagraphStyle('table_cell_bold',
fontName='Helvetica-Bold', fontSize=9,
textColor=GREY_DARK, leading=12),
'footer_text': ParagraphStyle('footer_text',
fontName='Helvetica', fontSize=8,
textColor=GREY_MID, leading=10, alignment=TA_CENTER),
'page_num': ParagraphStyle('page_num',
fontName='Helvetica-Bold', fontSize=9,
textColor=TEAL, leading=11, alignment=TA_CENTER),
'small_italic': ParagraphStyle('small_italic',
fontName='Helvetica-Oblique', fontSize=8.5,
textColor=GREY_MID, leading=11, spaceAfter=3),
'alert_text': ParagraphStyle('alert_text',
fontName='Helvetica-Bold', fontSize=10,
textColor=WHITE, leading=14,
leftIndent=8),
'mnemonic': ParagraphStyle('mnemonic',
fontName='Helvetica-Bold', fontSize=13,
textColor=NAVY, leading=20, alignment=TA_CENTER,
spaceAfter=2),
}
return styles
# ── Helper Functions ───────────────────────────────────────────────────────────
def section_block(title, color, width, styles):
"""Returns a colored section header block."""
return [
Spacer(1, 10),
Table(
[[Paragraph(f" {title}", styles['section_header'])]],
colWidths=[width],
style=TableStyle([
('BACKGROUND', (0,0), (-1,-1), color),
('ROWBACKGROUNDS', (0,0), (-1,-1), [color]),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('LEFTPADDING', (0,0), (-1,-1), 6),
('RIGHTPADDING', (0,0), (-1,-1), 6),
('ROUNDEDCORNERS', [4,4,4,4]),
])
),
Spacer(1, 6),
]
def callout_box(title, content_paras, color_bg, color_border, width, styles):
"""A colored callout/info box."""
inner = [[title_para] for title_para in ([Paragraph(title, styles['callout_title'])] if title else [])]
inner += [[p] for p in content_paras]
# Flatten as single cell with stacked paragraphs
all_content = []
if title:
all_content.append(Paragraph(title, styles['callout_title']))
all_content.extend(content_paras)
t = Table([[all_content]], colWidths=[width])
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), color_bg),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('BOX', (0,0), (-1,-1), 2, color_border),
('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
return t
def two_col_table(data, col_widths, header_color, styles, header_row=True):
"""Styled two-column table."""
table_data = []
for i, row in enumerate(data):
if i == 0 and header_row:
table_data.append([Paragraph(str(c), styles['table_header']) for c in row])
else:
table_data.append([Paragraph(str(c), styles['table_cell']) for c in row])
ts = TableStyle([
('BACKGROUND', (0,0), (-1,0), header_color),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, GREY_LIGHT]),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 8),
('RIGHTPADDING', (0,0), (-1,-1), 8),
('GRID', (0,0), (-1,-1), 0.5, HexColor('#D5D8DC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
])
t = Table(table_data, colWidths=col_widths)
t.setStyle(ts)
return t
# ── Page Template ──────────────────────────────────────────────────────────────
def on_page(canvas, doc, styles):
canvas.saveState()
W, H = A4
# Top bar
canvas.setFillColor(DARK_NAVY)
canvas.rect(0, H - 22, W, 22, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, H - 26, W, 4, fill=1, stroke=0)
# Header text
canvas.setFont('Helvetica-Bold', 8)
canvas.setFillColor(WHITE)
canvas.drawString(20, H - 15, 'AMPUTATION')
canvas.setFont('Helvetica', 8)
canvas.setFillColor(HexColor('#95A5A6'))
canvas.drawRightString(W - 20, H - 15, 'Surgical Long Case & Exam Revision Guide')
# Bottom bar
canvas.setFillColor(DARK_NAVY)
canvas.rect(0, 0, W, 20, fill=1, stroke=0)
canvas.setFillColor(TEAL)
canvas.rect(0, 20, W, 2, fill=1, stroke=0)
# Page number
canvas.setFont('Helvetica-Bold', 8)
canvas.setFillColor(WHITE)
canvas.drawCentredString(W / 2, 7, f'Page {doc.page}')
canvas.setFont('Helvetica', 7)
canvas.setFillColor(HexColor('#7F8C8D'))
canvas.drawString(20, 7, 'Sources: Bailey & Love 28e | Pye\'s Surgical Handicraft 22e | Mulholland & Greenfield 7e')
canvas.restoreState()
# ── COVER PAGE ─────────────────────────────────────────────────────────────────
def build_cover(W, H, styles):
"""Build cover page using canvas drawing - returned as a custom flowable."""
# We'll build it as a full-page table
cover_content = []
# Spacer for top bar
cover_content.append(Spacer(1, 30))
# Decorative top accent
cover_content.append(ColorBar(W - 80, 6, TEAL))
cover_content.append(Spacer(1, 20))
# Main Title
title_style = ParagraphStyle('ct', fontName='Helvetica-Bold', fontSize=34,
textColor=DARK_NAVY, leading=40, alignment=TA_CENTER, spaceAfter=6)
cover_content.append(Paragraph('AMPUTATION', title_style))
sub_style = ParagraphStyle('cs', fontName='Helvetica', fontSize=16,
textColor=TEAL, leading=20, alignment=TA_CENTER, spaceAfter=20)
cover_content.append(Paragraph('Surgical Long Case & Exam Revision Guide', sub_style))
cover_content.append(ColorBar(W - 80, 4, NAVY))
cover_content.append(Spacer(1, 25))
# Three badge-like items in a row
badge_data = [[
Paragraph('<b>DEFINITION</b><br/>Classic & Clinical', ParagraphStyle('b1', fontName='Helvetica-Bold',
fontSize=10, textColor=WHITE, leading=14, alignment=TA_CENTER)),
Paragraph('<b>EXAMINATION</b><br/>Step-by-step Guide', ParagraphStyle('b2', fontName='Helvetica-Bold',
fontSize=10, textColor=WHITE, leading=14, alignment=TA_CENTER)),
Paragraph('<b>VIVA Q&A</b><br/>14 Exam Questions', ParagraphStyle('b3', fontName='Helvetica-Bold',
fontSize=10, textColor=WHITE, leading=14, alignment=TA_CENTER)),
]]
badge_table = Table(badge_data, colWidths=[(W-80)/3]*3)
badge_table.setStyle(TableStyle([
('BACKGROUND', (0,0), (0,0), TEAL),
('BACKGROUND', (1,0), (1,0), NAVY),
('BACKGROUND', (2,0), (2,0), RED),
('TOPPADDING', (0,0), (-1,-1), 14),
('BOTTOMPADDING', (0,0), (-1,-1), 14),
('LEFTPADDING', (0,0), (-1,-1), 8),
('RIGHTPADDING', (0,0), (-1,-1), 8),
('INNERGRID', (0,0), (-1,-1), 2, WHITE),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
cover_content.append(badge_table)
cover_content.append(Spacer(1, 30))
# Key topics grid
topic_style = ParagraphStyle('ts', fontName='Helvetica', fontSize=9.5,
textColor=GREY_DARK, leading=13, alignment=TA_CENTER)
topics = [
['Definition & Historical Context', 'Indications - The 3 D\'s', 'Levels & Elective Sites'],
['History Taking Template', 'Stump Examination', 'Complications (Early & Late)'],
['Prosthetics & Rehabilitation', 'Energy Cost Tables', 'Viva Questions & Model Answers'],
]
topic_rows = [[Paragraph(cell, topic_style) for cell in row] for row in topics]
topic_table = Table(topic_rows, colWidths=[(W-80)/3]*3)
topic_table.setStyle(TableStyle([
('ROWBACKGROUNDS', (0,0), (-1,-1), [GREY_LIGHT, WHITE]),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('LEFTPADDING', (0,0), (-1,-1), 6),
('RIGHTPADDING', (0,0), (-1,-1), 6),
('GRID', (0,0), (-1,-1), 0.5, HexColor('#D5D8DC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
cover_content.append(Table(
[[Paragraph('CONTENTS AT A GLANCE', ParagraphStyle('cag', fontName='Helvetica-Bold',
fontSize=11, textColor=WHITE, leading=14, alignment=TA_CENTER))]],
colWidths=[W-80],
style=TableStyle([('BACKGROUND', (0,0), (-1,-1), NAVY),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8)])
))
cover_content.append(topic_table)
cover_content.append(Spacer(1, 35))
# Bottom tagline
tag_style = ParagraphStyle('tag', fontName='Helvetica-Oblique', fontSize=11,
textColor=GREY_MID, leading=16, alignment=TA_CENTER)
cover_content.append(Paragraph(
'"Properly planned amputation is a form of reconstruction which can return<br/>'
'a patient to the community fully mobile in a relatively short period of time."',
tag_style))
src_style = ParagraphStyle('src', fontName='Helvetica-Bold', fontSize=9,
textColor=TEAL, leading=12, alignment=TA_CENTER, spaceAfter=20)
cover_content.append(Paragraph('- Pye\'s Surgical Handicraft, 22nd Edition', src_style))
cover_content.append(Spacer(1, 20))
cover_content.append(ColorBar(W - 80, 3, TEAL))
return cover_content
# ── MAIN BUILD ─────────────────────────────────────────────────────────────────
def build_pdf():
doc = SimpleDocTemplate(
OUTPUT_PATH,
pagesize=A4,
leftMargin=2.5*cm, rightMargin=2.5*cm,
topMargin=2.2*cm, bottomMargin=1.8*cm,
title='Amputation - Surgical Long Case & Exam Revision Guide',
author='Orris Medical AI',
subject='Surgical Examination Revision'
)
W = A4[0] - 5*cm # usable width
styles = build_styles()
story = []
# ── COVER ──────────────────────────────────────────────────────────────────
for el in build_cover(W + 1*cm, A4[1], styles):
story.append(el)
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 1: DEFINITION & BACKGROUND
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('1. DEFINITION & HISTORICAL BACKGROUND', NAVY, W, styles):
story.append(el)
story.append(Paragraph(
'<b>Amputation</b> is the surgical removal of a limb or part of a limb. '
'It is one of the oldest surgical procedures, historically performed for leprosy, '
'ergotism, and as a form of punishment. Today, widespread occlusive vascular disease '
'accounts for the vast majority of current amputations.',
styles['body']))
story.append(callout_box(
'Key Modern Concept',
[Paragraph(
'Amputation is a <b>reconstructive operation</b>, not a failure. '
'With modern prosthetics, a well-planned amputation returns patients to '
'community life fully mobile. The surgeon\'s responsibility extends beyond '
'wound healing to guide the patient through rehabilitation.',
styles['callout_text'])],
TEAL_LIGHT, TEAL, W, styles))
story.append(Spacer(1, 8))
story.append(Paragraph(
'The historic view that "amputation is the last resort" has led to poor outcomes - '
'operations relegated to the end of lists and delegated to junior staff. Modern practice '
'recognises it as a planned surgical reconstruction requiring senior input.',
styles['body']))
# ─────────────────────────────────────────────────────────────────────────
# SECTION 2: INDICATIONS
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('2. INDICATIONS - THE CLASSIC "3 D\'s"', RED, W, styles):
story.append(el)
# Mnemonic box
story.append(callout_box(
'MNEMONIC',
[Paragraph('<b>DEAD DEADLY DEAD LOSS</b>',
ParagraphStyle('mn', fontName='Helvetica-Bold', fontSize=14,
textColor=RED, leading=20, alignment=TA_CENTER))],
RED_LIGHT, RED, W, styles))
story.append(Spacer(1, 8))
# Three-column indications
ind_data = [
[Paragraph('<b>DEAD LIMB</b>', styles['table_header']),
Paragraph('<b>DEADLY LIMB</b>', styles['table_header']),
Paragraph('<b>DEAD LOSS LIMB</b>', styles['table_header'])],
[
Paragraph('Gangrene due to arterial occlusion:\n'
'- Atherosclerotic occlusion\n'
'- Embolic occlusion\n'
'- Diabetic small vessel disease\n'
'- Buerger\'s disease\n'
'- Raynaud\'s disease\n'
'- Inadvertent intra-arterial injection',
ParagraphStyle('ic', fontName='Helvetica', fontSize=9,
textColor=GREY_DARK, leading=13)),
Paragraph('Life-threatening infection:\n'
'- Wet/moist gangrene\n'
'- Spreading cellulitis\n'
'- Gas gangrene (Clostridial)\n'
'- Malignancy (osteosarcoma)\n'
'- Arteriovenous fistula\n'
'- Severe systemic toxaemia',
ParagraphStyle('ic', fontName='Helvetica', fontSize=9,
textColor=GREY_DARK, leading=13)),
Paragraph('Functional loss:\n'
'- Relentless rest pain\n'
' (no reconstruction possible)\n'
'- Paralysis / contracture\n'
' (limb is a hindrance)\n'
'- Major unrecoverable\n'
' traumatic damage',
ParagraphStyle('ic', fontName='Helvetica', fontSize=9,
textColor=GREY_DARK, leading=13)),
]
]
ind_table = Table(ind_data, colWidths=[W/3]*3)
ind_table.setStyle(TableStyle([
('BACKGROUND', (0,0), (0,0), RED),
('BACKGROUND', (1,0), (1,0), ORANGE),
('BACKGROUND', (2,0), (2,0), HexColor('#8E44AD')),
('BACKGROUND', (0,1), (0,1), RED_LIGHT),
('BACKGROUND', (1,1), (1,1), AMBER_LIGHT),
('BACKGROUND', (2,1), (2,1), PURPLE_LIGHT),
('TOPPADDING', (0,0), (-1,-1), 8),
('BOTTOMPADDING', (0,0), (-1,-1), 8),
('LEFTPADDING', (0,0), (-1,-1), 8),
('RIGHTPADDING', (0,0), (-1,-1), 8),
('INNERGRID', (0,0), (-1,-1), 1, WHITE),
('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(ind_table)
story.append(Spacer(1, 10))
# Aetiology table
story.append(Paragraph('Aetiology by Percentage', styles['subsection']))
aet_data = [
['Indication', 'Percentage (%)'],
['Complications of diabetes mellitus', '60-80%'],
['Non-diabetic infection with ischaemia', '15-25%'],
['Ischaemia without infection', '5-10%'],
['Chronic osteomyelitis', '<5%'],
['Trauma, malignancy, frostbite, other', '<5%'],
]
story.append(two_col_table(aet_data, [W*0.65, W*0.35], NAVY, styles))
story.append(Spacer(1, 4))
story.append(Paragraph(
'Source: Mulholland & Greenfield\'s Surgery, 7th Ed.',
styles['small_italic']))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 3: TYPES AND LEVELS
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('3. TYPES & LEVELS OF AMPUTATION', TEAL, W, styles):
story.append(el)
story.append(Paragraph('By Urgency', styles['subsection']))
urg_data = [
['Type', 'Description', 'Wound Management'],
['Elective', 'Freedom to plan flaps; level based on blood supply & rehabilitation potential',
'Primary closure'],
['Urgent', 'Fulminating infection or trauma; tissue viability is paramount; '
'senior surgeon essential',
'Open wound -> delayed primary closure at ~5 days'],
]
story.append(two_col_table(urg_data, [W*0.18, W*0.50, W*0.32], TEAL, styles))
story.append(Spacer(1, 12))
story.append(Paragraph('Lower Limb Levels (Proximal to Distal)', styles['subsection']))
lvl_data = [
['Level', 'Landmark', 'Notes'],
['Hindquarter / Hemipelvectomy', 'Pelvis', 'Rare; malignancy mainly'],
['Above-knee (AKA)\nTransfemoral', '25-30 cm below greater trochanter',
'Weight-bearing: ischial tuberosity\n~40% vascular pts ambulatory\n+60-100% energy cost'],
['Through-knee\nGritti-Stokes', 'Knee disarticulation',
'End-bearing stump; poor cosmesis; rarely used'],
['Below-knee (BKA)\nTranstibial', '14 cm below knee joint',
'Weight-bearing: patellar tendon + tibial flares\n~75% ambulatory\n+30-60% energy cost\nBurgess long posterior flap'],
['Syme Amputation', 'Ankle disarticulation\n+ heel pad preservation',
'End-bearing; +10% energy only\nExcellent rehab potential\nBulbous stump appearance'],
['Transmetatarsal (TMA)', 'Through metatarsals',
'When several toes involved\nMinimal energy increase\nSteel-shank/rigid shoe'],
['Ray Amputation', 'Digit + corresponding metatarsal',
'When MTP joint involved\nWound often left open'],
['Digital / Toe', 'Through or disarticulated toe',
'Small vessel disease with good proximal supply\nHighest repeat amputation rate'],
]
lvl_table_data = []
for i, row in enumerate(lvl_data):
if i == 0:
lvl_table_data.append([Paragraph(c, styles['table_header']) for c in row])
else:
lvl_table_data.append([Paragraph(c, styles['table_cell']) for c in row])
lvl_t = Table(lvl_table_data, colWidths=[W*0.28, W*0.28, W*0.44])
lvl_t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), TEAL),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, TEAL_LIGHT]),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 7),
('RIGHTPADDING', (0,0), (-1,-1), 7),
('GRID', (0,0), (-1,-1), 0.5, HexColor('#D5D8DC')),
('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(lvl_t)
story.append(Spacer(1, 8))
story.append(callout_box(
'EXAM PEARL: Elective Level Landmarks',
[
Paragraph('Lower limb: AKA = 25-30 cm below greater trochanter | BKA = 14 cm below knee joint', styles['callout_text']),
Paragraph('Upper limb: Above elbow = 20 cm below acromion | Below elbow = 17 cm below olecranon', styles['callout_text']),
],
AMBER_LIGHT, AMBER, W, styles))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 4: LEVEL SELECTION
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('4. LEVEL SELECTION - HOW TO DECIDE', NAVY, W, styles):
story.append(el)
story.append(Paragraph(
'<b>Key principle:</b> Preserve the knee joint whenever possible. '
'BKA vs AKA dramatically changes rehabilitation potential.',
styles['body_bold']))
story.append(Spacer(1, 4))
tests_data = [
['Test', 'Details', 'Significance'],
['Transcutaneous PO2 (TcPO2)', 'Measures skin oxygen tension', '>20 mmHg = healing likely; most reliable'],
['Laser Doppler', 'Skin blood flow measurement', 'Good but variable results'],
['Skin temperature', 'Warm = better perfusion', 'Simple; unreliable alone'],
['Segmental pressures / ABPI', 'Ankle-brachial pressure index', 'ABPI >0.5 at proposed level favourable'],
['Arteriography', 'Delineates arterial anatomy', 'Also assesses reconstruction options'],
['Clinical judgement', 'Skin colour, bleeding, tissue viability at operation', 'MOST IMPORTANT - none of the above is decisive alone'],
]
story.append(two_col_table(tests_data, [W*0.28, W*0.38, W*0.34], NAVY, styles))
story.append(Spacer(1, 6))
story.append(callout_box(
'WARNING',
[Paragraph(
'None of the pre-operative tests has proved individually decisive. '
'Senior clinical judgement at the time of surgery remains the gold standard.',
ParagraphStyle('wt', fontName='Helvetica-Bold', fontSize=9.5, textColor=RED,
leading=13, leftIndent=6))],
RED_LIGHT, RED, W, styles))
# ─────────────────────────────────────────────────────────────────────────
# SECTION 5: PRINCIPLES OF SURGERY
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('5. PRINCIPLES OF SURGERY', TEAL, W, styles):
story.append(el)
story.append(Paragraph('General Operative Principles', styles['subsection']))
op_points = [
'Use all viable skin and soft tissue to patient\'s best advantage',
'Elective amputation: fashion skin flaps with adequate blood supply; primary closure',
'Urgent amputation: fashion flaps as for elective but <b>leave wound open</b>; delayed primary closure at ~5 days',
'Adequate bone section proximal to the level of soft tissue division',
'Muscles: myoplasty or myodesis stabilises bone end, improves prosthetic control',
'Nerves: identify, pull down, cut cleanly under tension to retract into soft tissue (prevent neuroma formation)',
'Haemostasis: ligate all vessels; tourniquet use controversial in ischaemic disease',
'Stump dressing: rigid plaster cast or elastic compression to shape stump',
]
for pt in op_points:
story.append(Paragraph(f'• {pt}', styles['bullet']))
story.append(Spacer(1, 8))
story.append(Paragraph('BKA - Burgess Long Posterior Flap Technique', styles['subsection']))
story.append(Paragraph(
'The <b>long posterior flap (Burgess technique)</b> is the standard for BKA. '
'The posterior flap of gastrocnemius muscle and skin is used to cover the bone end. '
'The gastrocnemius has a robust blood supply from the popliteal artery, making it '
'reliable even in ischaemic patients. The anterior incision is at the level of bone '
'section; the posterior flap is approximately 3x the width of the tibia in length.',
styles['body']))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 6: LONG CASE HISTORY
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('6. LONG CASE - HISTORY TAKING', HexColor('#1A5276'), W, styles):
story.append(el)
story.append(Paragraph('Opening Statement Template', styles['subsection']))
story.append(callout_box(
None,
[Paragraph(
'"This is a [age]-year-old [male/female] who has undergone [level] amputation of the '
'[right/left] lower limb, most likely secondary to [peripheral arterial disease / '
'diabetic foot / trauma / malignancy], presenting for [examination / review / '
'rehabilitation assessment]."',
ParagraphStyle('os', fontName='Helvetica-Oblique', fontSize=9.5,
textColor=DARK_NAVY, leading=14, leftIndent=6))],
TEAL_LIGHT, TEAL, W, styles))
story.append(Spacer(1, 10))
# Two-column history layout
hist_left = [
Paragraph('<b>PRESENTING COMPLAINT</b>', styles['subsection']),
Paragraph('• When was the amputation performed?', styles['bullet']),
Paragraph('• Original cause (PAD / DM / trauma / tumour)?', styles['bullet']),
Paragraph('• Elective or emergency?', styles['bullet']),
Paragraph('', styles['bullet']),
Paragraph('<b>PRE-AMPUTATION HISTORY</b>', styles['subsection']),
Paragraph('• Claudication - distance? improving or worsening?', styles['bullet']),
Paragraph('• Rest pain - duration, character, severity', styles['bullet']),
Paragraph('• Gangrene - dry or wet? extent?', styles['bullet']),
Paragraph('• Non-healing ulcer - site, duration', styles['bullet']),
Paragraph('• Was revascularisation attempted?', styles['bullet']),
Paragraph('• Trauma mechanism / malignancy type', styles['bullet']),
Paragraph('', styles['bullet']),
Paragraph('<b>RISK FACTORS</b>', styles['subsection']),
Paragraph('• Diabetes mellitus - duration, HbA1c, complications', styles['bullet']),
Paragraph('• Smoking - pack-years, current/ex', styles['bullet']),
Paragraph('• Hypertension, hyperlipidaemia', styles['bullet']),
Paragraph('• Cardiac history (MI, angina, AF)', styles['bullet']),
Paragraph('• Previous stroke / TIA', styles['bullet']),
Paragraph('• Buerger\'s disease (young male, heavy smoker)', styles['bullet']),
]
hist_right = [
Paragraph('<b>POST-OPERATIVE HISTORY</b>', styles['subsection']),
Paragraph('• Wound healing: primary / secondary / delayed?', styles['bullet']),
Paragraph('• Stump complications (infection, breakdown, neuroma)', styles['bullet']),
Paragraph('• Phantom limb pain or sensation?', styles['bullet']),
Paragraph(' - Character: burning, cramping, shooting?', styles['bullet2']),
Paragraph(' - Treatment received: gabapentin, amitriptyline?', styles['bullet2']),
Paragraph('• Prosthesis: fitted / using / abandoned?', styles['bullet']),
Paragraph('• K-level: K0 (no rehab) to K4 (high activity)', styles['bullet']),
Paragraph('• Physiotherapy / occupational therapy?', styles['bullet']),
Paragraph('', styles['bullet']),
Paragraph('<b>CONTRALATERAL LIMB</b>', styles['subsection']),
Paragraph('• Any symptoms in opposite limb? (CRITICAL)', styles['bullet']),
Paragraph('• Previous ulcers, toe amputations, surgery?', styles['bullet']),
Paragraph('', styles['bullet']),
Paragraph('<b>SOCIAL HISTORY</b>', styles['subsection']),
Paragraph('• Occupation, housing (stairs?)', styles['bullet']),
Paragraph('• Support at home', styles['bullet']),
Paragraph('• Current mobility: wheelchair / walking aids', styles['bullet']),
Paragraph('• Driving? Adapted vehicle?', styles['bullet']),
Paragraph('• Smoking, alcohol', styles['bullet']),
]
# Combine into table
# Pad lists to same length
max_len = max(len(hist_left), len(hist_right))
while len(hist_left) < max_len: hist_left.append(Spacer(1, 2))
while len(hist_right) < max_len: hist_right.append(Spacer(1, 2))
hist_table = Table([[hist_left, hist_right]], colWidths=[W*0.49, W*0.49],
colPadding=0)
hist_table.setStyle(TableStyle([
('VALIGN', (0,0), (-1,-1), 'TOP'),
('LEFTPADDING', (0,0), (-1,-1), 4),
('RIGHTPADDING', (0,0), (-1,-1), 4),
('TOPPADDING', (0,0), (-1,-1), 0),
('BOTTOMPADDING', (0,0), (-1,-1), 0),
('LINEAFTER', (0,0), (0,-1), 1, HexColor('#D5D8DC')),
]))
story.append(hist_table)
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 7: EXAMINATION
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('7. STUMP EXAMINATION - STEP BY STEP', RED, W, styles):
story.append(el)
story.append(callout_box(
'EXAMINATION ROUTINE',
[Paragraph(
'ALWAYS: Expose fully | Compare with contralateral limb | Examine proximal joints | '
'Complete vascular assessment of remaining limb',
styles['callout_text'])],
RED_LIGHT, RED, W, styles))
story.append(Spacer(1, 8))
exam_cols = [
[
Paragraph('<b>GENERAL INSPECTION</b>\n(End of Bed)', styles['subsection']),
Paragraph('• Well/unwell, comfortable?', styles['bullet']),
Paragraph('• Level and side of amputation', styles['bullet']),
Paragraph('• Bilateral or unilateral?', styles['bullet']),
Paragraph('• Prosthesis - on/off/present?', styles['bullet']),
Paragraph('• Wheelchair / walking aids', styles['bullet']),
Paragraph('• Signs of cause: diabetic facies, pallor', styles['bullet']),
Spacer(1, 6),
Paragraph('<b>STUMP INSPECTION</b>', styles['subsection']),
Paragraph('• <b>Level</b> of amputation', styles['bullet']),
Paragraph('• <b>Shape:</b> cylindrical (ideal), conical, bulbous,', styles['bullet']),
Paragraph(' "dog ears" (redundant skin)', styles['bullet2']),
Paragraph('• <b>Skin:</b> colour, trophic changes, oedema', styles['bullet']),
Paragraph('• <b>Scar:</b> healed/unhealed, position (not on weight-bearing surface), keloid', styles['bullet']),
Paragraph('• <b>Wound:</b> dehiscence, sinuses, ulceration', styles['bullet']),
Paragraph('• <b>Muscle bulk:</b> wasting?', styles['bullet']),
Paragraph('• <b>Posture:</b> fixed flexion deformity of proximal joint?', styles['bullet']),
],
[
Paragraph('<b>STUMP PALPATION</b>', styles['subsection']),
Paragraph('• <b>Temperature:</b> warm (good perfusion) vs cold', styles['bullet']),
Paragraph('• <b>Tenderness:</b> especially over scar/bone end', styles['bullet']),
Paragraph('• <b>Neuroma:</b> tender, mobile nodule in scar', styles['bullet']),
Paragraph('• <b>Bone:</b> prominence, inadequate coverage, spur', styles['bullet']),
Paragraph('• <b>Sinus:</b> probe if present (osteomyelitis?)', styles['bullet']),
Paragraph('• <b>Oedema</b> of stump', styles['bullet']),
Paragraph('• <b>Proximal joint ROM:</b> measure flexion contracture', styles['bullet']),
Spacer(1, 6),
Paragraph('<b>REMAINING LIMB ASSESSMENT</b>', styles['subsection']),
Paragraph('• Skin colour, temperature, capillary refill', styles['bullet']),
Paragraph('• Peripheral pulses: femoral, popliteal, DP, PT', styles['bullet']),
Paragraph('• ABPI measurement', styles['bullet']),
Paragraph('• Ulcers, gangrene, trophic changes', styles['bullet']),
Paragraph('• Diabetic foot: neuropathy, deformity (Charcot)', styles['bullet']),
Spacer(1, 6),
Paragraph('<b>SYSTEMIC EXAMINATION</b>', styles['subsection']),
Paragraph('• CVS: pulse (AF?), BP both arms, cardiac failure', styles['bullet']),
Paragraph('• Eyes: diabetic / hypertensive retinopathy', styles['bullet']),
Paragraph('• Abdomen: aortic pulsation (AAA co-exists with PAD)', styles['bullet']),
]
]
ex_table = Table([exam_cols], colWidths=[W*0.49, W*0.49])
ex_table.setStyle(TableStyle([
('VALIGN', (0,0), (-1,-1), 'TOP'),
('LEFTPADDING', (0,0), (-1,-1), 4),
('RIGHTPADDING', (0,0), (-1,-1), 4),
('TOPPADDING', (0,0), (-1,-1), 0),
('BOTTOMPADDING', (0,0), (-1,-1), 0),
('LINEAFTER', (0,0), (0,-1), 1, HexColor('#D5D8DC')),
]))
story.append(ex_table)
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 8: COMPLICATIONS
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('8. COMPLICATIONS OF AMPUTATION', HexColor('#6C3483'), W, styles):
story.append(el)
comp_left = [
Paragraph('<b>EARLY COMPLICATIONS</b>', styles['subsection']),
]
early_data = [
['Complication', 'Details'],
['Haemorrhage', 'Primary (operative)\nReactionary (24-48 h, reactive hyperaemia)\nSecondary (>10 days, infection)'],
['Wound infection', 'Common; highest risk in ischaemic/diabetic patients; broad-spectrum antibiotics'],
['Wound dehiscence', 'Failure of skin flap viability; may need revision amputation at higher level'],
['DVT / PE', 'Major risk; prophylaxis: LMWH + TED stockings on contralateral limb'],
['Respiratory', 'Basal atelectasis, pneumonia; early mobilisation essential'],
['Phantom sensation', 'Feeling that absent limb is present; begins immediately; almost universal'],
]
comp_left.append(two_col_table(early_data, [W*0.30, W*0.70], HexColor('#6C3483'), styles))
comp_left_b = [
Spacer(1, 10),
Paragraph('<b>LATE COMPLICATIONS</b>', styles['subsection']),
]
late_data = [
['Complication', 'Management'],
['Phantom limb PAIN', 'Gabapentin, amitriptyline, SNRIs\nMirror therapy, TENS, desensitisation\nDistinct from phantom sensation'],
['Neuroma', 'Painful end-bulb; desensitisation first\nSurgical: excise + bury nerve in muscle'],
['Bony spur', 'Periosteal new bone; causes pain in socket\nSurgical excision if symptomatic'],
['Fixed flexion deformity', 'Hip (AKA) or knee (BKA) contracture\nPrevented by positioning + early physio\nMay prevent prosthetic fitting'],
['Stump ulceration', 'Prosthetic socket pressure; refitting needed'],
['Skin problems', 'Folliculitis, eczema, verrucous hyperplasia'],
['Osteomyelitis', 'Rare; sinus present; bone scan/MRI; antibiotics +/- revision'],
['Re-amputation', '~30-50% in 5 years for vascular causes'],
['Psychological', 'Depression, PTSD, body image; MDT support'],
]
comp_left_b.append(two_col_table(late_data, [W*0.30, W*0.70], HexColor('#2980B9'), styles))
for el in comp_left:
story.append(el)
for el in comp_left_b:
story.append(el)
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 9: REHABILITATION & PROSTHETICS
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('9. REHABILITATION & PROSTHETICS', GREEN, W, styles):
story.append(el)
# Energy table
story.append(Paragraph('Energy Cost of Ambulation at Different Levels', styles['subsection']))
energy_data = [
['Amputation Level', 'Energy Increase vs Normal', 'Ambulation Rate (Vascular)'],
['Transmetatarsal', 'Minimal', '~90-95%'],
['Syme Amputation', '~10% increase', 'Excellent - can walk on stump at home'],
['Below-Knee (BKA)', '30-60% increase', '~75% of vascular patients'],
['Above-Knee (AKA)', '60-100% increase', '~40% of vascular patients'],
['Bilateral AKA', 'Prohibitive', '<10% ambulatory'],
]
e_table_data = []
for i, row in enumerate(energy_data):
if i == 0:
e_table_data.append([Paragraph(c, styles['table_header']) for c in row])
else:
if i <= 2:
bg = GREEN_LIGHT
elif i == 3:
bg = AMBER_LIGHT
else:
bg = RED_LIGHT
e_table_data.append([Paragraph(c, styles['table_cell']) for c in row])
e_t = Table(e_table_data, colWidths=[W*0.32, W*0.35, W*0.33])
e_t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), GREEN),
('BACKGROUND', (0,1), (-1,2), GREEN_LIGHT),
('BACKGROUND', (0,3), (-1,3), AMBER_LIGHT),
('BACKGROUND', (0,4), (-1,5), RED_LIGHT),
('TOPPADDING', (0,0), (-1,-1), 6),
('BOTTOMPADDING', (0,0), (-1,-1), 6),
('LEFTPADDING', (0,0), (-1,-1), 8),
('RIGHTPADDING', (0,0), (-1,-1), 8),
('GRID', (0,0), (-1,-1), 0.5, HexColor('#D5D8DC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(e_t)
story.append(Spacer(1, 10))
# Prosthetics grid
story.append(Paragraph('Prosthetic Details', styles['subsection']))
pros_data = [
['', 'BKA Prosthesis', 'AKA Prosthesis'],
['Weight-bearing surface', 'Patellar tendon + medial/lateral tibial flares', 'Ischial tuberosity'],
['Socket fixation', 'Suction/pin/strap', 'Suction socket (young)\nBelt (groin scars)'],
['Foot design', 'SACH, dynamic/energy-storing feet (Carbon fibre)', 'Attached to knee unit'],
['Knee unit (AKA)', 'N/A', 'Stance-control (elderly)\nPolycentric/microprocessor (active)'],
['Ambulation rate', '~75% (vascular)', '~40% (vascular)'],
['Special notes', 'Burgess flap heals well\nEarly rigid dressing', 'Groin scars affect socket\nBilateral: <10% ambulatory'],
]
p_table_data = []
for i, row in enumerate(pros_data):
if i == 0:
p_table_data.append([Paragraph(c, styles['table_header']) for c in row])
else:
cells = []
for j, cell in enumerate(row):
s = styles['table_cell_bold'] if j == 0 else styles['table_cell']
cells.append(Paragraph(cell, s))
p_table_data.append(cells)
p_t = Table(p_table_data, colWidths=[W*0.28, W*0.36, W*0.36])
p_t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), GREEN),
('BACKGROUND', (0,1), (0,-1), GREY_LIGHT),
('ROWBACKGROUNDS', (1,1), (-1,-1), [WHITE, GREEN_LIGHT]),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 7),
('RIGHTPADDING', (0,0), (-1,-1), 7),
('GRID', (0,0), (-1,-1), 0.5, HexColor('#D5D8DC')),
('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(p_t)
story.append(Spacer(1, 8))
# K-level
story.append(Paragraph('K-Level Functional Classification', styles['subsection']))
k_data = [
['K-Level', 'Description', 'Prosthetic Goal'],
['K0', 'No rehabilitation potential', 'No prosthesis indicated'],
['K1', 'Household ambulator only', 'Limited; level surfaces only'],
['K2', 'Community ambulator - limited', 'Low activity; variable terrain'],
['K3', 'Community ambulator - variable cadence', 'Most patients aim here; moderate activity'],
['K4', 'High activity (child, athlete, demanding work)', 'High-performance prosthesis'],
]
story.append(two_col_table(k_data, [W*0.12, W*0.50, W*0.38], GREEN, styles))
story.append(Spacer(1, 8))
story.append(callout_box(
'Multidisciplinary Rehabilitation Team',
[Paragraph(
'Surgeon | Physiotherapist | Occupational Therapist | Prosthetist | '
'Psychologist | Social Worker | Specialist Nurse | Dietitian (diabetic patients)',
styles['callout_text'])],
GREEN_LIGHT, GREEN, W, styles))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 10: VIVA Q&A
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('10. VIVA QUESTIONS & MODEL ANSWERS', HexColor('#1A5276'), W, styles):
story.append(el)
vivas = [
('Q1. Define amputation and give the 3 classic indications.',
'Amputation is the surgical removal of a limb or part thereof. The 3 indications are: '
'(1) Dead limb - gangrene due to irreversible arterial occlusion; '
'(2) Deadly limb - spreading infection/gas gangrene/malignancy threatening life; '
'(3) Dead loss limb - relentless rest pain where reconstruction is impossible, '
'paralysis, major unrecoverable trauma. (Bailey & Love)'),
('Q2. What is the most common cause of lower limb amputation? Give percentages.',
'Complications of diabetes mellitus = 60-80%. Non-diabetic infection with ischaemia = 15-25%. '
'Ischaemia without infection = 5-10%. Trauma, malignancy, other = <5% each. '
'(Mulholland & Greenfield Surgery)'),
('Q3. Why is preserving the knee joint so important?',
'An above-knee amputation (AKA) requires 60-100% more energy than normal walking. '
'A below-knee amputation (BKA) only requires 30-60% more. The knee joint provides '
'a crucial lever arm for prosthetic function. Ambulation rates are ~75% for BKA '
'vs ~40% for AKA in vascular patients. Preserving the knee dramatically improves '
'rehabilitation potential and quality of life.'),
('Q4. What is the ideal level and technique for a below-knee amputation?',
'Approximately 14 cm below the knee joint. The Burgess long posterior flap technique '
'is standard: the posterior flap of gastrocnemius muscle and skin covers the bone end. '
'The gastrocnemius has a robust blood supply from the popliteal artery, making it '
'reliable even in ischaemic patients. Bone ends are bevelled; periosteum is preserved. '
'The tibial nerve is identified, gently pulled down, and cut cleanly to retract.'),
('Q5. Distinguish between phantom limb sensation and phantom limb pain.',
'Phantom sensation = awareness that the absent limb is still present (position, '
'movement, volume). Almost universal after amputation; begins immediately. '
'Usually harmless and fades over time. '
'Phantom pain = painful sensations perceived in the absent limb - burning, cramping, '
'crushing, electric shocks. Distinct entity from sensation. Treatment: '
'gabapentin, amitriptyline, SNRIs, mirror therapy, TENS, desensitisation, '
'psychological support.'),
('Q6. A patient develops a tender nodule in the BKA scar 3 months later. Diagnosis and management?',
'Neuroma - painful end-bulb regeneration of transected nerve axons. '
'Management: (1) Conservative: desensitisation (tapping, massage), local anaesthetic injection. '
'(2) Surgical: excise the neuroma and bury the nerve end deep within muscle to prevent '
're-neuroma formation. Prevention: pull nerve down under tension and cut cleanly at '
'operation so it retracts proximally.'),
('Q7. What is a fixed flexion deformity and why does it matter?',
'Flexion contracture of the proximal joint due to unopposed muscle pull and poor '
'post-operative positioning: hip flexion after AKA, knee flexion after BKA. '
'Importance: prevents adequate prosthetic socket fitting, impairs gait biomechanics, '
'may make prosthetic ambulation impossible. '
'Prevention: correct positioning from day 1, early intensive physiotherapy, '
'prone lying periods for AKA patients.'),
('Q8. What concerns you most about the contralateral limb?',
'The contralateral limb is at extremely high risk of future amputation - '
'particularly in diabetic patients where repeat amputation rates are very high. '
'Full vascular and neurological assessment of the contralateral limb is mandatory. '
'Patient education programs significantly reduce repeat amputation rates. '
'The contralateral limb also bears all the load during prosthetic rehabilitation.'),
('Q9. What is a Syme amputation? When is it indicated?',
'Ankle disarticulation preserving the heel pad to cover the bone ends. '
'Advantages: end-bearing stump (patient can ambulate at home without prosthesis), '
'preserves limb length, excellent rehabilitation (+10% energy only). '
'Indicated: extensive foot trauma or non-viable tissue distal to hindfoot. '
'Contraindicated: if heel pad is not viable or well-vascularised. '
'Disadvantage: bulbous stump appearance; less aesthetically pleasing prosthesis.'),
('Q10. When would you leave an amputation wound open?',
'Urgent amputation for fulminating infection or trauma when tissue viability is uncertain. '
'Flaps are fashioned as for elective surgery but the wound is left open. '
'Intended delayed primary closure at approximately 5 days, once infection is controlled, '
'swelling resolved, and tissue viability confirmed. Antibiotic cover: broad-spectrum and massive.'),
('Q11. What tests help determine the amputation level?',
'Transcutaneous PO2 (TcPO2) - >20 mmHg suggests healing potential (most reliable). '
'Laser Doppler flowmetry. Segmental pressures / ABPI. Skin temperature and colour. '
'Arteriography (also assesses reconstruction options). '
'CRITICAL: None is individually decisive - senior clinical judgement at operation remains the gold standard.'),
('Q12. What are the major post-operative complications of amputation?',
'EARLY: haemorrhage (primary/reactionary/secondary), wound infection, dehiscence, DVT/PE, '
'pneumonia, phantom sensation. '
'LATE: phantom limb pain, neuroma, bony spur, fixed flexion deformity, stump ulceration, '
'skin problems (folliculitis, eczema), osteomyelitis (rare), re-amputation (~30-50% in 5 yrs), '
'psychological problems (depression, PTSD, body image).'),
('Q13. What percentage of AKA patients will achieve prosthetic ambulation?',
'Only approximately 40% of vascular insufficiency patients who undergo AKA achieve '
'ambulation with a prosthesis. For bilateral AKA, less than 10% are ambulatory. '
'This is why preserving the knee is so important. Compare to BKA: ~75% ambulate. '
'Young, fit patients (e.g. trauma) have much higher ambulation rates regardless of level.'),
('Q14. What is the role of the surgeon after the amputation wound heals?',
'"The surgeon\'s responsibility does not end once the wound is healed." (Pye\'s Surgical Handicraft). '
'The patient must be guided through rehabilitation and return to community. '
'Amputation is a reconstructive operation - the surgeon leads a multidisciplinary team '
'(physiotherapist, OT, prosthetist, psychologist, social worker) to ensure the patient '
'achieves maximal functional independence. Follow-up includes prosthetic review, '
'contralateral limb surveillance, cardiovascular risk management, and psychological support.'),
]
for i, (q, a) in enumerate(vivas):
is_even = i % 2 == 0
box_color = TEAL_LIGHT if is_even else AMBER_LIGHT
border_color = TEAL if is_even else AMBER
viva_content = [
Paragraph(q, styles['viva_q']),
Paragraph(a, styles['viva_a']),
]
viva_box = Table([viva_content], colWidths=[W])
viva_box.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), box_color),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
('TOPPADDING', (0,0), (-1,-1), 7),
('BOTTOMPADDING', (0,0), (-1,-1), 7),
('LEFTLINE', (0,0), (0,-1), 4, border_color),
('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(KeepTogether(viva_box))
story.append(Spacer(1, 5))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 11: QUICK REFERENCE SUMMARY
# ─────────────────────────────────────────────────────────────────────────
for el in section_block('11. QUICK REFERENCE SUMMARY TABLES', DARK_NAVY, W, styles):
story.append(el)
story.append(Paragraph('BKA vs AKA - Side-by-Side Comparison', styles['subsection']))
compare_data = [
['Parameter', 'BKA (Below-Knee)', 'AKA (Above-Knee)'],
['Level', '14 cm below knee joint', '25-30 cm below greater trochanter'],
['Standard technique', 'Burgess long posterior flap', 'Sagittal or equal flaps'],
['Weight-bearing surface', 'Patellar tendon + tibial flares', 'Ischial tuberosity'],
['Socket fixation', 'Pin/suction/strap', 'Suction socket or belt'],
['Ambulation rate (vascular)', '~75%', '~40%'],
['Energy cost', '+30-60%', '+60-100%'],
['Knee joint', 'PRESERVED', 'LOST'],
['Flexion contracture risk', 'Knee flexion', 'Hip flexion'],
['Preferred in', 'Most vascular/DM cases', 'When BKA not viable'],
]
c_data = []
for i, row in enumerate(compare_data):
if i == 0:
c_data.append([Paragraph(c, styles['table_header']) for c in row])
else:
c_data.append([
Paragraph(row[0], styles['table_cell_bold']),
Paragraph(row[1], styles['table_cell']),
Paragraph(row[2], styles['table_cell']),
])
c_t = Table(c_data, colWidths=[W*0.30, W*0.35, W*0.35])
c_t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), DARK_NAVY),
('BACKGROUND', (0,1), (0,-1), GREY_LIGHT),
('BACKGROUND', (1,1), (1,-1), TEAL_LIGHT),
('BACKGROUND', (2,1), (2,-1), RED_LIGHT),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 8),
('RIGHTPADDING', (0,0), (-1,-1), 8),
('GRID', (0,0), (-1,-1), 0.5, HexColor('#D5D8DC')),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(c_t)
story.append(Spacer(1, 12))
# Complications summary
story.append(Paragraph('Complications Quick List', styles['subsection']))
comp_quick = [
['EARLY', 'LATE'],
['Haemorrhage (primary / reactionary / secondary)',
'Phantom limb PAIN (gabapentin, amitriptyline, mirror therapy)'],
['Wound infection', 'Neuroma (excise + bury in muscle)'],
['Wound dehiscence', 'Bony spur (excise if symptomatic)'],
['DVT / PE', 'Fixed flexion deformity (physio, positioning)'],
['Basal atelectasis / pneumonia', 'Stump ulceration (socket refitting)'],
['Phantom SENSATION (almost universal)', 'Re-amputation (~30-50% at 5 yrs - vascular)'],
['', 'Psychological (depression, PTSD)'],
]
cq_data = []
for i, row in enumerate(comp_quick):
if i == 0:
cq_data.append([Paragraph(c, styles['table_header']) for c in row])
else:
cq_data.append([Paragraph(c, styles['table_cell']) for c in row])
cq_t = Table(cq_data, colWidths=[W*0.50, W*0.50])
cq_t.setStyle(TableStyle([
('BACKGROUND', (0,0), (0,0), HexColor('#E74C3C')),
('BACKGROUND', (1,0), (1,0), HexColor('#8E44AD')),
('BACKGROUND', (0,1), (0,-1), RED_LIGHT),
('BACKGROUND', (1,1), (1,-1), PURPLE_LIGHT),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 8),
('RIGHTPADDING', (0,0), (-1,-1), 8),
('GRID', (0,0), (-1,-1), 0.5, HexColor('#D5D8DC')),
('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(cq_t)
story.append(Spacer(1, 12))
# Final key pearls box
story.append(callout_box(
'EXAM KEY PEARLS - REMEMBER THESE',
[
Paragraph('1. The 3 D\'s: Dead | Deadly | Dead Loss', styles['bullet']),
Paragraph('2. DM causes 60-80% of lower limb amputations', styles['bullet']),
Paragraph('3. BKA preferred over AKA wherever possible - 2x energy difference', styles['bullet']),
Paragraph('4. BKA level = 14 cm below knee | AKA level = 25-30 cm below greater trochanter', styles['bullet']),
Paragraph('5. Burgess long posterior flap is the standard BKA technique', styles['bullet']),
Paragraph('6. Ambulation rates: BKA ~75% vs AKA ~40% (vascular patients)', styles['bullet']),
Paragraph('7. Phantom PAIN (gabapentin/amitriptyline) distinct from phantom SENSATION', styles['bullet']),
Paragraph('8. ALWAYS examine the contralateral limb - high risk of future amputation', styles['bullet']),
Paragraph('9. TcPO2 >20 mmHg = healing likely; no single test is decisive', styles['bullet']),
Paragraph('10. Urgent amputation = open wound + delayed primary closure at ~5 days', styles['bullet']),
],
TEAL_LIGHT, TEAL, W, styles))
story.append(Spacer(1, 10))
story.append(Paragraph(
'Sources: Bailey & Love\'s Short Practice of Surgery 28th Ed | Pye\'s Surgical Handicraft 22nd Ed | '
'Mulholland & Greenfield\'s Surgery 7th Ed | Sabiston Textbook of Surgery',
styles['small_italic']))
# ── BUILD ──────────────────────────────────────────────────────────────────
doc.build(story, onFirstPage=lambda c, d: on_page(c, d, styles),
onLaterPages=lambda c, d: on_page(c, d, styles))
print(f'PDF saved to: {OUTPUT_PATH}')
if __name__ == '__main__':
build_pdf()
cd /home/daytona/workspace/amputation-guide && python3 generate_pdf.py 2>&1
~/amputation-guide/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/amputation-guide/generate_pdf.py'
cd /home/daytona/workspace/amputation-guide && python3 generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/amputation-guide/Amputation_Exam_Revision_Guide.pdf
Amputation Exam Revision Guide
PDF Document · PDF
| Section | Content |
|---|---|
| Cover Page | Visual overview with badge layout |
| 1. Definition | Historical background + modern concept of amputation as reconstruction |
| 2. Indications | The 3 D's mnemonic table + aetiology percentages |
| 3. Types & Levels | Full level table (digital to hindquarter) + elective landmarks |
| 4. Level Selection | Tests (TcPO2, Laser Doppler, ABPI) + critical judgment note |
| 5. Principles of Surgery | Operative principles + Burgess flap description |
| 6. Long Case History | Two-column structured history template |
| 7. Stump Examination | Step-by-step inspection + palpation + vascular assessment |
| 8. Complications | Early and late complications with management |
| 9. Rehabilitation | Energy cost table + BKA vs AKA prosthetics + K-level classification + MDT |
| 10. Viva Q&A | 14 model questions with full answers (colour-coded boxes) |
| 11. Quick Reference | BKA vs AKA comparison table + complications grid + 10 exam key pearls |