Explain me brachial plexus block with anatomy as anesthesia pg
| Level | Components | Location |
|---|---|---|
| Roots | C5, C6, C7, C8, T1 | Exit intervertebral foramina |
| Trunks | Superior (C5+C6), Middle (C7), Inferior (C8+T1) | Between anterior & middle scalene muscles |
| Divisions | Anterior & posterior from each trunk (6 total) | Over lateral border of 1st rib, under clavicle |
| Cords | Lateral, Medial, Posterior | Named relative to axillary artery; below clavicle |
| Terminal nerves | Median, Ulnar, Radial, Musculocutaneous, Axillary | Lateral border of pectoralis minor |


| Approach | Anatomical Level Targeted | Surgical Indication |
|---|---|---|
| Interscalene | Roots / upper & middle trunks | Shoulder, proximal humerus |
| Supraclavicular | Distal trunks / proximal divisions | Elbow, forearm, hand ("spinal of the arm") |
| Infraclavicular | Cords | Elbow, forearm, hand; best for catheters |
| Axillary | Terminal nerves | Hand, wrist, forearm distal to elbow |

| Drug | Concentration | Duration | Onset |
|---|---|---|---|
| Ropivacaine | 0.375-0.5% (surgical), 0.2% (analgesia) | 8-12 h | Moderate |
| Bupivacaine | 0.25-0.5% | 8-16 h | Moderate |
| Lidocaine | 1-1.5% (±epi) | 2-4 h | Rapid |
| Mepivacaine | 1-1.5% | 4-6 h | Rapid |
| Complication | Most Common Approach |
|---|---|
| Phrenic nerve palsy | Interscalene (>95%), Supraclavicular (~50%) |
| Pneumothorax | Supraclavicular > Infraclavicular |
| Horner syndrome | Interscalene, Supraclavicular |
| Recurrent laryngeal nerve | Interscalene |
| Vascular puncture | Axillary, Infraclavicular |
| LAST | All (especially axillary - high vascularity) |
| Nerve injury | All approaches |
| Spinal/epidural injection | Interscalene |
| Surgery | Best Approach | Why |
|---|---|---|
| Shoulder arthroplasty / RCR | Interscalene | Targets C5-C6 roots + upper trunk |
| Clavicle ORIF | Interscalene + cervical plexus | Supraclavicular nerve (C3-C4) supplementation needed |
| Shoulder (high-risk lung) | Superior trunk / suprascapular + infraclavicular | Phrenic-sparing |
| Elbow / forearm | Supraclavicular or infraclavicular | Dense block at division/cord level |
| Wrist / hand | Infraclavicular or axillary | Cord / terminal nerve level |
| Catheter for prolonged analgesia | Infraclavicular | Best catheter stability |
| Pediatric or obese arm | Axillary | Superficial, safe |
Okay
Create a summary PDF on block selection by surgery
ls -la /home/daytona/workspace/ 2>/dev/null && mkdir -p /home/daytona/workspace/brachial-plexus-pdf
~/brachial-plexus-pdf/generate_pdf.py
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_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
OUTPUT = "/home/daytona/workspace/brachial-plexus-pdf/Brachial_Plexus_Block_Selection.pdf"
# --- Colours ---
DARK_BLUE = colors.HexColor("#1A3557")
MED_BLUE = colors.HexColor("#2E6DA4")
LIGHT_BLUE = colors.HexColor("#D6E8F7")
ACCENT = colors.HexColor("#E8511A")
PALE_GREY = colors.HexColor("#F4F6F9")
MID_GREY = colors.HexColor("#D0D8E4")
WHITE = colors.white
GREEN_DARK = colors.HexColor("#1A5741")
GREEN_LIGHT = colors.HexColor("#D4EDDA")
AMBER_DARK = colors.HexColor("#7A4F00")
AMBER_LIGHT = colors.HexColor("#FFF3CD")
RED_DARK = colors.HexColor("#7A1A1A")
RED_LIGHT = colors.HexColor("#FADADD")
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=1.8*cm, rightMargin=1.8*cm,
topMargin=2*cm, bottomMargin=2*cm,
title="Brachial Plexus Block Selection",
author="Orris Medical"
)
W = A4[0] - 3.6*cm # usable width
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
TITLE_STYLE = S("Title",
fontSize=20, textColor=WHITE, alignment=TA_CENTER,
fontName="Helvetica-Bold", spaceAfter=4)
SUBTITLE_STYLE = S("Subtitle",
fontSize=11, textColor=LIGHT_BLUE, alignment=TA_CENTER,
fontName="Helvetica", spaceAfter=2)
SECTION_STYLE = S("Section",
fontSize=13, textColor=WHITE, alignment=TA_LEFT,
fontName="Helvetica-Bold", leftIndent=6, spaceAfter=2)
BODY = S("Body",
fontSize=9, textColor=colors.HexColor("#1C1C1C"),
fontName="Helvetica", leading=13, spaceAfter=3)
BOLD_BODY = S("BoldBody",
fontSize=9, textColor=DARK_BLUE,
fontName="Helvetica-Bold", leading=13, spaceAfter=3)
SMALL = S("Small",
fontSize=7.5, textColor=colors.HexColor("#444444"),
fontName="Helvetica", leading=11)
FOOTER = S("Footer",
fontSize=7, textColor=colors.HexColor("#888888"),
fontName="Helvetica-Oblique", alignment=TA_CENTER)
TH = S("TH",
fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=11)
TD = S("TD",
fontSize=8, textColor=colors.HexColor("#1C1C1C"),
fontName="Helvetica", alignment=TA_LEFT, leading=11)
TD_C = S("TDC",
fontSize=8, textColor=colors.HexColor("#1C1C1C"),
fontName="Helvetica", alignment=TA_CENTER, leading=11)
TD_B = S("TDB",
fontSize=8, textColor=DARK_BLUE, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=11)
WARN = S("Warn",
fontSize=7.5, textColor=RED_DARK, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=10)
NOTE = S("Note",
fontSize=7.5, textColor=GREEN_DARK, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=10)
story = []
# ========================================================
# HEADER BANNER
# ========================================================
header_data = [[
Paragraph("BRACHIAL PLEXUS BLOCK SELECTION", TITLE_STYLE),
]]
header_table = Table([[Paragraph("BRACHIAL PLEXUS BLOCK SELECTION", TITLE_STYLE)]], colWidths=[W])
header_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 14),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [6]),
]))
story.append(header_table)
sub_table = Table([[Paragraph("Quick Reference Guide for Anesthesia | Based on Miller's 10e · Morgan & Mikhail 7e · Barash 9e", SUBTITLE_STYLE)]], colWidths=[W])
sub_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
story.append(sub_table)
story.append(Spacer(1, 10))
# ========================================================
# HELPER: section header
# ========================================================
def section_header(text):
t = Table([[Paragraph(text, SECTION_STYLE)]], colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
return t
def mini_header(text, color=DARK_BLUE):
style = S("MH", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=11, leftIndent=4)
t = Table([[Paragraph(text, style)]], colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
return t
def colored_cell(text, style, bg):
t = Table([[Paragraph(text, style)]], colWidths=["100%"])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
]))
return t
# ========================================================
# SECTION 1: ANATOMY OVERVIEW
# ========================================================
story.append(section_header("1. BRACHIAL PLEXUS ANATOMY OVERVIEW"))
story.append(Spacer(1, 6))
# Organisation table
anat_headers = ["Level", "Components", "Location", "Approach Targeting Here"]
anat_rows = [
["Roots", "C5, C6, C7, C8, T1", "Exit intervertebral foramina between C4-T1 vertebrae", "Interscalene"],
["Trunks", "Superior (C5+C6)\nMiddle (C7)\nInferior (C8+T1)", "Between anterior & middle scalene muscles", "Interscalene\n(upper/middle)"],
["Divisions", "Anterior & posterior\nfrom each trunk (6 total)", "Over lateral border of 1st rib,\nunder the clavicle", "Supraclavicular"],
["Cords", "Lateral, Medial, Posterior\n(named relative to axillary artery)", "Below clavicle,\nunder pectoralis minor", "Infraclavicular"],
["Terminal\nNerves", "Median, Ulnar, Radial\nMusculocutaneous, Axillary", "Lateral border of\npectoralis minor - axilla", "Axillary"],
]
anat_col = [2.4*cm, 4.2*cm, 5.8*cm, 3.8*cm]
anat_data = [[Paragraph(h, TH) for h in anat_headers]]
row_colors = [LIGHT_BLUE, PALE_GREY, LIGHT_BLUE, PALE_GREY, LIGHT_BLUE]
for i, row in enumerate(anat_rows):
anat_data.append([Paragraph(str(c).replace("\n","<br/>"), TD_B if i==0 else TD) for c in row])
anat_table = Table(anat_data, colWidths=anat_col, repeatRows=1)
anat_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [PALE_GREY, WHITE]),
("GRID", (0,0), (-1,-1), 0.4, MID_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(anat_table)
story.append(Spacer(1, 4))
# Cord → nerve mnemonic box
cord_style = S("CS", fontSize=8, textColor=DARK_BLUE, fontName="Helvetica",
leading=12, alignment=TA_LEFT)
cord_text = (
"<b>Cord → Terminal Nerve Formation:</b> "
"<b>Lateral cord</b> → Lat. head of median nerve + Musculocutaneous nerve | "
"<b>Medial cord</b> → Med. head of median nerve + Ulnar nerve + Medial cutaneous nerves | "
"<b>Posterior cord</b> → Axillary nerve + Radial nerve"
)
cord_box = Table([[Paragraph(cord_text, cord_style)]], colWidths=[W])
cord_box.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BLUE),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("BOX", (0,0), (-1,-1), 0.8, MED_BLUE),
]))
story.append(cord_box)
story.append(Spacer(1, 10))
# ========================================================
# SECTION 2: MAIN BLOCK SELECTION TABLE
# ========================================================
story.append(section_header("2. BLOCK SELECTION BY SURGERY"))
story.append(Spacer(1, 6))
# colour key
key_style = S("KEY", fontSize=7.5, textColor=colors.HexColor("#1C1C1C"),
fontName="Helvetica", alignment=TA_CENTER, leading=10)
key_data = [
[colored_cell("■ SHOULDER", key_style, colors.HexColor("#BDD7EE")),
colored_cell("■ UPPER ARM", key_style, colors.HexColor("#C6EFCE")),
colored_cell("■ ELBOW / FOREARM", key_style, colors.HexColor("#FFEB9C")),
colored_cell("■ WRIST / HAND", key_style, colors.HexColor("#FFC7CE")),
]
]
key_table = Table(key_data, colWidths=[W/4]*4)
key_table.setStyle(TableStyle([
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 2),
("RIGHTPADDING", (0,0), (-1,-1), 2),
]))
story.append(key_table)
story.append(Spacer(1, 5))
# Surgery region headers + rows
# Format: region_color, surgery, block, level_targeted, LA_volume, notes
SHOULDER_C = colors.HexColor("#BDD7EE")
ARM_C = colors.HexColor("#C6EFCE")
ELBOW_C = colors.HexColor("#FFEB9C")
HAND_C = colors.HexColor("#FFC7CE")
main_cols = [3.8*cm, 3.5*cm, 3.2*cm, 2.0*cm, 3.7*cm]
main_headers = ["Surgery / Procedure", "Preferred Block", "Level Targeted", "LA Vol (mL)", "Key Notes"]
main_rows = [
# --- SHOULDER ---
("SHOULDER", None, None, None, None, SHOULDER_C),
("Shoulder arthroplasty (TSA/hemi)", "Interscalene", "Roots C5-C6 /\nUpper trunk", "15–25", "Gold standard; spares C8-T1 (ulnar)", SHOULDER_C),
("Rotator cuff repair (RCR)", "Interscalene", "Roots C5-C6 /\nUpper trunk", "15–25", "Excellent post-op analgesia 12-18 h", SHOULDER_C),
("Shoulder arthroscopy", "Interscalene", "Roots / Trunks", "15–20", "Add cervical plexus block if tourniquet at shoulder", SHOULDER_C),
("Clavicle ORIF", "Interscalene +\nCervical plexus", "C5-C6 +\nC3-C4 (supraclavicular n.)", "15–20 +\n5–10", "Supraclavicular nerve (C3-C4) covers medial clavicle", SHOULDER_C),
("AC joint procedures", "Interscalene +\nCervical plexus", "Upper trunk +\nC3-C4", "15–20 +\n5–10", "Often requires superficial cervical plexus supplement", SHOULDER_C),
("Shoulder (high respiratory risk)", "Superior trunk block OR\nAnterior suprascapular\n+ Infraclavicular", "C5-C6 / suprascapular n.\n+ Cords", "10–15 +\n25–30", "Phrenic-sparing; avoids hemidiaphragm paralysis", SHOULDER_C),
# --- UPPER ARM ---
("UPPER ARM", None, None, None, None, ARM_C),
("Proximal humerus fracture ORIF", "Interscalene", "Roots / Upper trunk", "20–25", "C5-C7 block; tourniquet at shoulder needs cervical supplement", ARM_C),
("Mid-shaft humerus ORIF", "Interscalene OR\nSupraclavicular", "Roots/Trunks OR\nDivisions", "20–30", "Supraclavicular gives more reliable C8-T1 coverage distally", ARM_C),
("Arm tourniquet analgesia (any)", "Any + Intercostobrachial\nsupplementation", "T2 cutaneous coverage", "3–5\n(subcutaneous)", "T2 (intercostobrachial n.) always spared; ring infiltration in axilla", ARM_C),
# --- ELBOW / FOREARM ---
("ELBOW / FOREARM", None, None, None, None, ELBOW_C),
("Elbow fracture / ORIF", "Supraclavicular OR\nInfraclavicular", "Divisions OR Cords", "20–30", "Infraclavicular preferred if catheter needed; arm abduction required", ELBOW_C),
("Distal radius / ulna fracture", "Supraclavicular OR\nInfraclavicular", "Divisions OR Cords", "20–30", "Both approaches equally effective; infraclavicular catheter superior", ELBOW_C),
("Forearm fasciotomy / debridement", "Infraclavicular", "Cords", "25–35", "Posterior cord injection provides reliable coverage; easy catheter", ELBOW_C),
("Tendon repair forearm", "Infraclavicular OR\nAxillary", "Cords OR\nTerminal nerves", "25–35", "Axillary feasible if limited to forearm distal to mid-humeral level", ELBOW_C),
# --- WRIST / HAND ---
("WRIST / HAND", None, None, None, None, HAND_C),
("Carpal tunnel release", "Axillary OR\nWrist block", "Terminal nerves", "25–40\nOR 3–5 each", "Axillary if bilateral impractical; wrist block for isolated procedure", HAND_C),
("Hand ORIF / fracture fixation", "Axillary OR\nInfraclavicular", "Terminal nerves OR\nCords", "25–40", "Multiple injections around each nerve at axilla for reliability", HAND_C),
("Wrist arthroscopy", "Axillary OR\nInfraclavicular", "Terminal nerves OR\nCords", "25–35", "Axillary: supplement musculocutaneous n. in coracobrachialis", HAND_C),
("Digital / finger procedures", "Wrist block OR\nDigital ring block", "Terminal branches\nat wrist", "3–5 each", "Median ± ulnar ± radial superficial branch at wrist; no epinephrine in fingers", HAND_C),
("Replantation / microsurgery", "Infraclavicular\ncatheter (continuous)", "Cords", "Infusion\n5–10 mL/h", "Sympathectomy effect promotes vasodilation; catheter > single shot", HAND_C),
("Dupuytren's contracture", "Axillary", "Terminal nerves", "25–40", "Multiple injection technique; all four nerves around axillary artery", HAND_C),
]
THs = [Paragraph(h, TH) for h in main_headers]
table_data = [THs]
for row in main_rows:
surgery, block, level, vol, notes, rc = row
if block is None:
# Region header row
region_style = S("RH", fontSize=9, textColor=DARK_BLUE,
fontName="Helvetica-Bold", alignment=TA_LEFT,
leading=11, leftIndent=4)
merged_cell = Paragraph(f"▶ {surgery}", region_style)
table_data.append([merged_cell, "", "", "", ""])
else:
table_data.append([
Paragraph(surgery, TD),
Paragraph(block.replace("\n","<br/>"), TD_B),
Paragraph(level.replace("\n","<br/>"), TD_C),
Paragraph(vol.replace("\n","<br/>"), TD_C),
Paragraph(notes, SMALL),
])
main_table = Table(table_data, colWidths=main_cols, repeatRows=1)
# Build style commands
ts_cmds = [
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, PALE_GREY]),
]
# colour region headers + data rows
region_row_idx = 1 # track row index in table_data (0 = header)
for row in main_rows:
surgery, block, level, vol, notes, rc = row
if block is None:
ts_cmds.append(("BACKGROUND", (0,region_row_idx), (-1,region_row_idx), rc))
ts_cmds.append(("SPAN", (0,region_row_idx), (-1,region_row_idx)))
ts_cmds.append(("LINEABOVE", (0,region_row_idx), (-1,region_row_idx), 1.2, DARK_BLUE))
else:
ts_cmds.append(("BACKGROUND", (0,region_row_idx), (0,region_row_idx),
colors.HexColor(rc.hexval() + "33" if hasattr(rc,"hexval") else "#FAFAFA")))
# tint the surgery column lightly
lighter = colors.Color(rc.red, rc.green, rc.blue, alpha=0.25)
ts_cmds.append(("BACKGROUND", (0,region_row_idx), (0,region_row_idx), lighter))
region_row_idx += 1
main_table.setStyle(TableStyle(ts_cmds))
story.append(KeepTogether([main_table]))
story.append(Spacer(1, 10))
# ========================================================
# SECTION 3: APPROACH PROFILES
# ========================================================
story.append(section_header("3. APPROACH PROFILES AT A GLANCE"))
story.append(Spacer(1, 6))
profile_cols = [2.7*cm, 3.3*cm, 2.8*cm, 2.8*cm, 3.0*cm, 1.6*cm]
profile_headers = ["Approach", "US Landmarks", "Ideal Indication", "Spared Nerves", "Main Complications", "Catheter?"]
profiles = [
["Interscalene",
"Scalene muscles at C6 level;\n'Stoplight' sign (3 trunks)",
"Shoulder,\nproximal humerus",
"C8-T1 (ulnar n.)\nT2 (intercostobrachial)",
"Phrenic nerve palsy (>95%)\nHorner syndrome\nRecurrent laryngeal n.\nIntrathecal injection",
"Yes\n(perineural)"],
["Supraclavicular\n('Spinal of the arm')",
"Subclavian artery;\n'Cluster of grapes';\nFirst rib + pleura deep",
"Elbow, forearm,\nhand surgery",
"Suprascapular n. (variable)\nT2 intercostobrachial",
"Pneumothorax (~0.5-1%)\nPhrenic palsy (~50%)\nHorner syndrome\nSubclavian artery puncture",
"Yes\n(less stable)"],
["Infraclavicular",
"Axillary artery in\nparasagittal plane;\n2 cm medial + caudad\nto coracoid process",
"Elbow, forearm, hand;\nBest for catheters",
"T2 intercostobrachial\nShoulder / upper arm",
"Vascular puncture\nPneumothorax (rare)\nHematoma",
"YES\n(preferred)"],
["Axillary",
"Axillary artery + 4\nterminal nerves;\nMusculocutaneous in\ncoracobrachialis",
"Wrist and hand\nsurgery",
"Musculocutaneous n.\n(inject separately)\nAxillary n.; T2",
"Axillary vascular\npuncture/hematoma\nNerve injury\nHigh LAST risk",
"Less\ncommon"],
]
ph = [Paragraph(h, TH) for h in profile_headers]
profile_data = [ph]
for row in profiles:
profile_data.append([Paragraph(c.replace("\n","<br/>"), TD) for c in row])
profile_table = Table(profile_data, colWidths=profile_cols, repeatRows=1)
profile_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [PALE_GREY, WHITE]),
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
# highlight complication column lightly
("BACKGROUND", (4,1), (4,-1), colors.HexColor("#FFF5F5")),
# highlight catheter column
("BACKGROUND", (5,1), (5,-1), colors.HexColor("#F0FFF4")),
# bold infraclavicular catheter cell
("TEXTCOLOR", (5,3), (5,3), GREEN_DARK),
]))
story.append(profile_table)
story.append(Spacer(1, 10))
# ========================================================
# SECTION 4: LOCAL ANAESTHETICS
# ========================================================
story.append(section_header("4. LOCAL ANAESTHETICS & ADJUVANTS"))
story.append(Spacer(1, 6))
la_cols = [3.2*cm, 2.8*cm, 2.5*cm, 2.5*cm, 5.2*cm]
la_headers = ["Drug", "Concentration", "Onset", "Duration", "Notes"]
la_rows = [
["Ropivacaine", "0.375-0.5% (surgical)\n0.2% (analgesia)", "Moderate\n(15–20 min)", "8–12 h", "Preferred for peripheral blocks; less cardiotoxic than bupivacaine; motor-sensory differential with low concentrations"],
["Bupivacaine", "0.25-0.5%", "Moderate\n(15–20 min)", "8–16 h", "Long-acting; cardiotoxicity risk with intravascular injection; use with caution"],
["Levobupivacaine", "0.25-0.5%", "Moderate", "8–12 h", "Safer cardiac profile than racemic bupivacaine; similar duration"],
["Lidocaine", "1–1.5% (± epi)", "Rapid\n(5–10 min)", "2–4 h", "Add epinephrine 1:200,000 to extend duration; useful when rapid onset needed"],
["Mepivacaine", "1–1.5%", "Rapid\n(10–15 min)", "4–6 h", "Good alternative to lidocaine; intermediate duration; ambulatory surgery"],
]
la_adjuvants = [
["Dexamethasone (adjuvant)", "4–8 mg IV or perineural", "—", "+6–8 h", "Most reliable block prolongation; IV dexamethasone equally effective; preferred over perineural in most centres"],
["Dexmedetomidine (adjuvant)", "0.5–1 mcg/kg", "—", "+4–6 h", "Adds sedation; use caution in ambulatory patients; bradycardia possible"],
["Epinephrine (vasoconstrictor)", "1:200,000 (5 mcg/mL)", "—", "+20–30%", "Marker of intravascular injection; prolongs block; avoid in digital blocks"],
]
lah = [Paragraph(h, TH) for h in la_headers]
la_data = [lah]
for row in la_rows:
la_data.append([Paragraph(c.replace("\n","<br/>"), TD) for c in row])
# adjuvant sub-header
adj_style = S("ADJ", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=11, leftIndent=4)
la_data.append([Paragraph("ADJUVANTS", adj_style), "", "", "", ""])
for row in la_adjuvants:
la_data.append([Paragraph(c.replace("\n","<br/>"), TD) for c in row])
la_table = Table(la_data, colWidths=la_cols, repeatRows=1)
la_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS", (0,1), (- 1,len(la_rows)), [PALE_GREY, WHITE]),
("BACKGROUND", (0,len(la_rows)+1), (-1,len(la_rows)+1), MED_BLUE),
("SPAN", (0,len(la_rows)+1), (-1,len(la_rows)+1)),
("ROWBACKGROUNDS", (0,len(la_rows)+2), (-1,-1), [colors.HexColor("#FFF8E8"), WHITE]),
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(la_table)
story.append(Spacer(1, 10))
# ========================================================
# SECTION 5: CONTRAINDICATIONS & COMPLICATIONS
# ========================================================
story.append(section_header("5. CONTRAINDICATIONS & COMPLICATIONS"))
story.append(Spacer(1, 6))
left_w = W * 0.45
right_w = W * 0.52
gap = W * 0.03
# Contraindications
ci_style = S("CI", fontSize=8, textColor=colors.HexColor("#1C1C1C"),
fontName="Helvetica", leading=12)
ci_bold = S("CIB", fontSize=8, textColor=RED_DARK, fontName="Helvetica-Bold", leading=12)
ci_abs = [
"• Patient refusal",
"• True local anaesthetic allergy",
"• Local infection at injection site",
"• Contralateral phrenic nerve palsy\n (for interscalene / supraclavicular)",
"• Contralateral pneumonectomy\n (same as above)",
]
ci_rel = [
"• Severe coagulopathy (INR >3 / platelets <50k)",
"• Pre-existing neurological deficit in same limb",
"• Severe pulmonary disease (FEV1 or FVC <50%)\n — interscalene/supraclavicular only",
"• Ipsilateral subclavian catheter or\n transvenous pacemaker (infraclavicular)",
"• Bilateral blocks (combined phrenic palsy risk)",
]
ci_left = Table(
[[Paragraph("ABSOLUTE CONTRAINDICATIONS", S("CH", fontSize=8.5, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=11))]] +
[[Paragraph(c, ci_style)] for c in ci_abs],
colWidths=[left_w]
)
ci_left.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#C0392B")),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, RED_LIGHT]),
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
ci_right = Table(
[[Paragraph("RELATIVE CONTRAINDICATIONS", S("CH2", fontSize=8.5, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=11))]] +
[[Paragraph(c, ci_style)] for c in ci_rel],
colWidths=[right_w]
)
ci_right.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#E67E22")),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, AMBER_LIGHT]),
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
ci_outer = Table([[ci_left, Spacer(gap, 1), ci_right]], colWidths=[left_w, gap, right_w])
ci_outer.setStyle(TableStyle([("VALIGN", (0,0), (-1,-1), "TOP")]))
story.append(ci_outer)
story.append(Spacer(1, 8))
# Complications by approach
comp_headers = ["Complication", "Interscalene", "Supraclavicular", "Infraclavicular", "Axillary"]
comp_rows = [
["Phrenic nerve palsy", "●●● >95%", "●● ~50%", "Rare", "None"],
["Pneumothorax", "Rare", "●● ~0.5-1%", "● <0.5%", "None"],
["Horner syndrome", "●● Common", "● Occasional", "Rare", "None"],
["Recurrent laryngeal n. block","●● Common", "Rare", "None", "None"],
["Vascular puncture", "● Rare", "● Subclavian", "●● Axillary", "●● Axillary"],
["Intrathecal / epidural inj.", "●● Possible", "None", "None", "None"],
["LAST risk", "Moderate", "Moderate", "Moderate", "HIGH\n(vascular area)"],
["Nerve injury", "Low", "Low", "Low", "Low"],
]
comp_cols = [4.2*cm, 2.8*cm, 3.0*cm, 3.0*cm, 2.2*cm]
comp_h = [Paragraph(h, TH) for h in comp_headers]
comp_data = [comp_h]
for row in comp_rows:
comp_data.append([Paragraph(c, TD_C if i>0 else TD) for i,c in enumerate(row)])
comp_table = Table(comp_data, colWidths=comp_cols, repeatRows=1)
comp_ts = [
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("ROWBACKGROUNDS", (0,1), (-1,-1), [PALE_GREY, WHITE]),
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]
# Red cells for high risk entries
high_risk_cells = [
(1,1),(1,2), # phrenic - interscalene/supraclavicular
(2,2), # pneumothorax - supraclavicular
(3,1),(3,2), # Horner - interscalene/supraclavicular
(4,1),(4,2), # recurrent laryngeal
(7,1), # intrathecal
(8,4), # LAST axillary
]
for r,c in high_risk_cells:
comp_ts.append(("BACKGROUND", (c, r), (c, r), colors.HexColor("#FADADD")))
comp_table.setStyle(TableStyle(comp_ts))
story.append(comp_table)
story.append(Spacer(1, 10))
# ========================================================
# SECTION 6: DECISION ALGORITHM
# ========================================================
story.append(section_header("6. QUICK DECISION ALGORITHM"))
story.append(Spacer(1, 6))
algo_style = S("ALGO", fontSize=8.5, textColor=DARK_BLUE,
fontName="Helvetica", leading=13, alignment=TA_LEFT)
algo_bold = S("ALGOB", fontSize=8.5, textColor=DARK_BLUE,
fontName="Helvetica-Bold", leading=13, alignment=TA_LEFT)
algo_steps = [
("Step 1", "Identify surgery region", "Shoulder? → Interscalene (± cervical plexus)"),
("Step 2", "Assess pulmonary function", "FEV1/FVC <50% or contralateral phrenic palsy? → Phrenic-sparing approach (superior trunk / suprascapular + infraclavicular)"),
("Step 3", "Elbow / forearm / hand?", "Need catheter for prolonged analgesia? → Infraclavicular (best catheter stability) | Single shot? → Supraclavicular ('spinal of the arm')"),
("Step 4", "Wrist / hand only?", "Axillary block with multiple injections (always supplement musculocutaneous n. in coracobrachialis)"),
("Step 5", "Upper arm tourniquet?", "Add intercostobrachial nerve (T2) block — subcutaneous ring infiltration in axilla regardless of approach"),
("Step 6", "Microsurgery / replantation?", "Infraclavicular catheter with continuous infusion — sympathectomy effect aids vasodilation"),
]
algo_data = []
for step, q, a in algo_steps:
step_style = S("SS", fontSize=8.5, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=12)
q_style = S("QS", fontSize=8.5, textColor=DARK_BLUE, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=12)
a_style = S("AS", fontSize=8.5, textColor=colors.HexColor("#1C1C1C"), fontName="Helvetica",
alignment=TA_LEFT, leading=12)
algo_data.append([
Paragraph(step, step_style),
Paragraph(q, q_style),
Paragraph(a.replace("→","→"), a_style),
])
algo_table = Table(algo_data, colWidths=[1.8*cm, 4.2*cm, 10.2*cm])
algo_ts = [
("GRID", (0,0), (-1,-1), 0.3, MID_GREY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ROWBACKGROUNDS", (0,0), (-1,-1), [PALE_GREY, WHITE]),
]
for i in range(len(algo_steps)):
algo_ts.append(("BACKGROUND", (0,i), (0,i), DARK_BLUE if i%2==0 else MED_BLUE))
algo_table.setStyle(TableStyle(algo_ts))
story.append(algo_table)
story.append(Spacer(1, 10))
# ========================================================
# FOOTER
# ========================================================
story.append(HRFlowable(width=W, thickness=0.5, color=MID_GREY))
story.append(Spacer(1, 4))
footer_text = (
"Sources: Miller's Anesthesia 10e | Morgan & Mikhail's Clinical Anesthesiology 7e | "
"Barash, Cullen & Stoelting's Clinical Anesthesia 9e | "
"Generated by Orris Medical AI | For educational use only — always verify against current institutional guidelines."
)
story.append(Paragraph(footer_text, FOOTER))
# ========================================================
# BUILD
# ========================================================
doc.build(story)
print(f"PDF created: {OUTPUT}")
cd /home/daytona/workspace/brachial-plexus-pdf && python generate_pdf.py 2>&1
Brachial Plexus Block Selection
PDF Document · PDF