Need ans upto 9 number for viva anatomy upper limb 1st year
| Region | Bones |
|---|---|
| Shoulder girdle | Clavicle, Scapula |
| Arm (brachium) | Humerus |
| Forearm (antebrachium) | Radius (lateral), Ulna (medial) |
| Wrist (carpus) | 8 carpal bones (2 rows of 4) |
| Hand | 5 metacarpals + 14 phalanges |
| Wall | Formed by |
|---|---|
| Apex (inlet) | Clavicle (ant), Scapula superior margin (post), Lateral border of rib I (medial) |
| Anterior wall | Pectoralis major, pectoralis minor, subclavius, clavipectoral fascia |
| Posterior wall | Subscapularis, teres major, latissimus dorsi |
| Medial wall | Serratus anterior + thoracic wall (ribs 2-6) |
| Lateral wall | Intertubercular groove of humerus |
| Floor (base) | Axillary fascia + skin between anterior and posterior axillary folds |
| Nerve | Origin | Key muscles | Sensory |
|---|---|---|---|
| Musculocutaneous | Lateral cord | Biceps brachii, brachialis, coracobrachialis | Lateral forearm (via lateral cutaneous nerve of forearm) |
| Median | Both lateral & medial cords (M-shape over axillary artery) | Flexors of forearm (except FCU & medial FDP), LOAF muscles in hand | Lateral 3½ digits (palm) |
| Ulnar | Medial cord | FCU, medial FDP, intrinsic hand muscles | Medial 1½ digits |
| Axillary | Posterior cord | Deltoid, teres minor | Regimental badge area |
| Radial | Posterior cord | All posterior compartments (arm + forearm) | Posterior arm, forearm, lateral dorsum of hand |
| Muscle | Action | Nerve |
|---|---|---|
| Pronator teres | Pronation + flexion elbow | Median (C6,C7) |
| Flexor carpi radialis | Flex + abduct wrist | Median (C6,C7) |
| Palmaris longus | Flex wrist (absent in 15%) | Median (C7,C8) |
| Flexor carpi ulnaris | Flex + adduct wrist | Ulnar (C7,C8) |
| Flexor digitorum superficialis | Flex PIP joints 2-5 | Median (C7,C8,T1) |
| Muscle | Action | Nerve |
|---|---|---|
| Flexor digitorum profundus (medial half) | Flex DIP joints 4-5 | Ulnar |
| Flexor digitorum profundus (lateral half) | Flex DIP joints 2-3 | Anterior interosseous (Median) |
| Flexor pollicis longus | Flex thumb IP joint | Anterior interosseous (Median) |
| Pronator quadratus | Pronation | Anterior interosseous (Median) |
| Arch | Formation | Branches |
|---|---|---|
| Superficial | Ulnar + superficial branch of radial | Common palmar digital arteries → proper digital arteries |
| Deep | Radial + deep branch of ulnar | Palmar metacarpal arteries (join common digital arteries) |
| Movement | Range | Primary muscles |
|---|---|---|
| Flexion | 0-90° (>90° = elevation) | Deltoid (clavicular), Pectoralis major, Biceps |
| Extension | 0-40° | Deltoid (spinal), Latissimus dorsi, Teres major |
| Abduction | 0-90° at GH joint (90-180° = scapular rotation) | Supraspinatus (0-15°), Deltoid (15-90°) |
| Adduction | 20-40° | Pectoralis major, Latissimus dorsi, Teres major |
| Internal rotation | 50-95° | Subscapularis, Pectoralis major, Teres major |
| External rotation | 40-45° | Infraspinatus, Teres minor |
| Muscle | Origin | Insertion | Nerve | Action |
|---|---|---|---|---|
| Supraspinatus | Supraspinous fossa of scapula | Superior facet of greater tubercle of humerus | Suprascapular nerve (C5, C6) | Initiates abduction (first 0-15°); prevents inferior subluxation |
| Infraspinatus | Infraspinous fossa of scapula | Middle facet of greater tubercle | Suprascapular nerve (C5, C6) | External rotation of arm; posterior stability |
| Teres minor | Lateral border of scapula | Inferior facet of greater tubercle | Axillary nerve (C5, C6) | External rotation; inferior stability |
| Subscapularis | Subscapular fossa (anterior surface scapula) | Lesser tubercle of humerus | Upper + Lower subscapular nerves (C5, C6) | Internal rotation; prevents anterior dislocation |
| Topic | Key Point for Viva |
|---|---|
| Osteology | 8 carpal bones (2 rows); scaphoid most commonly fractured |
| Axilla | Gateway to upper limb; axillary artery (3 parts), 5 groups lymph nodes |
| Brachial Plexus | C5-T1; 5 roots→3 trunks→6 divisions→3 cords→5 terminal branches |
| Cubital Fossa | Contents: median nerve, brachial artery, biceps tendon (medial to lateral) |
| Muscles of Forearm | Anterior = median + ulnar; Posterior = radial (posterior interosseous) |
| Nerves | Radial = wrist drop; Ulnar = claw hand; Median = LOAF + opposition loss |
| Vessels | Brachial → radial + ulnar at neck of radius; superficial + deep palmar arch |
| Shoulder Joint | Ball & socket; most mobile but most dislocated; Bankart + Hill-Sachs lesion |
| Rotator Cuff | SITS: primary dynamic stabilizer; supraspinatus most commonly torn |
Make a study guide PDF of all 9 topics for quick revision
ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or missing"
mkdir -p /home/daytona/workspace/upper-limb-study-guide && python3 -c "import reportlab; print(reportlab.Version)"
~/upper-limb-study-guide/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
PageBreak, HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame
from reportlab.lib.colors import HexColor
OUTPUT = "/home/daytona/workspace/upper-limb-study-guide/Upper_Limb_Anatomy_Viva_Guide.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
NAVY = HexColor("#1a3a5c")
TEAL = HexColor("#0d7377")
GOLD = HexColor("#f5a623")
LIGHT_B = HexColor("#e8f4f8")
LIGHT_G = HexColor("#eaf7ea")
LIGHT_Y = HexColor("#fffbea")
LIGHT_P = HexColor("#f3eeff")
WHITE = colors.white
DARK = HexColor("#1e1e1e")
GRAY = HexColor("#666666")
LGRAY = HexColor("#f4f4f4")
RED_L = HexColor("#fff0f0")
RED_D = HexColor("#c0392b")
# topic accent colours cycling through the 9 topics
TOPIC_COLORS = [
HexColor("#1a3a5c"), # 1 deep navy
HexColor("#0d7377"), # 2 teal
HexColor("#6c3483"), # 3 purple
HexColor("#17618a"), # 4 blue
HexColor("#145a32"), # 5 dark green
HexColor("#6e2f00"), # 6 brown
HexColor("#7b0a2a"), # 7 dark red
HexColor("#0b4f4a"), # 8 dark teal
HexColor("#2e4057"), # 9 slate
]
TOPIC_LIGHT = [
HexColor("#dce8f5"),
HexColor("#d0f0f0"),
HexColor("#ede0ff"),
HexColor("#d6ebf7"),
HexColor("#d5f5e3"),
HexColor("#fde8d8"),
HexColor("#fde0e6"),
HexColor("#d0ecea"),
HexColor("#dde3ea"),
]
# ── Document styles ──────────────────────────────────────────────────────────
def make_styles():
base = getSampleStyleSheet()
s = {}
s["cover_title"] = ParagraphStyle("cover_title",
fontSize=30, fontName="Helvetica-Bold",
textColor=WHITE, alignment=TA_CENTER, leading=36, spaceAfter=6)
s["cover_sub"] = ParagraphStyle("cover_sub",
fontSize=14, fontName="Helvetica",
textColor=HexColor("#d0e8ff"), alignment=TA_CENTER, leading=20, spaceAfter=4)
s["cover_note"] = ParagraphStyle("cover_note",
fontSize=11, fontName="Helvetica-Oblique",
textColor=HexColor("#aed6f1"), alignment=TA_CENTER, leading=16)
s["topic_header"] = ParagraphStyle("topic_header",
fontSize=17, fontName="Helvetica-Bold",
textColor=WHITE, alignment=TA_LEFT, leading=22,
leftIndent=8, spaceAfter=4, spaceBefore=0)
s["section_title"] = ParagraphStyle("section_title",
fontSize=11, fontName="Helvetica-Bold",
textColor=NAVY, spaceBefore=8, spaceAfter=3, leading=14)
s["body"] = ParagraphStyle("body",
fontSize=9.5, fontName="Helvetica",
textColor=DARK, leading=14, spaceAfter=3, alignment=TA_JUSTIFY)
s["bullet"] = ParagraphStyle("bullet",
fontSize=9.5, fontName="Helvetica",
textColor=DARK, leading=13, spaceAfter=2,
leftIndent=12, bulletIndent=0)
s["mnemonic"] = ParagraphStyle("mnemonic",
fontSize=10, fontName="Helvetica-Bold",
textColor=HexColor("#7b0a2a"), leading=14,
spaceBefore=4, spaceAfter=4,
leftIndent=8, borderPad=4)
s["clinical"] = ParagraphStyle("clinical",
fontSize=9, fontName="Helvetica-Oblique",
textColor=HexColor("#7b0a2a"), leading=13,
leftIndent=6, spaceAfter=3)
s["toc_entry"] = ParagraphStyle("toc_entry",
fontSize=11, fontName="Helvetica",
textColor=DARK, leading=18, leftIndent=20)
s["toc_num"] = ParagraphStyle("toc_num",
fontSize=11, fontName="Helvetica-Bold",
textColor=TEAL, leading=18)
s["footer"] = ParagraphStyle("footer",
fontSize=8, fontName="Helvetica",
textColor=GRAY, alignment=TA_CENTER)
s["source"] = ParagraphStyle("source",
fontSize=7.5, fontName="Helvetica-Oblique",
textColor=GRAY, alignment=TA_RIGHT, spaceAfter=0)
return s
# ── Helper builders ──────────────────────────────────────────────────────────
def topic_banner(title, number, styles, color):
"""Coloured banner for each topic."""
banner_data = [[Paragraph(f"<b>Topic {number}:</b> {title}", styles["topic_header"])]]
t = Table(banner_data, colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [4, 4, 4, 4]),
]))
return t
def simple_table(headers, rows, col_widths, accent, light):
"""Styled data table."""
data = [headers] + rows
t = Table(data, colWidths=col_widths, repeatRows=1)
style = [
("BACKGROUND", (0,0), (-1,0), accent),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 8.5),
("FONTNAME", (0,1), (-1,-1), "Helvetica"),
("FONTSIZE", (0,1), (-1,-1), 8.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, light]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#cccccc")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("WORDWRAP", (0,0), (-1,-1), True),
]
t.setStyle(TableStyle(style))
return t
def mnemonic_box(text, styles):
data = [[Paragraph(f"🧠 {text}", styles["mnemonic"])]]
t = Table(data, colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), HexColor("#fff8e1")),
("BOX", (0,0), (-1,-1), 1, GOLD),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
]))
return t
def clinical_box(text, styles):
data = [[Paragraph(f"⚕ {text}", styles["clinical"])]]
t = Table(data, colWidths=[17*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), RED_L),
("BOX", (0,0), (-1,-1), 0.8, RED_D),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 10),
]))
return t
def sp(n=1): return Spacer(1, n*4*mm)
def hr(color=HexColor("#dddddd")): return HRFlowable(width="100%", thickness=0.5, color=color)
# ── Content builder ──────────────────────────────────────────────────────────
def build_content(styles):
story = []
C = TOPIC_COLORS
L = TOPIC_LIGHT
# ════════════════════════════════════════════
# COVER PAGE
# ════════════════════════════════════════════
cover_bg = Table(
[[Paragraph("UPPER LIMB ANATOMY", styles["cover_title"]),],
[Paragraph("Viva Quick Revision Guide", styles["cover_sub"]),],
[Paragraph("1st Year MBBS · Topics 1 – 9", styles["cover_sub"]),],
[Spacer(1, 8*mm)],
[Paragraph("Based on Gray's Anatomy for Students & THIEME Atlas of Anatomy", styles["cover_note"]),],
],
colWidths=[17*cm]
)
cover_bg.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 18),
("BOTTOMPADDING",(0,0), (-1,-1), 18),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
]))
story.append(sp(6))
story.append(cover_bg)
story.append(sp(3))
# Topics list on cover
toc_items = [
("1", "Osteology of Upper Limb"),
("2", "Axilla"),
("3", "Brachial Plexus"),
("4", "Cubital Fossa and Arms"),
("5", "Muscles of Forearm"),
("6", "Nerves of Upper Limb"),
("7", "Vessels of Upper Limb"),
("8", "Shoulder Joint"),
("9", "Rotator's Cuff"),
]
toc_data = [[Paragraph(f"<b>{n}.</b>", styles["toc_num"]),
Paragraph(t, styles["toc_entry"])] for n, t in toc_items]
toc_table = Table(toc_data, colWidths=[1.2*cm, 15.8*cm])
toc_table.setStyle(TableStyle([
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING",(0,0), (-1,-1), 3),
("LINEBELOW", (0,0), (-1,-1), 0.3, HexColor("#cccccc")),
]))
story.append(toc_table)
story.append(PageBreak())
# ════════════════════════════════════════════
# TOPIC 1: OSTEOLOGY
# ════════════════════════════════════════════
story.append(topic_banner("Osteology of the Upper Limb", 1, styles, C[0]))
story.append(sp())
story.append(Paragraph("Bones Overview (32 bones per limb)", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Region</b>", styles["body"]),
Paragraph("<b>Bones</b>", styles["body"])],
[
["Shoulder girdle", "Clavicle, Scapula"],
["Arm (Brachium)", "Humerus"],
["Forearm (Antebrachium)", "Radius (lateral), Ulna (medial)"],
["Wrist (Carpus)", "8 carpal bones (2 rows of 4)"],
["Hand", "5 Metacarpals + 14 Phalanges (2 in thumb, 3 in each finger)"],
],
[5*cm, 12*cm], C[0], L[0]
))
story.append(sp())
story.append(Paragraph("Carpal Bones (Proximal → Distal, Lateral → Medial)", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Row</b>", styles["body"]), Paragraph("<b>Bones</b>", styles["body"])],
[
["Proximal", "Scaphoid · Lunate · Triquetrum · Pisiform"],
["Distal", "Trapezium · Trapezoid · Capitate · Hamate"],
],
[3*cm, 14*cm], C[0], L[0]
))
story.append(sp())
story.append(mnemonic_box(
'Mnemonic: "She Looks Too Pretty; Try To Catch Her"', styles))
story.append(sp())
story.append(Paragraph("Key Bone Features to Know", styles["section_title"]))
bone_points = [
"<b>Clavicle:</b> Only horizontal long bone; transmits forces from upper limb to axial skeleton. Fractures at junction of middle and lateral thirds.",
"<b>Scapula:</b> Triangular flat bone. Key landmarks: glenoid cavity, coracoid process, acromion, scapular spine, supraspinous and infraspinous fossae, subscapular fossa.",
"<b>Humerus:</b> Head articulates with glenoid. Surgical neck (site of fracture + axillary nerve injury). Greater tubercle (3 facets for SITS). Radial (spiral) groove carries radial nerve + profunda brachii artery.",
"<b>Radius:</b> Lateral forearm bone. Head at elbow. Radial tuberosity for biceps insertion. Styloid process (distal).",
"<b>Ulna:</b> Medial. Olecranon = tip of elbow. Coronoid process, trochlear notch (wraps around humerus trochlea). Styloid process (distal).",
"<b>Scaphoid:</b> Most commonly fractured carpal bone — tenderness in anatomical snuffbox. Risk of avascular necrosis (blood enters distally).",
]
for pt in bone_points:
story.append(Paragraph(f"• {pt}", styles["bullet"]))
story.append(sp())
story.append(clinical_box(
"Clinical: Colles' fracture = distal radius fracture with dorsal displacement → 'dinner fork deformity'. "
"Scaphoid fracture may not appear on initial X-ray — if snuffbox tenderness persists, MRI is indicated.", styles))
story.append(PageBreak())
# ════════════════════════════════════════════
# TOPIC 2: AXILLA
# ════════════════════════════════════════════
story.append(topic_banner("Axilla", 2, styles, C[1]))
story.append(sp())
story.append(Paragraph(
"The axilla is a pyramidal space forming the gateway between the neck and the arm. "
"All major vessels, nerves, and lymphatics of the upper limb pass through here.",
styles["body"]))
story.append(sp())
story.append(Paragraph("Boundaries", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Wall</b>", styles["body"]), Paragraph("<b>Structure</b>", styles["body"])],
[
["Apex (inlet)", "Clavicle (ant) + Scapula superior margin (post) + Lateral border rib I"],
["Anterior wall", "Pectoralis major, pectoralis minor, subclavius, clavipectoral fascia"],
["Posterior wall", "Subscapularis, teres major, latissimus dorsi"],
["Medial wall", "Serratus anterior + thoracic wall (ribs 2–6)"],
["Lateral wall", "Intertubercular groove of humerus (narrowest wall)"],
["Floor (base)", "Axillary fascia + skin between anterior/posterior axillary folds"],
],
[4*cm, 13*cm], C[1], L[1]
))
story.append(sp())
story.append(Paragraph("Contents (ABCLN)", styles["section_title"]))
story.append(mnemonic_box("A–Axillary artery B–Brachial plexus cords C–Cephalic vein L–Lymph nodes N–Nerves", styles))
story.append(sp())
story.append(Paragraph("Axillary Artery – 3 Parts (divided by pectoralis minor)", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Part</b>", styles["body"]),
Paragraph("<b>Position</b>", styles["body"]),
Paragraph("<b>Branches</b>", styles["body"])],
[
["Part 1", "Medial to pec minor", "Superior thoracic artery (1 branch)"],
["Part 2", "Behind pec minor", "Thoracoacromial artery, Lateral thoracic artery (2 branches)"],
["Part 3", "Lateral to pec minor", "Subscapular artery, Ant. circumflex humeral, Post. circumflex humeral (3 branches)"],
],
[2*cm, 5*cm, 10*cm], C[1], L[1]
))
story.append(mnemonic_box("Rule of 1–2–3: Part 1 = 1 branch, Part 2 = 2 branches, Part 3 = 3 branches", styles))
story.append(sp())
story.append(Paragraph("Important Apertures in Axilla Walls", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Space</b>", styles["body"]), Paragraph("<b>Boundaries</b>", styles["body"]), Paragraph("<b>Contents</b>", styles["body"])],
[
["Quadrangular space", "Sup: teres minor | Inf: teres major | Med: long head triceps | Lat: surgical neck humerus", "Axillary nerve + Post. circumflex humeral artery"],
["Triangular space", "Sup: teres minor | Inf: teres major | Lat: long head triceps", "Circumflex scapular artery"],
["Triangular interval","Sup: teres major | Lat: lateral head triceps | Med: long head triceps", "Radial nerve + Profunda brachii artery"],
],
[3.5*cm, 8*cm, 5.5*cm], C[1], L[1]
))
story.append(sp())
story.append(Paragraph("Axillary Lymph Nodes – 5 Groups", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Group</b>", styles["body"]), Paragraph("<b>Position</b>", styles["body"]), Paragraph("<b>Drains</b>", styles["body"])],
[
["Anterior (pectoral)", "Along lateral thoracic artery", "Breast, ant thoracic wall"],
["Posterior (subscapular)", "Along subscapular artery", "Post thorax, upper back"],
["Lateral", "Along axillary vein", "Whole upper limb"],
["Central", "Embedded in axillary fat", "Receives from above 3 groups"],
["Apical", "At apex, behind pec minor", "All axillary nodes → subclavian lymph trunk"],
],
[4*cm, 6.5*cm, 6.5*cm], C[1], L[1]
))
story.append(PageBreak())
# ════════════════════════════════════════════
# TOPIC 3: BRACHIAL PLEXUS
# ════════════════════════════════════════════
story.append(topic_banner("Brachial Plexus", 3, styles, C[2]))
story.append(sp())
story.append(Paragraph(
"<b>Formation:</b> Anterior rami of C5, C6, C7, C8, T1. "
"Originates in the neck, crosses rib I, enters the axilla.",
styles["body"]))
story.append(sp())
story.append(mnemonic_box("Rugby Teams Drink Cold Beer → Roots · Trunks · Divisions · Cords · Branches", styles))
story.append(sp())
story.append(Paragraph("Trunks and Cords", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Trunk</b>", styles["body"]), Paragraph("<b>Roots</b>", styles["body"]),
Paragraph("<b>Cord</b>", styles["body"]), Paragraph("<b>Formation</b>", styles["body"])],
[
["Superior", "C5 + C6", "Lateral", "Ant div: superior + middle trunks (C5–C7)"],
["Middle", "C7", "Posterior", "All 3 posterior divisions (C5–T1)"],
["Inferior", "C8 + T1", "Medial", "Ant div: inferior trunk (C8–T1)"],
],
[3*cm, 2.5*cm, 3*cm, 8.5*cm], C[2], L[2]
))
story.append(sp())
story.append(Paragraph("5 Terminal Branches", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Nerve</b>", styles["body"]), Paragraph("<b>From</b>", styles["body"]),
Paragraph("<b>Motor</b>", styles["body"]), Paragraph("<b>Sensory</b>", styles["body"])],
[
["Musculocutaneous\n(C5–C7)", "Lateral cord", "Biceps brachii, Brachialis, Coracobrachialis", "Lat. forearm (lat. cut. n. of forearm)"],
["Median\n(C6–T1)", "Lat + Med cords\n(M-shape over axillary a.)", "Flexors of forearm (except FCU + med FDP), LOAF hand muscles", "Lat 3½ digits (palmar)"],
["Ulnar\n(C8–T1)", "Medial cord", "FCU, medial FDP, all intrinsic EXCEPT LOAF", "Medial 1½ digits"],
["Axillary\n(C5–C6)", "Posterior cord", "Deltoid, teres minor", "Regimental badge area"],
["Radial\n(C5–T1)", "Posterior cord\n(largest terminal branch)", "All post. compartments of arm + forearm", "Post arm/forearm, lat dorsum of hand"],
],
[3*cm, 3.5*cm, 5.5*cm, 5*cm], C[2], L[2]
))
story.append(sp())
story.append(Paragraph("LOAF Muscles (Median Nerve, in hand)", styles["section_title"]))
story.append(mnemonic_box("L–Lateral 2 Lumbricals O–Opponens pollicis A–Abductor pollicis brevis F–Flexor pollicis brevis", styles))
story.append(sp())
story.append(Paragraph("Branches from Posterior Cord", styles["section_title"]))
for b in ["Superior subscapular nerve → subscapularis (C5,C6)",
"Thoracodorsal nerve → latissimus dorsi (C6,C7,C8)",
"Inferior subscapular nerve → subscapularis + teres major (C5,C6)",
"Axillary nerve → exits via quadrangular space (C5,C6)",
"Radial nerve → exits via triangular interval (C5–T1)"]:
story.append(Paragraph(f"• {b}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Brachial Plexus Injuries", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Injury</b>", styles["body"]), Paragraph("<b>Roots</b>", styles["body"]),
Paragraph("<b>Deformity</b>", styles["body"]), Paragraph("<b>Mechanism</b>", styles["body"])],
[
["Erb's palsy\n(upper trunk)", "C5–C6", "Waiter's tip: arm adducted, medially rotated, extended, forearm pronated", "Forceful shoulder depression + neck lateral tilt (birth injury, motorcycle fall)"],
["Klumpke's palsy\n(lower trunk)", "C8–T1", "Claw hand + Horner's syndrome\n(ptosis, miosis, anhidrosis)", "Forceful upward pull of arm (grabbing branch to break a fall)"],
],
[3*cm, 2*cm, 6*cm, 6*cm], C[2], L[2]
))
story.append(PageBreak())
# ════════════════════════════════════════════
# TOPIC 4: CUBITAL FOSSA & ARMS
# ════════════════════════════════════════════
story.append(topic_banner("Cubital Fossa and Arms", 4, styles, C[3]))
story.append(sp())
story.append(Paragraph(
"The cubital fossa is a triangular depression anterior to the elbow joint.",
styles["body"]))
story.append(sp())
story.append(Paragraph("Boundaries of Cubital Fossa", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Boundary</b>", styles["body"]), Paragraph("<b>Structure</b>", styles["body"])],
[
["Base (superiorly)", "Imaginary line between medial and lateral epicondyles of humerus"],
["Lateral border", "Brachioradialis muscle"],
["Medial border", "Pronator teres muscle"],
["Floor", "Brachialis + supinator muscles"],
["Roof", "Skin, superficial fascia, bicipital aponeurosis (lacertus fibrosus), deep fascia"],
],
[4*cm, 13*cm], C[3], L[3]
))
story.append(sp())
story.append(Paragraph("Contents (Medial → Lateral)", styles["section_title"]))
story.append(mnemonic_box("My Bottle Really Tastes Nice → Median nerve · Brachial artery · (Biceps) tendon · (Radial nerve)", styles))
for ct in [
"<b>Median nerve</b> – most medial",
"<b>Brachial artery</b> – divides at neck of radius into radial (lateral) and ulnar (medial) arteries",
"<b>Biceps brachii tendon</b> – most lateral palpable structure",
"<b>Radial nerve</b> – technically deep to brachioradialis, not strictly inside fossa",
]:
story.append(Paragraph(f"• {ct}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Surface Veins of Cubital Fossa", styles["section_title"]))
for v in [
"Cephalic vein – lateral",
"Basilic vein – medial",
"Median cubital vein – connects cephalic + basilic; preferred site for venipuncture and IV access",
]:
story.append(Paragraph(f"• {v}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Arm Compartments", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Compartment</b>", styles["body"]),
Paragraph("<b>Muscles</b>", styles["body"]),
Paragraph("<b>Nerve</b>", styles["body"]),
Paragraph("<b>Action</b>", styles["body"])],
[
["Anterior (flexor)", "Biceps brachii (long + short heads)\nBrachialis\nCoracobrachialis", "Musculocutaneous\nC5–C7", "Flex elbow; Biceps also supinates forearm\nBrachialis = pure flexor"],
["Posterior (extensor)", "Triceps brachii\n(long, lateral, medial heads)", "Radial nerve\nC6–C8", "Extend elbow; long head also\nextends + adducts shoulder"],
],
[3*cm, 5.5*cm, 3.5*cm, 5*cm], C[3], L[3]
))
story.append(sp())
story.append(clinical_box(
"Radial nerve in spiral groove: Mid-shaft humeral fracture → radial nerve injury → wrist drop "
"(loss of wrist + finger extension). Sensory loss over first web space dorsally.", styles))
story.append(PageBreak())
# ════════════════════════════════════════════
# TOPIC 5: MUSCLES OF FOREARM
# ════════════════════════════════════════════
story.append(topic_banner("Muscles of Forearm", 5, styles, C[4]))
story.append(sp())
story.append(Paragraph("Anterior Compartment – Superficial Layer (Common Flexor Origin: Medial Epicondyle)", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Muscle</b>", styles["body"]), Paragraph("<b>Action</b>", styles["body"]),
Paragraph("<b>Nerve</b>", styles["body"]), Paragraph("<b>Segments</b>", styles["body"])],
[
["Pronator teres", "Pronation + elbow flexion", "Median", "C6,C7"],
["Flexor carpi radialis", "Flex + abduct wrist", "Median", "C6,C7"],
["Palmaris longus", "Flex wrist (absent ~15%)", "Median", "C7,C8"],
["Flexor carpi ulnaris", "Flex + adduct wrist", "Ulnar", "C7,C8"],
["Flexor digitorum superficialis", "Flex PIP joints digits 2–5", "Median", "C7,C8,T1"],
],
[5*cm, 5*cm, 3.5*cm, 3.5*cm], C[4], L[4]
))
story.append(sp())
story.append(Paragraph("Anterior Compartment – Deep Layer", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Muscle</b>", styles["body"]), Paragraph("<b>Action</b>", styles["body"]),
Paragraph("<b>Nerve</b>", styles["body"]), Paragraph("<b>Segments</b>", styles["body"])],
[
["FDP (lateral half)", "Flex DIP joints 2–3", "Anterior interosseous (median)", "C8,T1"],
["FDP (medial half)", "Flex DIP joints 4–5", "Ulnar", "C8,T1"],
["Flexor pollicis longus","Flex thumb IP joint", "Anterior interosseous (median)", "C8,T1"],
["Pronator quadratus", "Pronation", "Anterior interosseous (median)", "C8,T1"],
],
[5*cm, 5*cm, 4*cm, 3*cm], C[4], L[4]
))
story.append(sp())
story.append(Paragraph("Posterior Compartment – Superficial Layer (Common Extensor Origin: Lateral Epicondyle)", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Muscle</b>", styles["body"]), Paragraph("<b>Action</b>", styles["body"]),
Paragraph("<b>Nerve (deep branch radial / PIN)</b>", styles["body"])],
[
["Brachioradialis", "Accessory elbow flexor (midprone)", "Radial N. (before division) C5,C6"],
["Extensor carpi radialis longus", "Extend + abduct wrist", "Radial N. (before division) C6,C7"],
["Extensor carpi radialis brevis", "Extend + abduct wrist", "Deep branch radial / PIN C6,C7"],
["Extensor digitorum", "Extend fingers 2–5", "PIN C7,C8"],
["Extensor digiti minimi", "Extend little finger", "PIN C7,C8"],
["Extensor carpi ulnaris", "Extend + adduct wrist", "PIN C7,C8"],
],
[5.5*cm, 5*cm, 6.5*cm], C[4], L[4]
))
story.append(sp())
story.append(Paragraph("Posterior Compartment – Deep Layer", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Muscle</b>", styles["body"]), Paragraph("<b>Action</b>", styles["body"])],
[
["Abductor pollicis longus", "Abduct + extend thumb at CMC"],
["Extensor pollicis brevis", "Extend thumb MCP"],
["Extensor pollicis longus", "Extend thumb IP; forms medial border of snuffbox"],
["Extensor indicis", "Extend index finger"],
["Supinator", "Supinate forearm; PIN passes through its 2 heads (arcade of Frohse)"],
],
[6*cm, 11*cm], C[4], L[4]
))
story.append(sp())
story.append(mnemonic_box("All posterior compartment muscles → Radial nerve (PIN = Posterior Interosseous Nerve = deep branch of radial)", styles))
story.append(sp())
story.append(clinical_box(
"PIN compression at arcade of Frohse → loss of finger/thumb extension but wrist extension preserved "
"(ECRL/ECRB spared as they arise before the PIN). "
"Golfer's elbow = medial epicondylitis (common flexor origin). "
"Tennis elbow = lateral epicondylitis (common extensor origin).", styles))
story.append(PageBreak())
# ════════════════════════════════════════════
# TOPIC 6: NERVES OF UPPER LIMB
# ════════════════════════════════════════════
story.append(topic_banner("Nerves of the Upper Limb", 6, styles, C[5]))
story.append(sp())
story.append(Paragraph("Median Nerve (C6–T1)", styles["section_title"]))
for pt in [
"Formed by lateral and medial roots from lateral and medial cords (forms an M over axillary artery)",
"Enters forearm between 2 heads of pronator teres → passes through carpal tunnel (with 9 tendons)",
"Gives <b>recurrent (thenar) branch</b> just distal to flexor retinaculum → thenar muscles",
"Gives <b>palmar cutaneous branch</b> before carpal tunnel → sensation over thenar eminence",
"<b>Injury at wrist:</b> Loss of LOAF + opposition; sensory loss lateral 3½ digits; 'ape thumb'",
"<b>Injury at elbow:</b> 'Benediction hand' – can't flex index + middle fingers (FDP lateral half + FPL loss)",
"Carpal tunnel syndrome: Compression in carpal tunnel → LOAF weakness + nocturnal paresthesia lateral 3½ digits",
]:
story.append(Paragraph(f"• {pt}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Ulnar Nerve (C8–T1)", styles["section_title"]))
for pt in [
"Passes posterior to medial epicondyle ('funny bone') → between 2 heads of FCU",
"Enters hand via Guyon's canal (superficial to flexor retinaculum)",
"Divides into superficial (sensory) + deep (motor) branches in hand",
"<b>Innervates:</b> All intrinsic hand muscles EXCEPT LOAF; FCU; medial half FDP",
"<b>Injury at medial epicondyle:</b> Claw hand ring + little fingers (hyperextension MCP, flexion IP)",
"<b>Injury at wrist:</b> More severe claw (all intrinsics lost; lumbrical correction for 2nd/3rd gone)",
"Sensory loss: Medial 1½ digits + medial palm",
]:
story.append(Paragraph(f"• {pt}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Radial Nerve (C5–T1) – Largest Terminal Branch of Posterior Cord", styles["section_title"]))
for pt in [
"Exits axilla through triangular interval with profunda brachii artery",
"Runs in spiral (radial) groove wrapping around posterior humerus",
"Divides in lateral cubital fossa: <b>Superficial branch</b> (sensory only) + <b>Deep branch / PIN</b> (motor)",
"PIN enters posterior forearm by passing between 2 heads of supinator (arcade of Frohse)",
"<b>Mid-shaft humeral fracture:</b> Radial nerve injury → wrist drop; sensory loss first web space",
"<b>Saturday night palsy:</b> Radial nerve compression in spiral groove (arm draped over chair)",
]:
story.append(Paragraph(f"• {pt}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Axillary Nerve (C5–C6)", styles["section_title"]))
for pt in [
"Exits quadrangular space with posterior circumflex humeral artery",
"Winds around surgical neck of humerus",
"Innervates: Deltoid + teres minor; gives superior lateral cutaneous nerve of arm",
"<b>Injury:</b> Shoulder dislocation / surgical neck fracture → loss of shoulder abduction (deltoid paralysis); sensory loss 'regimental badge area'",
]:
story.append(Paragraph(f"• {pt}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Musculocutaneous Nerve (C5–C7)", styles["section_title"]))
for pt in [
"Pierces coracobrachialis (clinical landmark to identify in axilla)",
"Innervates anterior arm: Coracobrachialis, biceps brachii, brachialis",
"Continues as lateral cutaneous nerve of forearm (sensory to lateral forearm)",
]:
story.append(Paragraph(f"• {pt}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Nerve Injury Summary", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Nerve</b>", styles["body"]), Paragraph("<b>Injury site</b>", styles["body"]),
Paragraph("<b>Deformity/Sign</b>", styles["body"]), Paragraph("<b>Key loss</b>", styles["body"])],
[
["Radial", "Spiral groove", "Wrist drop", "Wrist + finger extension; 1st web space sensation"],
["Ulnar", "Medial epicondyle", "Claw hand (4th+5th)", "Interossei, hypothenar, medial 2 lumbricals"],
["Ulnar", "Wrist (Guyon's)", "Claw hand (worse)", "All intrinsics except LOAF"],
["Median", "Wrist", "Ape thumb (flat thenar)", "LOAF muscles, opposition, lat 3½ digits sensation"],
["Median", "Elbow", "Benediction hand", "Forearm flexors (index/middle, FPL, FDP lat half)"],
["Axillary", "Surgical neck", "Loss of shoulder roundness","Deltoid paralysis, lat deltoid sensation"],
],
[2.5*cm, 3.5*cm, 5*cm, 6*cm], C[5], L[5]
))
story.append(PageBreak())
# ════════════════════════════════════════════
# TOPIC 7: VESSELS OF UPPER LIMB
# ════════════════════════════════════════════
story.append(topic_banner("Vessels of the Upper Limb", 7, styles, C[6]))
story.append(sp())
story.append(Paragraph("Arterial Sequence", styles["section_title"]))
story.append(mnemonic_box(
"Subclavian A. → Axillary A. (at lateral border rib I) → Brachial A. (at lower border teres major) → "
"Radial + Ulnar A. (at neck of radius in cubital fossa)", styles))
story.append(sp())
story.append(Paragraph("Axillary Artery Branches (Parts 1–2–3)", styles["section_title"]))
for b in [
"<b>Part 1:</b> Superior thoracic artery",
"<b>Part 2:</b> Thoracoacromial (4 branches: pectoral, acromial, deltoid, clavicular) + Lateral thoracic artery",
"<b>Part 3:</b> Subscapular artery → circumflex scapular + thoracodorsal; Anterior circumflex humeral; Posterior circumflex humeral",
]:
story.append(Paragraph(f"• {b}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Brachial Artery", styles["section_title"]))
for b in [
"Runs medial side of arm in cleft between biceps and triceps, with median nerve",
"Gives <b>profunda brachii</b> (with radial nerve in spiral groove) — nutrient artery to humerus",
"Gives superior and inferior ulnar collateral arteries",
"Divides at the <b>neck of radius</b> (apex of cubital fossa) → Radial + Ulnar arteries",
"Blood pressure is measured at the brachial artery",
]:
story.append(Paragraph(f"• {b}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Palmar Arches", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Arch</b>", styles["body"]), Paragraph("<b>Formed by</b>", styles["body"]),
Paragraph("<b>Level</b>", styles["body"]), Paragraph("<b>Branches</b>", styles["body"])],
[
["Superficial palmar arch", "Ulnar A. (main) + superficial branch of radial A.", "Deep to palmar aponeurosis", "3 common palmar digital arteries → proper digital arteries"],
["Deep palmar arch", "Radial A. (main) + deep branch of ulnar A.", "Deep to long flexor tendons", "3 palmar metacarpal arteries + 3 perforating branches"],
],
[3.5*cm, 5*cm, 3.5*cm, 5*cm], C[6], L[6]
))
story.append(sp())
story.append(Paragraph("Key Superficial Veins", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Vein</b>", styles["body"]), Paragraph("<b>Origin</b>", styles["body"]),
Paragraph("<b>Course</b>", styles["body"]), Paragraph("<b>Termination</b>", styles["body"])],
[
["Cephalic vein", "Lateral side dorsal venous network", "Over anatomical snuffbox → lateral forearm → deltopectoral groove", "Axillary vein (pierces clavipectoral fascia)"],
["Basilic vein", "Medial side dorsal venous network", "Medial forearm → pierces deep fascia mid-arm", "Joins brachial veins → axillary vein"],
["Median cubital vein", "Connects cephalic to basilic", "Anterior cubital fossa", "Preferred site for venipuncture"],
],
[3.5*cm, 4*cm, 5*cm, 4.5*cm], C[6], L[6]
))
story.append(sp())
story.append(clinical_box(
"Allen's test: Compress both radial and ulnar arteries at wrist, then release one → tests adequacy of palmar arch anastomosis. "
"Radial artery pulse is felt at wrist between FCR and brachioradialis tendons, and also in the anatomical snuffbox.", styles))
story.append(PageBreak())
# ════════════════════════════════════════════
# TOPIC 8: SHOULDER JOINT
# ════════════════════════════════════════════
story.append(topic_banner("Shoulder Joint (Glenohumeral Joint)", 8, styles, C[7]))
story.append(sp())
story.append(Paragraph(
"<b>Type:</b> Synovial, multiaxial ball-and-socket joint. Most mobile joint in the body. "
"Most frequently dislocated joint (45% of all dislocations). "
"Price of mobility = instability.",
styles["body"]))
story.append(sp())
story.append(Paragraph("Articulating Surfaces", styles["section_title"]))
for pt in [
"Head of humerus (large, spherical ball) articulates with glenoid cavity of scapula (small, shallow socket)",
"Articular surface of scapula is 1/3 to 1/4 the size of humeral head",
"<b>Glenoid labrum:</b> Fibrocartilaginous rim ~5 mm wide deepening the socket; increases contact area",
"Size discrepancy increases mobility but compromises stability",
]:
story.append(Paragraph(f"• {pt}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Ligaments", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Ligament</b>", styles["body"]), Paragraph("<b>Connects</b>", styles["body"]),
Paragraph("<b>Function</b>", styles["body"])],
[
["Glenohumeral lig. (sup, mid, inf)", "Glenoid labrum → lesser tubercle/ant capsule", "Reinforce anterior capsule"],
["Coracohumeral lig.", "Coracoid process → greater tubercle", "Strengthen superior capsule; check external rotation"],
["Transverse humeral lig.", "Greater tubercle → lesser tubercle", "Holds long head biceps in intertubercular groove"],
["Coracoacromial lig.", "Coracoid → acromion (arch)", "Forms protective arch above shoulder"],
],
[4*cm, 5.5*cm, 7.5*cm], C[7], L[7]
))
story.append(sp())
story.append(Paragraph("Movements at Glenohumeral Joint", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Movement</b>", styles["body"]), Paragraph("<b>Range</b>", styles["body"]),
Paragraph("<b>Primary muscles</b>", styles["body"])],
[
["Flexion", "0–90° (>90° = elevation)", "Deltoid (clavicular), Pectoralis major, Biceps brachii"],
["Extension", "0–40°", "Deltoid (spinal), Latissimus dorsi, Teres major"],
["Abduction", "0–90° at GH joint", "Supraspinatus (0–15°), Deltoid (15–90°)"],
["Adduction", "20–40°", "Pectoralis major, Latissimus dorsi, Teres major"],
["Internal rotation", "50–95°", "Subscapularis, Pec major, Teres major, Lat dorsi"],
["External rotation", "40–45°", "Infraspinatus, Teres minor"],
],
[3.5*cm, 3.5*cm, 10*cm], C[7], L[7]
))
story.append(sp())
story.append(Paragraph("Bursae", styles["section_title"]))
for b in [
"<b>Subacromial (subdeltoid) bursa:</b> Largest; lies between acromion/deltoid and supraspinatus tendon. Communicates with joint cavity if rotator cuff tears (full thickness)",
"<b>Subscapular bursa:</b> Between subscapularis tendon and scapular neck; communicates with joint cavity",
]:
story.append(Paragraph(f"• {b}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Blood Supply & Innervation", styles["section_title"]))
for b in [
"<b>Blood supply:</b> Anterior + Posterior circumflex humeral arteries; suprascapular artery",
"<b>Nerve supply:</b> Suprascapular nerve, axillary nerve, musculocutaneous nerve, lateral pectoral nerve (Hilton's law)",
]:
story.append(Paragraph(f"• {b}", styles["bullet"]))
story.append(sp())
story.append(clinical_box(
"Shoulder dislocation (anterior-inferior most common): "
"Head of humerus dislocates anteriorly due to forceful external rotation of raised arm. "
"Bankart lesion = tear of anteroinferior labrum. "
"Hill-Sachs lesion = impression fracture of posterosuperior humeral head. "
"Complications: axillary nerve injury (test sensation regimental badge area), "
"axillary artery injury (test radial pulse), rotator cuff tear.", styles))
story.append(PageBreak())
# ════════════════════════════════════════════
# TOPIC 9: ROTATOR'S CUFF
# ════════════════════════════════════════════
story.append(topic_banner("Rotator's Cuff", 9, styles, C[8]))
story.append(sp())
story.append(Paragraph(
"The rotator cuff is a group of 4 muscles and their tendons that surround the glenohumeral joint, "
"forming the primary dynamic stabilizers of the shoulder. Their tendons blend with the fibrous capsule of the joint.",
styles["body"]))
story.append(sp())
story.append(mnemonic_box("SITS → Supraspinatus · Infraspinatus · Teres minor · Subscapularis", styles))
story.append(sp())
story.append(Paragraph("The 4 SITS Muscles", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Muscle</b>", styles["body"]), Paragraph("<b>Origin</b>", styles["body"]),
Paragraph("<b>Insertion</b>", styles["body"]), Paragraph("<b>Nerve</b>", styles["body"]),
Paragraph("<b>Action</b>", styles["body"])],
[
["Supraspinatus", "Supraspinous fossa", "Superior facet,\ngreater tubercle", "Suprascapular\nC5, C6", "Initiates abduction\n(0–15°); prevents\ninferior subluxation"],
["Infraspinatus", "Infraspinous fossa", "Middle facet,\ngreater tubercle", "Suprascapular\nC5, C6", "External rotation;\nposterior stability"],
["Teres minor", "Lateral border scapula", "Inferior facet,\ngreater tubercle", "Axillary nerve\nC5, C6", "External rotation;\ninferior stability"],
["Subscapularis", "Subscapular fossa\n(anterior scapula)", "Lesser tubercle", "Upper + lower\nsubscapular nn.\nC5, C6", "Internal rotation;\nprevents anterior\ndislocation"],
],
[3*cm, 3.5*cm, 3.5*cm, 3*cm, 4*cm], C[8], L[8]
))
story.append(sp())
story.append(Paragraph("Functions of the Rotator Cuff", styles["section_title"]))
for f in [
"Compresses humeral head against glenoid (concavity-compression mechanism)",
"Counteracts upward pull of deltoid during abduction — prevents superior subluxation",
"Provides dynamic stability to supplement the weak joint capsule",
"Each muscle provides specific directional movement and stability",
]:
story.append(Paragraph(f"• {f}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Supraspinatus and the Painful Arc", styles["section_title"]))
for pt in [
"Supraspinatus tendon runs under the coracoacromial arch and over the subacromial bursa",
"<b>Painful arc:</b> Pain during 60–120° of abduction (tendon impinges under acromion at this range)",
"Pain absent below 60° (tendon not yet under arch) and above 120° (tendon clear of arch)",
"Most commonly injured rotator cuff tendon",
"Most tears occur at the <b>critical zone</b> ~1 cm from insertion (watershed zone of poor vascularity)",
]:
story.append(Paragraph(f"• {pt}", styles["bullet"]))
story.append(sp())
story.append(Paragraph("Rotator Cuff Tears – Clinical", styles["section_title"]))
story.append(simple_table(
[Paragraph("<b>Feature</b>", styles["body"]), Paragraph("<b>Detail</b>", styles["body"])],
[
["Common cause", "Degenerative (age >40) + repetitive overhead/pulling activity"],
["Most torn tendon", "Supraspinatus (poor vascular zone at insertion)"],
["Presentation", "Shoulder pain, weakness in abduction + external rotation"],
["Full-thickness tear", "Subacromial bursa communicates with joint cavity"],
["Test", "Empty can test (Jobe's test) for supraspinatus; Drop arm test"],
["Treatment", "Conservative (PT, NSAIDs) or arthroscopic repair; rehab protocol: immobilization → passive → active exercise"],
],
[5*cm, 12*cm], C[8], L[8]
))
story.append(sp())
story.append(clinical_box(
"Shoulder dislocation can rupture the rotator cuff, especially in elderly patients. "
"Full-thickness supraspinatus tear allows deltoid to pull humeral head superiorly "
"→ superior migration on X-ray → secondary impingement. "
"Bankart lesion (labrum tear) = most common lesion with anterior dislocation. "
"Arthroscopic techniques now equal or superior to open repair for most indications.", styles))
story.append(sp(2))
# ════════════════════════════════════════════
# FINAL QUICK REVISION TABLE
# ════════════════════════════════════════════
story.append(HRFlowable(width="100%", thickness=1.5, color=NAVY))
story.append(sp())
story.append(Paragraph("Quick Revision Summary", styles["topic_header"]))
qr_banner = Table([[Paragraph("<b>Quick Revision Summary – All 9 Topics</b>", styles["topic_header"])]],
colWidths=[17*cm])
qr_banner.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
]))
story[-1] = qr_banner # replace the plain header with the styled banner
story.append(sp())
story.append(simple_table(
[Paragraph("<b>#</b>", styles["body"]), Paragraph("<b>Topic</b>", styles["body"]),
Paragraph("<b>Key Viva Point</b>", styles["body"]), Paragraph("<b>Must-Know Mnemonic/Fact</b>", styles["body"])],
[
["1", "Osteology", "32 bones/limb; 8 carpals in 2 rows", "SLTP / TTCH for carpals; Scaphoid → AVN risk"],
["2", "Axilla", "Pyramidal gateway; 3-part axillary artery; 5 lymph node groups", "1-2-3 branch rule for axillary artery parts"],
["3", "Brachial Plexus","C5–T1; RTDCB; 3 trunks → 3 cords → 5 terminal branches", "Erb's palsy C5-6 waiter's tip; Klumpke C8-T1 claw+Horner"],
["4", "Cubital Fossa", "Contents medial→lateral: Median n., Brachial a., Biceps tendon", "Median cubital vein = venipuncture site"],
["5", "Muscles Forearm","Ant = median+ulnar; Post = PIN (deep radial)", "All post. compartment = radial nerve"],
["6", "Nerves UL", "Radial=wrist drop; Ulnar=claw hand; Median=ape thumb", "LOAF = median; Ulnar = all intrinsics except LOAF"],
["7", "Vessels UL", "Brachial → radial+ulnar at neck of radius; palmar arches","Superficial = ulnar; Deep = radial; Cephalic→axillary"],
["8", "Shoulder Joint", "Ball-and-socket; most mobile/most dislocated; Bankart lesion", "Axillary n. injured in dislocation → deltoid loss"],
["9", "Rotator Cuff", "SITS muscles; primary dynamic stabilizers", "Supraspinatus most torn; painful arc 60–120°"],
],
[0.6*cm, 3*cm, 7*cm, 6.4*cm], NAVY, LIGHT_B
))
story.append(sp(3))
story.append(Paragraph(
"Source: Gray's Anatomy for Students (9780323934237) · THIEME Atlas General Anatomy & Musculoskeletal System (9781626237186)",
styles["source"]))
return story
# ── Document setup with header/footer ───────────────────────────────────────
def add_page_elements(canvas, doc):
canvas.saveState()
w, h = A4
# Header bar
canvas.setFillColor(NAVY)
canvas.rect(0, h - 22, w, 22, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica-Bold", 8)
canvas.drawString(18, h - 14, "UPPER LIMB ANATOMY | 1st Year MBBS Viva Guide")
canvas.setFont("Helvetica", 8)
canvas.drawRightString(w - 18, h - 14, "Gray's Anatomy for Students")
# Footer
canvas.setFillColor(LGRAY)
canvas.rect(0, 0, w, 18, fill=1, stroke=0)
canvas.setFillColor(GRAY)
canvas.setFont("Helvetica", 7.5)
canvas.drawCentredString(w / 2, 5, f"Page {doc.page} | Topics 1–9 | Upper Limb Anatomy")
canvas.restoreState()
def main():
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=1.8*cm,
rightMargin=1.8*cm,
topMargin=2.2*cm,
bottomMargin=1.6*cm,
title="Upper Limb Anatomy – Viva Quick Revision Guide",
author="Medical Study Guide",
subject="1st Year MBBS Anatomy",
)
styles = make_styles()
story = build_content(styles)
doc.build(story, onFirstPage=add_page_elements, onLaterPages=add_page_elements)
print(f"PDF created: {OUTPUT}")
if __name__ == "__main__":
main()
cd /home/daytona/workspace/upper-limb-study-guide && python3 generate_pdf.py 2>&1
~/upper-limb-study-guide/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/upper-limb-study-guide/generate_pdf.py'
cd /home/daytona/workspace/upper-limb-study-guide && python3 generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/upper-limb-study-guide/Upper_Limb_Anatomy_Viva_Guide.pdf
Upper Limb Anatomy Viva Guide
PDF Document · PDF
| Page | Content |
|---|---|
| Cover | Title page with all 9 topics listed as a table of contents |
| 1 | Osteology - bone table, carpal bones, key features, clinical notes |
| 2 | Axilla - boundaries, contents, axillary artery (3 parts), quadrangular/triangular spaces, lymph nodes |
| 3 | Brachial Plexus - formation, trunks/cords table, 5 terminal branches, LOAF, Erb's/Klumpke's injuries |
| 4 | Cubital Fossa & Arms - boundaries, contents, arm compartments, radial nerve injury |
| 5 | Muscles of Forearm - anterior (superficial + deep) and posterior compartment tables |
| 6 | Nerves - Median, Ulnar, Radial, Axillary, Musculocutaneous with injury summary table |
| 7 | Vessels - arterial sequence, palmar arches, superficial veins table, Allen's test |
| 8 | Shoulder Joint - articulating surfaces, ligaments, movements table, bursae, dislocation |
| 9 + Summary | Rotator Cuff - SITS table, painful arc, clinical tears + final 9-topic quick revision table |