Brachial plexus diagram
brachial plexus diagram anatomy

Summary : This anatomical illustration shows the brachial plexus and its relationship to surrounding muscles, arteries, and veins in the upper thoracic and shoulder region. It is a labeled diagram highlighting the major nerves, blood vessels, and muscle groups relevant to the anatomy of the brachial plexus.

This composite image illustrates the anatomy and diagnosis of a cervical rib through three modalities. Panel A is an anatomical diagram showing the cervical vertebrae (C4-T1), the first and second ribs, and the brachial plexus (C5-T1). A white arrow identifies a cervical rib emerging from the C7 vertebra. Panel B is a posterior-anterior (PA) neck X-ray demonstrating a radiopaque bony projection (cervical rib) at the C7 level, indicated by a white arrow. Panel C provides a comparative ultrasound study in the transverse plane. The left image (Cervical rib side) shows a hyperechoic structure (CR) with posterior acoustic shadowing located between the anterior scalene (AS) and middle scalene (MS) muscles, encroaching upon the brachial plexus (yellow dashed circle). The right image (Contralateral side) shows the normal anatomy of the C7 transverse process (C7 TP) and the interscalene groove containing the brachial plexus. These images demonstrate how a cervical rib can narrow the interscalene space, contributing to neurogenic thoracic outlet syndrome (TOS).

This composite educational resource comprises three Magnetic Resonance Neurography (MRN) coronal views (a, b, c) and a correlating schematic anatomical diagram (d) illustrating a severe traumatic brachial plexus injury. The right side of the images displays normal brachial plexus anatomy, with continuous nerve structures including the upper trunk (1), middle trunk (2), C8 root (3), and Th1 root (4). In contrast, the left side demonstrates a total rupture of the brachial plexus (dashed arrows). This injury is characterized by the complete discontinuity of the neural trunks and cords, accompanied by a large axillary cavity hematoma (curved dashed arrows). The schematic (d) highlights the side-to-side difference, showing the organized right-sided roots (C5-Th1) and trunks versus the disorganized, hemorrhagic area on the left. This material is designed for advanced medical education in radiology and neurosurgery, focusing on diagnostic imaging features of high-grade nerve trauma, specifically Seddon grade 3-5 injuries (neurotmesis) and the identification of postganglionic plexopathy.

This medical anatomical diagram consists of two panels (A and B) illustrating the musculoskeletal and neural anatomy of the right infraclavicular thoracic outlet. Panel A provides an anterior view, highlighting the brachial plexus (teal) at the cord level as it passes through the retropectoralis minor space. The pectoralis minor muscle is shown originating from the third, fourth, and fifth ribs and inserting onto the coracoid process, forming a muscular bridge over the neurovascular structures. Panel B displays an outlet (inferior-to-superior) view, emphasizing the close spatial relationship between the undersurface of the pectoralis minor muscle and the underlying medial, lateral, and posterior cords of the brachial plexus. Key landmarks include the clavicle, ribs, coracoid process, and humerus. These illustrations serve to demonstrate the anatomical basis of pectoralis minor syndrome (PMS), an etiology of neurogenic thoracic outlet syndrome (NTOS) where hypertrophy or shortening of the muscle causes dynamic compression of the plexus cords against the posterior rib cage.

| Level | Components |
|---|---|
| Roots | C5, C6, C7, C8, T1 |
| Trunks | Upper (C5-C6), Middle (C7), Lower (C8-T1) |
| Divisions | Each trunk divides into anterior and posterior (6 total) |
| Cords | Lateral, Medial, Posterior (named by relation to axillary artery) |
| Branches/Terminal nerves | Musculocutaneous, Median, Ulnar, Radial, Axillary |
Create an illustrated PDF guide on brachial plexus nerve injuries
brachial plexus nerve injury Erb palsy Klumpke anatomy
Erb palsy upper trunk brachial plexus injury waiter tip posture
brachial plexus anatomy roots trunks divisions cords diagram labeled
mkdir -p /tmp/workspace/brachial-plexus-guide && ls /tmp/workspace/
~/brachial-plexus-guide/build_pdf.py
"""
Build an illustrated PDF guide on brachial plexus nerve injuries.
Uses reportlab for layout and PIL/requests for image fetching.
"""
import requests
import io
import os
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, Image, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate
from reportlab.graphics.shapes import Drawing, Rect, String, Line
from reportlab.graphics import renderPDF
from PIL import Image as PILImage
OUTPUT = "/tmp/workspace/brachial-plexus-guide/Brachial_Plexus_Nerve_Injuries_Guide.pdf"
# ── Color palette ──────────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1A3A5C")
TEAL = colors.HexColor("#1B7A8E")
AMBER = colors.HexColor("#E8A020")
LIGHT_BG= colors.HexColor("#EFF6FB")
WHITE = colors.white
GREY = colors.HexColor("#5A6472")
RED_BOX = colors.HexColor("#C0392B")
GREEN = colors.HexColor("#1E8449")
ORANGE = colors.HexColor("#D35400")
PAGE_W, PAGE_H = A4
MARGIN = 2.0 * cm
# ── Styles ─────────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def make_style(name, parent='Normal', **kwargs):
return ParagraphStyle(name, parent=styles[parent], **kwargs)
title_style = make_style('MainTitle',
fontSize=26, textColor=WHITE, leading=32, alignment=TA_CENTER,
fontName='Helvetica-Bold', spaceAfter=4)
subtitle_style = make_style('SubTitle',
fontSize=13, textColor=colors.HexColor("#B8D4E8"), leading=16,
alignment=TA_CENTER, fontName='Helvetica', spaceAfter=0)
h1 = make_style('H1',
fontSize=16, textColor=WHITE, leading=20, fontName='Helvetica-Bold',
spaceAfter=4, spaceBefore=0)
h2 = make_style('H2',
fontSize=13, textColor=NAVY, leading=17, fontName='Helvetica-Bold',
spaceAfter=6, spaceBefore=10)
h3 = make_style('H3',
fontSize=11, textColor=TEAL, leading=14, fontName='Helvetica-Bold',
spaceAfter=4, spaceBefore=8)
body = make_style('Body', fontSize=9.5, leading=14, textColor=colors.black,
alignment=TA_JUSTIFY, fontName='Helvetica', spaceAfter=4)
body_sm = make_style('BodySm', fontSize=8.5, leading=12, textColor=GREY,
fontName='Helvetica', spaceAfter=2)
bullet = make_style('Bullet', fontSize=9.5, leading=13, textColor=colors.black,
leftIndent=14, bulletIndent=4, fontName='Helvetica', spaceAfter=2)
caption = make_style('Caption', fontSize=8, leading=10, textColor=GREY,
alignment=TA_CENTER, fontName='Helvetica-Oblique', spaceAfter=6)
callout = make_style('Callout', fontSize=10, leading=14, textColor=NAVY,
fontName='Helvetica-Bold', alignment=TA_LEFT, spaceAfter=0)
table_header = make_style('TH', fontSize=9, textColor=WHITE,
fontName='Helvetica-Bold', alignment=TA_CENTER, leading=12)
table_cell = make_style('TC', fontSize=8.5, textColor=colors.black,
fontName='Helvetica', alignment=TA_LEFT, leading=12)
# ── Image fetcher ──────────────────────────────────────────────────────────────
def fetch_img(url, width, max_height=None):
"""Download image, return reportlab Image flowable."""
try:
r = requests.get(url, timeout=15)
r.raise_for_status()
pil = PILImage.open(io.BytesIO(r.content))
w_px, h_px = pil.size
aspect = h_px / w_px
height = width * aspect
if max_height and height > max_height:
height = max_height
width = height / aspect
pil.save("/tmp/_tmpimg.png")
img = Image("/tmp/_tmpimg.png", width=width, height=height)
return img
except Exception as e:
print(f"Image fetch failed ({url}): {e}")
return None
# ── Colored section header builder ────────────────────────────────────────────
def section_header(title, bg=NAVY, width=PAGE_W - 2*MARGIN):
data = [[Paragraph(title, h1)]]
t = Table(data, colWidths=[width])
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), bg),
('TOPPADDING', (0,0), (-1,-1), 7),
('BOTTOMPADDING', (0,0), (-1,-1), 7),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
('ROWBACKGROUNDS', (0,0), (-1,-1), [bg]),
]))
return t
def callout_box(title, text, bg=LIGHT_BG, border=TEAL):
title_p = Paragraph(f"<b>{title}</b>", make_style('CBTitle', fontSize=10,
textColor=border, fontName='Helvetica-Bold', leading=13))
body_p = Paragraph(text, make_style('CBBody', fontSize=9, leading=13,
fontName='Helvetica', textColor=colors.black))
data = [[title_p], [body_p]]
t = Table(data, colWidths=[PAGE_W - 2*MARGIN - 2])
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), bg),
('BOX', (0,0), (-1,-1), 1.5, border),
('TOPPADDING', (0,0), (-1,-1), 6),
('BOTTOMPADDING', (0,0), (-1,-1), 6),
('LEFTPADDING', (0,0), (-1,-1), 10),
('RIGHTPADDING', (0,0), (-1,-1), 10),
]))
return t
# ── Build document ─────────────────────────────────────────────────────────────
story = []
CONTENT_W = PAGE_W - 2*MARGIN
# ========== COVER PAGE ==========================================================
def cover_page():
# Background banner table
banner_data = [[
Paragraph("BRACHIAL PLEXUS", title_style),
], [
Paragraph("NERVE INJURIES", title_style),
], [
Paragraph("A Comprehensive Illustrated Guide", subtitle_style),
]]
banner = Table(banner_data, colWidths=[CONTENT_W])
banner.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), NAVY),
('TOPPADDING', (0,0), (0,0), 24),
('BOTTOMPADDING', (0,0), (-1,0), 2),
('BOTTOMPADDING', (0,1), (-1,1), 2),
('BOTTOMPADDING', (0,2), (-1,2), 24),
('LEFTPADDING', (0,0), (-1,-1), 20),
('RIGHTPADDING', (0,0), (-1,-1), 20),
]))
story.append(banner)
story.append(Spacer(1, 10))
# Cover image
img = fetch_img("https://cdn.orris.care/cdss_images/627d8843242852eb2b3b5ee250ed223510a4154370c2f1fe0ed7db2cb380ce6b.png",
width=CONTENT_W, max_height=11*cm)
if img:
story.append(img)
story.append(Paragraph("Brachial Plexus - Roots, Trunks, Divisions, Cords and Terminal Branches\n(Miller's Review of Orthopaedics)", caption))
story.append(Spacer(1, 10))
# Cover summary box
summary = (
"This guide covers the anatomy, classification, clinical presentations, "
"imaging, and management of brachial plexus nerve injuries. "
"Content drawn from Gray's Anatomy for Students, Campbell's Operative "
"Orthopaedics 15e, Bradley & Daroff's Neurology, Grainger & Allison's "
"Diagnostic Radiology, and Miller's Review of Orthopaedics."
)
story.append(callout_box("About This Guide", summary, bg=LIGHT_BG, border=TEAL))
story.append(Spacer(1, 8))
# Contents list
toc_data = [
[Paragraph("<b>Section</b>", table_header), Paragraph("<b>Page</b>", table_header)],
[Paragraph("1. Anatomy of the Brachial Plexus", table_cell), Paragraph("2", table_cell)],
[Paragraph("2. Mechanisms & Classification of Injury", table_cell), Paragraph("3", table_cell)],
[Paragraph("3. Clinical Syndromes", table_cell), Paragraph("4", table_cell)],
[Paragraph("4. Associated Injuries & Complications", table_cell), Paragraph("5", table_cell)],
[Paragraph("5. Diagnosis & Imaging", table_cell), Paragraph("6", table_cell)],
[Paragraph("6. Management", table_cell), Paragraph("7", table_cell)],
[Paragraph("7. Prognosis", table_cell), Paragraph("8", table_cell)],
]
toc = Table(toc_data, colWidths=[CONTENT_W-2*cm, 2*cm])
toc.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), NAVY),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BG]),
('BOX', (0,0), (-1,-1), 0.5, NAVY),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.HexColor("#CCCCCC")),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 8),
]))
story.append(toc)
story.append(PageBreak())
cover_page()
# ========== SECTION 1: ANATOMY ==================================================
story.append(section_header("1. Anatomy of the Brachial Plexus", bg=NAVY))
story.append(Spacer(1, 8))
story.append(Paragraph(
"The brachial plexus is a somatic nerve network formed by the anterior rami of "
"<b>C5, C6, C7, C8, and T1</b>. It originates in the neck, passes over the first "
"rib, and enters the axilla. All major nerves innervating the upper limb arise "
"from this plexus, mostly from its cord level.",
body))
story.append(Spacer(1, 6))
# Two-column: schematic + anatomical image
img_schematic = fetch_img(
"https://cdn.orris.care/cdss_images/62ef9714975a8ea1509371bbecc736c66c2fdd7a02df72fb8141a511a0a08af2.png",
width=(CONTENT_W/2) - 5, max_height=7*cm)
img_anatomy = fetch_img(
"https://cdn.orris.care/cdss_images/42e3982ca738d0e6877cc67f524d1fbfcf9d635fdfed6e0372f6519623416ef7.png",
width=(CONTENT_W/2) - 5, max_height=7*cm)
if img_schematic and img_anatomy:
img_table = Table([[img_schematic, img_anatomy]], colWidths=[(CONTENT_W/2)-3, (CONTENT_W/2)-3])
img_table.setStyle(TableStyle([('ALIGN', (0,0), (-1,-1), 'CENTER'), ('VALIGN', (0,0), (-1,-1), 'TOP')]))
story.append(img_table)
story.append(Table([[
Paragraph("Fig 1a. Schematic: Roots → Trunks → Divisions → Cords → Terminal Nerves\n(Gray's Anatomy for Students)", caption),
Paragraph("Fig 1b. Anatomical illustration: Brachial plexus with surrounding muscles and vessels\n(Gray's Anatomy for Students)", caption)
]], colWidths=[(CONTENT_W/2)-3, (CONTENT_W/2)-3]))
story.append(Spacer(1, 8))
# Anatomy table
story.append(Paragraph("Structural Components", h2))
anatomy_data = [
[Paragraph("<b>Level</b>", table_header),
Paragraph("<b>Components</b>", table_header),
Paragraph("<b>Key Notes</b>", table_header)],
[Paragraph("Roots", table_cell),
Paragraph("C5, C6, C7, C8, T1\n(anterior rami)", table_cell),
Paragraph("Pass between anterior & middle scalene muscles", table_cell)],
[Paragraph("Trunks", table_cell),
Paragraph("Superior (C5-C6)\nMiddle (C7)\nInferior (C8-T1)", table_cell),
Paragraph("Cross the base of posterior triangle of the neck", table_cell)],
[Paragraph("Divisions", table_cell),
Paragraph("Anterior & posterior\n(6 total — 2 per trunk)", table_cell),
Paragraph("No terminal branches at this level", table_cell)],
[Paragraph("Cords", table_cell),
Paragraph("Lateral, Medial, Posterior", table_cell),
Paragraph("Named by relation to 2nd part of axillary artery", table_cell)],
[Paragraph("Terminal Branches", table_cell),
Paragraph("Musculocutaneous, Axillary,\nRadial, Median, Ulnar", table_cell),
Paragraph("Arise from cords; supply entire upper limb", table_cell)],
]
at = Table(anatomy_data, colWidths=[CONTENT_W*0.18, CONTENT_W*0.38, CONTENT_W*0.44])
at.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), TEAL),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BG]),
('BOX', (0,0), (-1,-1), 0.5, TEAL),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.HexColor("#CCDDEE")),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 6),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(at)
story.append(Spacer(1, 8))
# Important branches
story.append(Paragraph("Key Pre-Divisional Branches", h3))
pre_div = [
("Dorsal scapular nerve", "C5", "Rhomboids + levator scapulae"),
("Long thoracic nerve", "C5-C7", "Serratus anterior (palsy = winging of scapula)"),
("Nerve to subclavius", "C5-C6", "Subclavius muscle"),
("Suprascapular nerve", "C5-C6", "Supraspinatus + infraspinatus"),
]
branch_data = [[Paragraph("<b>Nerve</b>", table_header),
Paragraph("<b>Roots</b>", table_header),
Paragraph("<b>Muscle(s) Supplied</b>", table_header)]]
for n, r, m in pre_div:
branch_data.append([Paragraph(n, table_cell), Paragraph(r, table_cell), Paragraph(m, table_cell)])
bt = Table(branch_data, colWidths=[CONTENT_W*0.38, CONTENT_W*0.15, CONTENT_W*0.47])
bt.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), GREY),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BG]),
('BOX', (0,0), (-1,-1), 0.5, GREY),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.HexColor("#DDDDDD")),
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 6),
]))
story.append(bt)
story.append(PageBreak())
# ========== SECTION 2: MECHANISMS & CLASSIFICATION ==============================
story.append(section_header("2. Mechanisms & Classification of Injury", bg=TEAL))
story.append(Spacer(1, 8))
story.append(Paragraph("Mechanisms of Injury", h2))
story.append(Paragraph(
"Brachial plexus injuries occur predominantly through <b>traction and avulsion forces</b>. "
"Penetrating injuries (stab wounds, gunshots) and compression (hematoma, tumour) account for "
"a smaller proportion. Motor vehicle accidents (especially motorcyclists), difficult childbirths "
"(shoulder dystocia), and occupational falls are the most common causes.",
body))
story.append(Spacer(1, 6))
mech_data = [
[Paragraph("<b>Mechanism</b>", table_header),
Paragraph("<b>Force Direction</b>", table_header),
Paragraph("<b>Structures at Risk</b>", table_header)],
[Paragraph("Shoulder depression + head deviation\n(e.g., motorcycle crash)", table_cell),
Paragraph("Upper trunk stretch", table_cell),
Paragraph("C5-C6 → Upper trunk (Erb palsy)", table_cell)],
[Paragraph("Forcible arm hyperabduction over head\n(e.g., catching an overhead support)", table_cell),
Paragraph("Lower trunk stretch", table_cell),
Paragraph("C8-T1 → Lower trunk (Klumpke palsy)", table_cell)],
[Paragraph("Violent neck-shoulder separation\n(birth traction, high-speed RTA)", table_cell),
Paragraph("Root avulsion", table_cell),
Paragraph("Preganglionic root avulsion (irreparable)", table_cell)],
[Paragraph("Penetrating trauma\n(knife, gunshot)", table_cell),
Paragraph("Direct laceration / shock wave", table_cell),
Paragraph("Any cord or trunk level; poor recovery", table_cell)],
[Paragraph("Hematoma / compression\n(bleeding disorder, central line)", table_cell),
Paragraph("External pressure", table_cell),
Paragraph("Usually neurapraxia — good prognosis when resorbed", table_cell)],
]
mt = Table(mech_data, colWidths=[CONTENT_W*0.32, CONTENT_W*0.26, CONTENT_W*0.42])
mt.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), TEAL),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BG]),
('BOX', (0,0), (-1,-1), 0.5, TEAL),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.HexColor("#CCDDEE")),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 6),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(mt)
story.append(Spacer(1, 10))
story.append(Paragraph("Seddon / Sunderland Classification", h2))
seddon_data = [
[Paragraph("<b>Seddon</b>", table_header),
Paragraph("<b>Sunderland</b>", table_header),
Paragraph("<b>Pathology</b>", table_header),
Paragraph("<b>Prognosis</b>", table_header)],
[Paragraph("Neurapraxia", table_cell),
Paragraph("Grade I", table_cell),
Paragraph("Focal conduction block; axons intact", table_cell),
Paragraph("Full recovery weeks-months", table_cell)],
[Paragraph("Axonotmesis", table_cell),
Paragraph("Grade II-IV", table_cell),
Paragraph("Axon disrupted; endoneurium ± perineurium intact", table_cell),
Paragraph("Partial to good recovery via Wallerian regeneration", table_cell)],
[Paragraph("Neurotmesis", table_cell),
Paragraph("Grade V", table_cell),
Paragraph("Complete nerve transection (all layers)", table_cell),
Paragraph("No spontaneous recovery; surgical repair needed", table_cell)],
[Paragraph("Root Avulsion", table_cell),
Paragraph("Grade V\n(preganglionic)", table_cell),
Paragraph("Root torn from spinal cord; no continuity", table_cell),
Paragraph("Irreparable; nerve transfer only option", table_cell)],
]
st = Table(seddon_data, colWidths=[CONTENT_W*0.2, CONTENT_W*0.16, CONTENT_W*0.38, CONTENT_W*0.26])
st.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), NAVY),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BG]),
('BOX', (0,0), (-1,-1), 0.5, NAVY),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.HexColor("#CCCCCC")),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 6),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(st)
story.append(Spacer(1, 8))
story.append(callout_box(
"Preganglionic vs. Postganglionic — Key Distinction",
"Preganglionic injuries (root avulsion from spinal cord) are <b>irreparable by primary nerve repair</b> "
"because the nerve cell body in the dorsal root ganglion is separated from the cord. Only nerve transfers "
"(e.g., intercostal, phrenic, contralateral C7) can restore some function. "
"Postganglionic injuries retain the cell body and may regenerate or be repaired by grafting. "
"75% of traumatic brachial plexus injuries involve root avulsion (Grainger & Allison's Diagnostic Radiology).",
bg=colors.HexColor("#FFF3E0"), border=AMBER))
story.append(PageBreak())
# ========== SECTION 3: CLINICAL SYNDROMES =======================================
story.append(section_header("3. Clinical Syndromes", bg=colors.HexColor("#2E4057")))
story.append(Spacer(1, 8))
# ERB PALSY
story.append(Paragraph("3.1 Erb Palsy (Upper Trunk Injury — C5, C6)", h2))
story.append(Paragraph(
"The most common brachial plexus injury, accounting for ~20x more cases than Klumpke palsy. "
"Caused by <b>forcible increase of the neck-shoulder angle</b> — either during difficult "
"vaginal delivery (shoulder dystocia, pulling on the infant's head) or from a fall compressing "
"the shoulder downward (motorcycle crash, fall of load on shoulder).",
body))
story.append(Spacer(1, 4))
erb_features = [
"<b>Posture:</b> Arm adducted and internally rotated, forearm pronated, wrist flexed — classic \"waiter's tip\" position",
"<b>Motor loss:</b> Deltoid, supraspinatus, infraspinatus, biceps, brachioradialis (C5-C6 muscles)",
"<b>Reflex loss:</b> Biceps reflex absent on affected side; asymmetric Moro reflex in neonates",
"<b>Sensory loss:</b> Lateral arm and forearm (C5-C6 dermatomes)",
"<b>Spared:</b> Finger flexion and extension (C7-T1 intact)",
"<b>Key prognostic sign:</b> Return of biceps function within 2-4 weeks — indicates favorable outcome",
]
for f in erb_features:
story.append(Paragraph(f"• {f}", bullet))
story.append(Spacer(1, 4))
story.append(callout_box(
"Clinical Pearl",
"Biceps function is the single most important prognostic indicator in brachial plexus birth palsy. "
"Over 90% of Erb palsy cases show resolution by 3 months of age. "
"Surgical reconstruction should be considered in infants with no spontaneous recovery by 3 months.",
bg=colors.HexColor("#E8F8F5"), border=GREEN))
story.append(Spacer(1, 10))
# KLUMPKE PALSY
story.append(Paragraph("3.2 Klumpke Palsy (Lower Trunk Injury — C8, T1)", h2))
story.append(Paragraph(
"Rare — affects the lower trunk by <b>forcible hyperabduction of the arm over the head</b> "
"(e.g., a person grabbing an overhead support while falling). Also seen in birth injuries when "
"the arm is raised above the head during delivery.",
body))
story.append(Spacer(1, 4))
klumpke_features = [
"<b>Posture:</b> Claw hand (intrinsic minus hand) — MCP hyperextension, IP flexion",
"<b>Motor loss:</b> All intrinsic hand muscles (interossei, lumbricals, thenar, hypothenar)",
"<b>Reflex loss:</b> Finger grasp reflex absent (neonates)",
"<b>Sensory loss:</b> Medial forearm and hand (C8-T1 dermatomes)",
"<b>Horner syndrome:</b> Ptosis, miosis, anhidrosis — if T1 sympathetic fibers involved",
"<b>Spared:</b> Shoulder and elbow function",
]
for f in klumpke_features:
story.append(Paragraph(f"• {f}", bullet))
story.append(Spacer(1, 10))
# COMPLETE PLEXOPATHY
story.append(Paragraph("3.3 Complete Brachial Plexopathy (C5-T1)", h2))
story.append(Paragraph(
"The rarest and most severe form — entire plexus involved (C5-T1). Results in "
"<b>complete flaccid paralysis of the entire upper limb</b> with global sensory loss. "
"Often associated with high-energy trauma and root avulsions. May accompany Horner syndrome, "
"diaphragmatic paralysis (phrenic nerve C3-C5), and cervical cord injury.",
body))
story.append(Spacer(1, 8))
# Comparison table
story.append(Paragraph("Comparison of Clinical Syndromes", h3))
comp_data = [
[Paragraph("<b>Feature</b>", table_header),
Paragraph("<b>Erb Palsy (C5-C6)</b>", table_header),
Paragraph("<b>Klumpke Palsy (C8-T1)</b>", table_header),
Paragraph("<b>Complete (C5-T1)</b>", table_header)],
[Paragraph("Frequency", table_cell),
Paragraph("Most common", table_cell),
Paragraph("Rare", table_cell),
Paragraph("Least common", table_cell)],
[Paragraph("Mechanism", table_cell),
Paragraph("Neck-shoulder separation", table_cell),
Paragraph("Arm hyperabduction", table_cell),
Paragraph("High-energy trauma", table_cell)],
[Paragraph("Deformity", table_cell),
Paragraph("Waiter's tip", table_cell),
Paragraph("Claw hand", table_cell),
Paragraph("Flail arm", table_cell)],
[Paragraph("Shoulder", table_cell),
Paragraph("Affected", table_cell),
Paragraph("Normal", table_cell),
Paragraph("Affected", table_cell)],
[Paragraph("Hand intrinsics", table_cell),
Paragraph("Spared", table_cell),
Paragraph("Paralysed", table_cell),
Paragraph("Paralysed", table_cell)],
[Paragraph("Horner syndrome", table_cell),
Paragraph("No", table_cell),
Paragraph("Yes (if T1)", table_cell),
Paragraph("Yes", table_cell)],
]
ct = Table(comp_data, colWidths=[CONTENT_W*0.22, CONTENT_W*0.26, CONTENT_W*0.26, CONTENT_W*0.26])
ct.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), colors.HexColor("#2E4057")),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BG]),
('BOX', (0,0), (-1,-1), 0.5, NAVY),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.HexColor("#CCCCCC")),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 6),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(ct)
story.append(PageBreak())
# ========== SECTION 4: ASSOCIATED INJURIES ======================================
story.append(section_header("4. Associated Injuries & Complications", bg=RED_BOX))
story.append(Spacer(1, 8))
story.append(Paragraph(
"Brachial plexus injuries — particularly high-energy avulsions — rarely occur in isolation. "
"A systematic search for associated injuries is mandatory.",
body))
story.append(Spacer(1, 6))
assoc_items = [
("<b>Shoulder dislocation / proximal humerus fracture</b>",
"Infraclavicular plexus injury — cords at risk. Posterior shoulder dislocation occurs in up to "
"8% of brachial plexus birth palsy infants — screen with ultrasound."),
("<b>Clavicle fracture</b>",
"Occurs in up to 10-20% of birth-related brachial plexus palsy cases. "
"Infraclavicular hematoma can compress the plexus secondarily."),
("<b>Cervical spine injury</b>",
"High-energy polytrauma: brachial plexus avulsion may be accompanied by diffuse cord oedema. "
"Do NOT mistake cord oedema from avulsion for a direct cord injury with cervical fracture."),
("<b>Horner syndrome</b>",
"Ptosis + miosis + anhidrosis indicates sympathetic chain involvement (T1 root). "
"Signals lower plexus or complete injury; associated with worse prognosis."),
("<b>Diaphragmatic paralysis</b>",
"Phrenic nerve (C3-C5) injury: rare, suggests high cervical root involvement. "
"Presents as respiratory distress, particularly in neonates."),
("<b>Causalgia / Complex Regional Pain Syndrome</b>",
"Intense burning pain after partial nerve injury. Can commence immediately or weeks after injury "
"once the skin wound has healed. Requires specialist pain management."),
("<b>Vascular injury</b>",
"Subclavian artery injury associated with supraclavicular plexus trauma. "
"Scapulothoracic dissociation (complete brachial plexus avulsion + vascular disruption) is limb-threatening."),
]
for title, text in assoc_items:
row_data = [[Paragraph(title, make_style('AT', fontSize=9.5, fontName='Helvetica-Bold',
textColor=NAVY, leading=13)),
Paragraph(text, table_cell)]]
rt = Table(row_data, colWidths=[CONTENT_W*0.33, CONTENT_W*0.67])
rt.setStyle(TableStyle([
('BACKGROUND', (0,0), (0,0), LIGHT_BG),
('BOX', (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 8),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(rt)
story.append(Spacer(1, 3))
story.append(PageBreak())
# ========== SECTION 5: DIAGNOSIS & IMAGING ======================================
story.append(section_header("5. Diagnosis & Imaging", bg=colors.HexColor("#4A235A")))
story.append(Spacer(1, 8))
story.append(Paragraph("Clinical Assessment", h2))
story.append(Paragraph(
"Diagnosis is based on a careful neurological examination: motor testing of each root level, "
"sensory mapping, reflex assessment, and screening for Horner syndrome. In neonates, "
"<b>serial examinations</b> are required as no single baseline investigation reliably predicts "
"recovery. Electrodiagnostic testing (EMG/NCS) and imaging may be used in selected cases.",
body))
story.append(Spacer(1, 6))
story.append(Paragraph("Imaging Modalities", h2))
imaging_data = [
[Paragraph("<b>Modality</b>", table_header),
Paragraph("<b>Best For</b>", table_header),
Paragraph("<b>Key Findings</b>", table_header)],
[Paragraph("Plain X-ray", table_cell),
Paragraph("Fractures, cervical rib, skeletal integrity", table_cell),
Paragraph("Clavicle/humeral fracture, cervical rib at C7, scapulothoracic dissociation", table_cell)],
[Paragraph("MRI (T2 myelogram)", table_cell),
Paragraph("Gold standard for root avulsion\n(replaced CT myelography)", table_cell),
Paragraph("Traumatic meningocele (dural tear + CSF leak = complete root avulsion); "
"diffuse cord oedema; intact roots indicate more distal injury", table_cell)],
[Paragraph("CT Myelography", table_cell),
Paragraph("When MRI unavailable / contraindicated", table_cell),
Paragraph("Pseudomeningocele confirms root avulsion; less soft tissue detail than MRI", table_cell)],
[Paragraph("Ultrasound", table_cell),
Paragraph("Neonatal posterior shoulder dislocation\nReal-time nerve assessment", table_cell),
Paragraph("Screen for posterior shoulder dislocation in BPBP; identify interscalene masses", table_cell)],
[Paragraph("EMG / NCS", table_cell),
Paragraph("Localize level, assess severity,\nmonitor recovery", table_cell),
Paragraph("Fibrillations (axon loss); conduction block (neurapraxia); may be negative up to 4 weeks post-injury", table_cell)],
]
imgt = Table(imaging_data, colWidths=[CONTENT_W*0.2, CONTENT_W*0.3, CONTENT_W*0.5])
imgt.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), colors.HexColor("#4A235A")),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BG]),
('BOX', (0,0), (-1,-1), 0.5, colors.HexColor("#4A235A")),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.HexColor("#CCCCCC")),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 6),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(imgt)
story.append(Spacer(1, 8))
# MRI image
img_mri = fetch_img(
"https://cdn.orris.care/cdss_images/875498a79e6532fcf2d6bef39d726c8e0165bcee6e4f629293b63a6d1ebbe6a6.png",
width=8*cm, max_height=9*cm)
if img_mri:
mri_tbl = Table([[img_mri]], colWidths=[8*cm])
mri_tbl.setStyle(TableStyle([('ALIGN', (0,0), (-1,-1), 'CENTER')]))
story.append(mri_tbl)
story.append(Paragraph(
"Fig 5. Coronal T2-weighted MRI myelogram: Brachial plexus avulsion at C8-T1 (left) "
"with traumatic meningoceles (arrows). Note: a complete root avulsion is accompanied by a "
"dural tear and CSF leakage, forming a traumatic meningocele.\n(Grainger & Allison's Diagnostic Radiology)",
caption))
story.append(Spacer(1, 6))
story.append(callout_box(
"Preganglionic Indicator on MRI",
"The presence of a <b>traumatic meningocele</b> (CSF-filled sac at the neural foramen on T2 MRI) "
"is a reliable indicator of complete nerve root avulsion. This is a preganglionic injury — "
"nerve repair or grafting cannot restore function. <b>Nerve transfer surgery</b> is the only "
"reconstructive option.",
bg=colors.HexColor("#F4ECF7"), border=colors.HexColor("#4A235A")))
story.append(PageBreak())
# ========== SECTION 6: MANAGEMENT ===============================================
story.append(section_header("6. Management", bg=GREEN))
story.append(Spacer(1, 8))
story.append(Paragraph(
"Management is tailored to injury severity, level, patient age, and time from injury. "
"A <b>multidisciplinary approach</b> (neurosurgery, orthopaedics, physiotherapy, occupational "
"therapy, pain management) is essential, ideally at a specialist centre.",
body))
story.append(Spacer(1, 6))
story.append(Paragraph("Conservative (Non-Surgical) Management", h2))
consv = [
"<b>Early range-of-motion exercises</b> — prevent joint contractures and maintain muscle length",
"<b>Splinting</b> — maintain functional position while recovery is awaited",
"<b>Physiotherapy & occupational therapy</b> — begin within 1 month of age for birth injuries",
"<b>Pain management</b> — causalgia/CRPS requires multidisciplinary pain input; neuropathic agents (gabapentin, amitriptyline)",
"<b>Serial neurological assessment</b> — identify spontaneous recovery trajectory; key decision window at 3 months",
"<b>Botulinum toxin</b> — considered for muscle imbalance/spasticity in birth palsy (evidence growing)",
]
for c in consv:
story.append(Paragraph(f"• {c}", bullet))
story.append(Spacer(1, 8))
story.append(Paragraph("Surgical Management", h2))
story.append(Paragraph(
"Surgical reconstruction should be considered when there is <b>no evidence of spontaneous "
"recovery at 3 months</b> (for birth injuries) or when nerve continuity is disrupted (for "
"traumatic injuries). Earlier surgery is generally associated with better outcomes.",
body))
story.append(Spacer(1, 4))
surg_data = [
[Paragraph("<b>Procedure</b>", table_header),
Paragraph("<b>Indication</b>", table_header),
Paragraph("<b>Notes</b>", table_header)],
[Paragraph("Neurolysis", table_cell),
Paragraph("Scar entrapment, neurapraxia", table_cell),
Paragraph("Decompression of intact nerve in scar tissue", table_cell)],
[Paragraph("Primary nerve repair\n(end-to-end)", table_cell),
Paragraph("Sharply transected nerve with minimal gap", table_cell),
Paragraph("Best results in early, clean lacerations", table_cell)],
[Paragraph("Nerve grafting\n(sural nerve graft)", table_cell),
Paragraph("Postganglionic injury with gap\n(neurotmesis)", table_cell),
Paragraph("Sural nerve most common donor; results depend on length & delay", table_cell)],
[Paragraph("Nerve transfer\n(neurotization)", table_cell),
Paragraph("Root avulsion (preganglionic)\n— most common indication", table_cell),
Paragraph("Intercostal, phrenic, spinal accessory, contralateral C7, Oberlin transfer (ulnar → biceps)", table_cell)],
[Paragraph("Tendon transfer", table_cell),
Paragraph("Late reconstruction after partial recovery", table_cell),
Paragraph("Rebalance joint function using adjacent functional muscles", table_cell)],
[Paragraph("Shoulder stabilisation\n(anterior release / Botox)", table_cell),
Paragraph("Internal rotation contracture\nin birth palsy", table_cell),
Paragraph("Subscapularis release (proximal or distal) to prevent posterior dislocation", table_cell)],
]
surgt = Table(surg_data, colWidths=[CONTENT_W*0.24, CONTENT_W*0.3, CONTENT_W*0.46])
surgt.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), GREEN),
('ROWBACKGROUNDS', (0,1), (-1,-1), [WHITE, LIGHT_BG]),
('BOX', (0,0), (-1,-1), 0.5, GREEN),
('INNERGRID', (0,0), (-1,-1), 0.25, colors.HexColor("#CCDDCC")),
('TOPPADDING', (0,0), (-1,-1), 5),
('BOTTOMPADDING', (0,0), (-1,-1), 5),
('LEFTPADDING', (0,0), (-1,-1), 6),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
]))
story.append(surgt)
story.append(PageBreak())
# ========== SECTION 7: PROGNOSIS & SUMMARY ======================================
story.append(section_header("7. Prognosis & Key Clinical Pearls", bg=ORANGE))
story.append(Spacer(1, 8))
story.append(Paragraph("Prognostic Factors", h2))
prog_items = [
("<b>Rate of early improvement</b>",
"Evidence of improved arm function within 2-4 weeks (esp. biceps in Erb palsy) predicts full recovery."),
("<b>Type of injury</b>",
"Neurapraxia → full recovery. Axonotmesis → partial-full recovery. Neurotmesis / avulsion → no spontaneous recovery."),
("<b>Level</b>",
"Preganglionic (avulsion) is worse than postganglionic. Upper plexus injuries generally have better outcomes than lower."),
("<b>Completeness</b>",
"Partial injuries recover better than complete plexopathy."),
("<b>Age</b>",
"Birth palsy recovers better than adult traumatic injury due to neuroplasticity. >90% Erb palsy resolve by 3 months."),
("<b>Time to surgery</b>",
"Earlier nerve reconstruction is associated with superior outcomes."),
("<b>Penetrating vs. closed</b>",
"Knife / bullet wounds: speed and extent of recovery are poor."),
]
for title, text in prog_items:
prow = [[Paragraph(title, make_style('PT', fontSize=9.5, fontName='Helvetica-Bold',
textColor=ORANGE, leading=13)),
Paragraph(text, table_cell)]]
pt = Table(prow, colWidths=[CONTENT_W*0.28, CONTENT_W*0.72])
pt.setStyle(TableStyle([
('TOPPADDING', (0,0), (-1,-1), 4),
('BOTTOMPADDING', (0,0), (-1,-1), 4),
('LEFTPADDING', (0,0), (-1,-1), 6),
('LINEBELOW', (0,0), (-1,0), 0.25, colors.HexColor("#DDDDDD")),
('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(pt)
story.append(Spacer(1, 10))
story.append(Paragraph("Key Clinical Pearls Summary", h2))
pearls = [
"Upper plexus injuries (Erb palsy) are ~20x more common than lower (Klumpke palsy).",
"75% of traumatic brachial plexus injuries involve root avulsion — which is irreparable by direct nerve repair.",
"Traumatic meningocele on MRI = diagnostic of complete nerve root avulsion (preganglionic injury).",
"Horner syndrome indicates T1 root involvement and signals a more complete, serious injury.",
"Deficits persist in approximately 25% of birth palsy patients despite optimal management.",
"Thoracic outlet syndrome presents with lower trunk signs (C8-T1) and is frequently overdiagnosed.",
"EMG may be falsely normal for up to 4 weeks after axonal injury — do not rely on early EMG to exclude injury.",
"Shoulder internal rotation contracture in birth palsy requires early physiotherapy ± Botox ± surgery to prevent posterior shoulder dislocation.",
]
for p in pearls:
story.append(Paragraph(f"• {p}", bullet))
story.append(Spacer(1, 10))
# Final anatomical diagram
story.append(Paragraph("Reference: Full Brachial Plexus Anatomy", h2))
img_full = fetch_img(
"https://cdn.orris.care/cdss_images/GLGCA_4906546_1765807530631_5d820eab-0455-43fe-b3c8-11e99b8aaed7.png",
width=CONTENT_W, max_height=10*cm)
if img_full:
story.append(img_full)
story.append(Paragraph(
"Fig 7. Brachial plexus with surrounding anatomy: nerve roots, trunks, major terminal nerves, "
"subclavian artery, axillary artery, and adjacent muscles.",
caption))
story.append(Spacer(1, 10))
story.append(HRFlowable(width=CONTENT_W, thickness=1, color=GREY))
story.append(Spacer(1, 4))
story.append(Paragraph(
"<i>Sources: Gray's Anatomy for Students | Campbell's Operative Orthopaedics 15e (2026) | "
"Bradley & Daroff's Neurology in Clinical Practice | Grainger & Allison's Diagnostic Radiology | "
"Miller's Review of Orthopaedics 9e | S. Das Manual on Clinical Surgery 13e</i>",
body_sm))
# ========== BUILD PDF =============================================================
def add_page_number(canvas, doc):
canvas.saveState()
canvas.setFont('Helvetica', 8)
canvas.setFillColor(GREY)
page_num = canvas.getPageNumber()
canvas.drawCentredString(PAGE_W/2, 1.2*cm, f"Brachial Plexus Nerve Injuries Guide | Page {page_num}")
canvas.restoreState()
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=MARGIN, bottomMargin=1.8*cm,
title="Brachial Plexus Nerve Injuries — Illustrated Guide",
author="Orris Medical",
subject="Brachial plexus anatomy and nerve injury"
)
doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print(f"PDF built: {OUTPUT}")
cd /tmp/workspace/brachial-plexus-guide && python build_pdf.py 2>&1
ls -lh /tmp/workspace/brachial-plexus-guide/
Brachial Plexus Nerve Injuries Guide
PDF Document · PDF
| Section | Content |
|---|---|
| Cover | Full-color title banner + schematic plexus diagram + table of contents |
| 1. Anatomy | Two-column illustrated spread (Gray's schematic + anatomical view), components table (Roots → Trunks → Divisions → Cords → Branches), pre-divisional branches table |
| 2. Mechanisms & Classification | Traction/avulsion/penetrating causes table; full Seddon/Sunderland classification; callout on preganglionic vs. postganglionic distinction |
| 3. Clinical Syndromes | Erb palsy (C5-C6), Klumpke palsy (C8-T1), complete plexopathy — with features, postures, reflexes, and 3-syndrome comparison table |
| 4. Associated Injuries | Shoulder dislocation, clavicle fracture, cervical cord injury, Horner syndrome, diaphragmatic paralysis, causalgia, vascular injury |
| 5. Diagnosis & Imaging | Modality comparison table (X-ray, MRI, CT myelography, US, EMG/NCS) + MRI image of traumatic meningocele from Grainger & Allison |
| 6. Management | Conservative (physio, splinting, Botox) + surgical options table (neurolysis, repair, grafting, nerve transfer, tendon transfer, shoulder release) |
| 7. Prognosis & Pearls | Prognostic factors + 8 key clinical pearls + full reference anatomical illustration |