Give me clinical diagram of dynamic stabilizers of shoulder from Campbell Orthopaedics.


| Mechanism | Description |
|---|---|
| Concavity-compression | Rotator cuff contraction compresses the humeral head into the glenoid concavity, resisting translatory forces. Loss of labrum reduces this effect by 20% |
| Coordinated contraction | Guides the humeral head to the center of the glenoid surface |
| Dynamization of capsuloligamentous structures | Through rotator cuff attachments, passive ligaments are tensioned as the shoulder moves through its ROM |
| Effect | Mechanism |
|---|---|
| Passive tension | From muscle bulk alone |
| Compressive contraction | Muscle contraction compresses the humeral head on the articular surface |
| Passive ligament tensioning | Joint motion produced by deltoid tightens passive ligaments |
| Barrier effect | Contracted muscle acts as a physical barrier |
| Dynamic Stabilizer | Primary Mechanism | Key Position |
|---|---|---|
| Rotator cuff (4 muscles) | Concavity-compression; centering | Midranges of motion |
| Long head of biceps | Anterior restraint (ABER) | Abduction + external rotation |
| Deltoid | Compression + barrier effect | Elevation, external rotation |
| Scapular stabilizers | Glenoid positioning (compressive vs. shear force) | All positions |
| Proprioceptive reflexes | Reflex muscle contraction | Extremes of motion / instability |
Create a clinical decision tree for multidirectional instability management
ls /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or not found"
mkdir -p /home/daytona/workspace/mdi-decision-tree && python3 -c "import matplotlib; print(matplotlib.__version__)"
~/mdi-decision-tree/build_tree.py
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
import matplotlib.patheffects as pe
import numpy as np
fig, ax = plt.subplots(figsize=(22, 30))
ax.set_xlim(0, 22)
ax.set_ylim(0, 30)
ax.axis('off')
fig.patch.set_facecolor('#F5F7FA')
# ── colour palette ──────────────────────────────────────────────────
C_TITLE = '#1A1F5E' # dark navy – header
C_DIAG = '#1A237E' # indigo – diagnosis / entry
C_SCREEN = '#283593' # deep blue – screening boxes
C_NONOP = '#1565C0' # blue – nonoperative path
C_EXCL = '#B71C1C' # red – exclusions / contraindications
C_SURG = '#1B5E20' # dark green – surgery boxes
C_REHAB = '#4A148C' # purple – rehab / post-op
C_ARROW = '#37474F' # charcoal – arrows
C_SULCUS = '#E65100' # orange – sulcus sign decision
C_OUTCOME = '#00695C' # teal – outcomes
WHITE = '#FFFFFF'
LIGHT_BG = '#E8EAF6' # very light indigo background for boxes
# ── helper: draw a rounded rectangle with text ──────────────────────
def box(ax, x, y, w, h, text, bg, fg='white', fontsize=8.5,
bold=False, border=None, alpha=1.0, style='round,pad=0.1'):
fc = bg
ec = border if border else bg
lw = 1.8 if border else 0.8
patch = FancyBboxPatch((x - w/2, y - h/2), w, h,
boxstyle=style,
facecolor=fc, edgecolor=ec,
linewidth=lw, zorder=3, alpha=alpha)
ax.add_patch(patch)
weight = 'bold' if bold else 'normal'
ax.text(x, y, text, ha='center', va='center',
fontsize=fontsize, color=fg, fontweight=weight,
wrap=True, zorder=4,
multialignment='center',
linespacing=1.35)
# ── helper: arrow ────────────────────────────────────────────────────
def arrow(ax, x1, y1, x2, y2, label='', color=C_ARROW, lw=1.6,
connectionstyle='arc3,rad=0.0'):
ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
arrowprops=dict(arrowstyle='->', color=color,
lw=lw,
connectionstyle=connectionstyle),
zorder=5)
if label:
mx, my = (x1+x2)/2, (y1+y2)/2
ax.text(mx+0.15, my, label, fontsize=7.5, color=color,
ha='left', va='center', fontstyle='italic', zorder=6)
# ── helper: horizontal connector line ───────────────────────────────
def hline(ax, x1, x2, y, color=C_ARROW, lw=1.6):
ax.plot([x1, x2], [y, y], color=color, lw=lw, zorder=5)
def vline(ax, x, y1, y2, color=C_ARROW, lw=1.6):
ax.plot([x, x], [y1, y2], color=color, lw=lw, zorder=5)
# ════════════════════════════════════════════════════════════════════
# TITLE
# ════════════════════════════════════════════════════════════════════
ax.text(11, 29.3, 'Clinical Decision Tree', ha='center', va='center',
fontsize=18, fontweight='bold', color=WHITE, zorder=6)
ax.text(11, 28.8, 'Multidirectional Instability (MDI) of the Shoulder',
ha='center', va='center', fontsize=13, color='#CFD8DC', zorder=6)
title_bg = FancyBboxPatch((0.3, 28.35), 21.4, 1.6,
boxstyle='round,pad=0.15',
facecolor=C_TITLE, edgecolor='none',
linewidth=0, zorder=2)
ax.add_patch(title_bg)
source_txt = ('Sources: Campbell\'s Operative Orthopaedics 15th Ed 2026 (Ch. 52) | '
'Rockwood & Green\'s Fractures in Adults 10th Ed 2025 (Ch. 35, Algorithm 35-4)')
ax.text(11, 28.1, source_txt, ha='center', va='center',
fontsize=6.5, color='#78909C', style='italic', zorder=6)
# ════════════════════════════════════════════════════════════════════
# NODE 1 – ENTRY / PRESENTATION
# ════════════════════════════════════════════════════════════════════
box(ax, 11, 27.15, 8.5, 0.95,
'Patient presents with MDI of the Shoulder\n'
'(symptomatic subluxation/dislocation in ≥2 directions; inferior component obligatory)',
C_DIAG, fontsize=8.5, bold=True, border='#90CAF9')
arrow(ax, 11, 26.67, 11, 26.12)
# ════════════════════════════════════════════════════════════════════
# NODE 2 – INITIAL SCREENING (exclude voluntaries / psych)
# ════════════════════════════════════════════════════════════════════
box(ax, 11, 25.75, 8.5, 0.72,
'Initial Screening: Exclude Voluntary Dislocators & Psychological / Secondary-Gain Issues',
C_SCREEN, fontsize=8.2, bold=True, border='#90CAF9')
# Branch YES (excluded) – goes RIGHT
arrow(ax, 15.25, 25.75, 18.5, 25.75, color=C_EXCL, lw=1.4)
box(ax, 19.8, 25.75, 2.5, 0.7,
'NOT a surgical\ncandidate\n(exclude from OR)',
C_EXCL, fontsize=7.5, bold=True)
ax.text(16.6, 25.9, 'Voluntary / psych',
fontsize=7, color=C_EXCL, ha='center', style='italic')
arrow(ax, 11, 25.39, 11, 24.82)
ax.text(11.2, 25.12, 'Involuntary – no psych issues',
fontsize=7, color='#1565C0', ha='left', style='italic')
# ════════════════════════════════════════════════════════════════════
# NODE 3 – NONOPERATIVE TREATMENT
# ════════════════════════════════════════════════════════════════════
box(ax, 11, 24.45, 9.5, 0.72,
'Nonoperative Treatment (MANDATORY FIRST-LINE for ALL patients)',
C_NONOP, fontsize=8.5, bold=True, border='#BBDEFB')
arrow(ax, 11, 24.09, 11, 23.55)
# PT details sub-box
box(ax, 11, 23.1, 9.5, 0.85,
'Structured Physical Therapy Programme ≥ 6–12 months\n'
'• Rotator cuff strengthening • Scapular stabilisation '
'(serratus ant., trapezius, rhomboids)\n'
'• Proprioceptive neuromuscular re-training • Activity modification if needed',
'#1976D2', fontsize=7.8, border='#BBDEFB')
arrow(ax, 11, 22.67, 11, 22.1)
# ════════════════════════════════════════════════════════════════════
# NODE 4 – RESPONSE TO PT DECISION DIAMOND
# ════════════════════════════════════════════════════════════════════
# Diamond shape via polygon
diamond_x = 11
diamond_y = 21.6
dw, dh = 4.2, 0.85
diamond = plt.Polygon(
[[diamond_x, diamond_y + dh],
[diamond_x + dw, diamond_y],
[diamond_x, diamond_y - dh],
[diamond_x - dw, diamond_y]],
closed=True, facecolor='#FFF9C4', edgecolor='#F9A825', linewidth=2, zorder=3)
ax.add_patch(diamond)
ax.text(diamond_x, diamond_y, 'Response to\nPhysical Therapy?',
ha='center', va='center', fontsize=9, fontweight='bold',
color='#E65100', zorder=4)
# YES branch (good response) – go RIGHT
arrow(ax, 15.2, 21.6, 17.4, 21.6, color=C_OUTCOME, lw=1.5)
ax.text(16.1, 21.75, 'Adequate\nresponse', fontsize=7, color=C_OUTCOME,
ha='center', style='italic')
box(ax, 19.2, 21.6, 3.5, 0.85,
'Continue PT /\nActivity modification\nLong-term follow-up',
C_OUTCOME, fontsize=7.8, bold=False, border='#A5D6A7')
# NO branch – go DOWN
arrow(ax, 11, 20.75, 11, 20.22, color=C_EXCL)
ax.text(11.2, 20.48, 'Failed PT > 1 year', fontsize=7.5, color=C_EXCL,
ha='left', style='italic', fontweight='bold')
# ════════════════════════════════════════════════════════════════════
# NODE 5 – PRE-SURGICAL COUNSELLING
# ════════════════════════════════════════════════════════════════════
box(ax, 11, 19.85, 9.5, 0.72,
'Pre-Surgical Counselling: Discuss inconsistent results; activity/occupation modification as alternatives',
'#5C6BC0', fontsize=8, border='#C5CAE9')
arrow(ax, 11, 19.49, 11, 18.95)
# ════════════════════════════════════════════════════════════════════
# NODE 6 – EUA & DIRECTION OF INSTABILITY
# ════════════════════════════════════════════════════════════════════
box(ax, 11, 18.58, 9.5, 0.72,
'Examination Under Anaesthesia (EUA) – Confirm direction & degree of instability\n'
'(Sulcus sign, load-and-shift, apprehension, anterior/posterior draw)',
C_SCREEN, fontsize=8, border='#90CAF9')
arrow(ax, 11, 18.22, 11, 17.72)
# ════════════════════════════════════════════════════════════════════
# NODE 7 – SULCUS SIGN DECISION
# ════════════════════════════════════════════════════════════════════
box(ax, 11, 17.38, 7.5, 0.65,
'Sulcus Sign Persists in External Rotation? (indicates rotator interval laxity)',
C_SULCUS, fontsize=8, bold=True, border='#FFCC80')
arrow(ax, 11, 17.05, 11, 16.6, color=C_SULCUS)
ax.text(11.15, 16.83, 'Yes → add Rotator Interval Closure to chosen procedure',
fontsize=7.5, color=C_SULCUS, ha='left', style='italic')
# ════════════════════════════════════════════════════════════════════
# NODE 8 – DIRECTION BRANCH (3 columns)
# ════════════════════════════════════════════════════════════════════
box(ax, 11, 16.25, 9.0, 0.65,
'Determine Dominant Direction of Instability',
C_DIAG, fontsize=8.5, bold=True, border='#90CAF9')
# horizontal branch line
y_branch = 15.92
vline(ax, 11, 15.92, 15.55)
hline(ax, 4.2, 17.8, y_branch)
# ---- LEFT branch: ANTEROINFERIOR ----
vline(ax, 4.2, y_branch, 15.2)
arrow(ax, 4.2, 15.2, 4.2, 14.72)
box(ax, 4.2, 14.95, 4.2, 0.5,
'Anteroinferior\nInstability',
C_DIAG, fontsize=8.5, bold=True)
# ---- CENTRE branch: POSTEROINFERIOR ----
vline(ax, 11, y_branch, 15.2)
arrow(ax, 11, 15.2, 11, 14.72)
box(ax, 11, 14.95, 4.2, 0.5,
'Posteroinferior\nInstability',
'#1A237E', fontsize=8.5, bold=True)
# ---- RIGHT branch: ANTERIOR + POSTERIOR + INFERIOR (pan) ----
vline(ax, 17.8, y_branch, 15.2)
arrow(ax, 17.8, 15.2, 17.8, 14.72)
box(ax, 17.8, 14.95, 4.2, 0.5,
'Anterior + Posterior\n+ Inferior (Pan-MDI)',
'#283593', fontsize=8, bold=True)
# ════════════════════════════════════════════════════════════════════
# SURGICAL APPROACH DECISION (open vs arthroscopic)
# ════════════════════════════════════════════════════════════════════
# LEFT column
arrow(ax, 4.2, 14.69, 4.2, 14.15)
box(ax, 4.2, 13.82, 4.0, 0.65,
'Arthroscopic vs Open\nAnteroinferior Capsular Shift\n± Rotator Interval Closure',
C_SURG, fontsize=8, bold=True, border='#A5D6A7')
# CENTRE column
arrow(ax, 11, 14.69, 11, 14.15)
box(ax, 11, 13.82, 4.0, 0.65,
'Arthroscopic vs Open\nPosteroinferior Capsular Shift\n± Rotator Interval Closure',
C_SURG, fontsize=8, bold=True, border='#A5D6A7')
# RIGHT column
arrow(ax, 17.8, 14.69, 17.8, 14.15)
box(ax, 17.8, 13.82, 4.0, 0.65,
'Arthroscopic vs Open Anterior\n& Posterior Inferior Capsular Shift\n± Rotator Interval Closure',
C_SURG, fontsize=8, bold=True, border='#A5D6A7')
# ════════════════════════════════════════════════════════════════════
# OPEN vs ARTHROSCOPIC SUB-DECISION
# ════════════════════════════════════════════════════════════════════
# Shared label
box(ax, 11, 13.05, 9.5, 0.55,
'Arthroscopic vs Open: Surgeon Preference, Patient Factors, Capsular Redundancy Degree',
'#37474F', fontsize=7.5, bg='#ECEFF1', fg='#263238', border='#B0BEC5')
# LEFT sub-branches
arrow(ax, 4.2, 13.49, 3.1, 12.88, color='#2E7D32')
box(ax, 2.5, 12.6, 2.4, 0.5,
'Arthroscopic\nCapsular Plication',
'#2E7D32', fontsize=7.5, border='#A5D6A7')
arrow(ax, 4.2, 13.49, 5.3, 12.88, color='#388E3C')
box(ax, 5.9, 12.6, 2.4, 0.5,
'Open Capsular\nShift (Neer-Foster)',
'#388E3C', fontsize=7.5, border='#A5D6A7')
# CENTRE sub-branches
arrow(ax, 11, 13.49, 9.9, 12.88, color='#2E7D32')
box(ax, 9.3, 12.6, 2.4, 0.5,
'Arthroscopic\nCapsular Plication',
'#2E7D32', fontsize=7.5, border='#A5D6A7')
arrow(ax, 11, 13.49, 12.1, 12.88, color='#388E3C')
box(ax, 12.7, 12.6, 2.4, 0.5,
'Open Capsular\nShift (Posterior)',
'#388E3C', fontsize=7.5, border='#A5D6A7')
# RIGHT sub-branches
arrow(ax, 17.8, 13.49, 16.7, 12.88, color='#2E7D32')
box(ax, 16.1, 12.6, 2.4, 0.5,
'Arthroscopic\nPan-Capsular Plica.',
'#2E7D32', fontsize=7.5, border='#A5D6A7')
arrow(ax, 17.8, 13.49, 18.9, 12.88, color='#388E3C')
box(ax, 19.5, 12.6, 2.4, 0.5,
'Open Ant+Post\nCapsular Shift',
'#388E3C', fontsize=7.5, border='#A5D6A7')
# ════════════════════════════════════════════════════════════════════
# SURGICAL NOTES BOX (key intraop points)
# ════════════════════════════════════════════════════════════════════
arrow(ax, 11, 12.35, 11, 11.8)
box(ax, 11, 11.45, 14.0, 0.72,
'Key Intraoperative Principles (all approaches)\n'
'• Obliterate inferior capsular pouch • Shift capsule to opposite side of calcar '
'• Close rotator interval if sulcus persists in ER\n'
'• Arm in 20–30° abd + 20–30° ER during repair to avoid over-constraint '
'• Avoid thermal capsulorrhaphy (risk: chondrolysis)',
'#4E342E', fontsize=7.5, border='#BCAAA4', bg='#EFEBE9', fg='#212121')
# ════════════════════════════════════════════════════════════════════
# POST-OPERATIVE REHABILITATION
# ════════════════════════════════════════════════════════════════════
arrow(ax, 11, 11.09, 11, 10.55)
box(ax, 11, 10.18, 9.5, 0.72,
'Postoperative Rehabilitation Protocol',
C_REHAB, fontsize=8.5, bold=True, border='#CE93D8')
arrow(ax, 11, 9.82, 11, 9.35)
# Phase table
phases = [
('Phase I\n0–6 weeks', 'Sling immobilisation with abduction pillow\nPassive ROM; pendulums only', '#6A1B9A'),
('Phase II\n6–12 weeks', 'Active-assisted ROM; begin rotator cuff activation\nScapular stabilisation exercises', '#7B1FA2'),
('Phase III\n3–6 months','Progressive strengthening; proprioceptive training\nFull active ROM achieved', '#8E24AA'),
('Phase IV\n6–12 months','Sport-specific / work-specific training\nReturn-to-activity clearance', '#9C27B0'),
]
xs = [3.2, 7.5, 14.5, 18.8]
for (title, detail, clr), px in zip(phases, xs):
box(ax, px, 8.75, 4.0, 1.15,
title + '\n' + detail,
clr, fontsize=7.2, border='#CE93D8')
arrow(ax, 11, 9.35, px, 9.34, color=C_REHAB, lw=1.2)
# ════════════════════════════════════════════════════════════════════
# OUTCOME ASSESSMENT
# ════════════════════════════════════════════════════════════════════
# Collect all phase boxes and draw arrow down from each to outcome
for px in xs:
arrow(ax, px, 8.18, px, 7.72, color=C_REHAB, lw=1.0)
hline(ax, xs[0], xs[-1], 7.72, color=C_REHAB, lw=1.0)
vline(ax, 11, 7.72, 7.35, color=C_REHAB, lw=1.2)
box(ax, 11, 7.0, 9.5, 0.65,
'Outcome Assessment (12 months post-op): ASES, WOSI, Rowe scores; recurrence rate check',
C_OUTCOME, fontsize=8, border='#A5D6A7')
arrow(ax, 11, 6.67, 11, 6.18)
# ════════════════════════════════════════════════════════════════════
# FINAL OUTCOMES BRANCH
# ════════════════════════════════════════════════════════════════════
diamond2_x, diamond2_y = 11, 5.78
dw2, dh2 = 3.8, 0.75
diamond2 = plt.Polygon(
[[diamond2_x, diamond2_y + dh2],
[diamond2_x + dw2, diamond2_y],
[diamond2_x, diamond2_y - dh2],
[diamond2_x - dw2, diamond2_y]],
closed=True, facecolor='#E8F5E9', edgecolor='#2E7D32', linewidth=2, zorder=3)
ax.add_patch(diamond2)
ax.text(diamond2_x, diamond2_y, 'Stability\nRestored?',
ha='center', va='center', fontsize=9, fontweight='bold',
color='#1B5E20', zorder=4)
# YES → right
arrow(ax, 14.8, 5.78, 17.0, 5.78, color=C_OUTCOME, lw=1.5)
ax.text(15.75, 5.93, 'Yes', fontsize=8, color=C_OUTCOME, ha='center')
box(ax, 18.8, 5.78, 3.5, 0.9,
'Successful outcome\nReturn to activity\nLong-term surveillance',
C_OUTCOME, fontsize=7.8, border='#A5D6A7')
# NO → left
arrow(ax, 7.2, 5.78, 5.0, 5.78, color=C_EXCL, lw=1.5)
ax.text(6.2, 5.93, 'No', fontsize=8, color=C_EXCL, ha='center')
box(ax, 3.2, 5.78, 3.5, 0.9,
'Revision planning:\nRepeat EUA; assess\nbone loss, capsule quality',
C_EXCL, fontsize=7.8, border='#EF9A9A')
# ════════════════════════════════════════════════════════════════════
# WARNING / CONTRAINDICATIONS FOOTER
# ════════════════════════════════════════════════════════════════════
warn_bg = FancyBboxPatch((0.5, 4.35), 21.0, 0.82,
boxstyle='round,pad=0.1',
facecolor='#FFF3E0', edgecolor='#E65100',
linewidth=1.5, zorder=2)
ax.add_patch(warn_bg)
ax.text(11, 4.76,
'⚠ Contraindications to Surgery: Voluntary dislocation | Significant psychological issues or secondary gain | '
'Inadequate PT trial (<6 mo) | Active infection',
ha='center', va='center', fontsize=7.8, color='#BF360C',
fontweight='bold', zorder=6)
# ════════════════════════════════════════════════════════════════════
# LEGEND
# ════════════════════════════════════════════════════════════════════
legend_items = [
(C_DIAG, 'Diagnosis / Entry node'),
(C_NONOP, 'Nonoperative pathway'),
(C_SURG, 'Surgical intervention'),
(C_EXCL, 'Exclusion / Contraindication'),
(C_REHAB, 'Rehabilitation protocol'),
(C_OUTCOME,'Outcome assessment'),
(C_SULCUS, 'Key decision point'),
]
lx, ly = 0.6, 3.85
ax.text(lx, ly, 'Legend:', fontsize=7.5, fontweight='bold', color='#263238')
for i, (clr, label) in enumerate(legend_items):
px = lx + (i % 4) * 5.3
py = ly - 0.45 - (i // 4) * 0.42
patch = FancyBboxPatch((px, py - 0.14), 0.35, 0.28,
boxstyle='round,pad=0.03',
facecolor=clr, edgecolor='none', zorder=3)
ax.add_patch(patch)
ax.text(px + 0.48, py, label, fontsize=7, color='#263238', va='center')
plt.tight_layout(pad=0.5)
plt.savefig('/home/daytona/workspace/mdi-decision-tree/MDI_Decision_Tree.png',
dpi=180, bbox_inches='tight', facecolor='#F5F7FA')
print("Saved successfully")
cd /home/daytona/workspace/mdi-decision-tree && python3 build_tree.py 2>&1
~/mdi-decision-tree/build_tree.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/mdi-decision-tree/build_tree.py'
cd /home/daytona/workspace/mdi-decision-tree && python3 build_tree.py 2>&1
~/mdi-decision-tree/build_tree.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/mdi-decision-tree/build_tree.py'
cd /home/daytona/workspace/mdi-decision-tree && python3 build_tree.py 2>&1
ls -lh /home/daytona/workspace/mdi-decision-tree/MDI_Decision_Tree.png && file /home/daytona/workspace/mdi-decision-tree/MDI_Decision_Tree.png
MDI Decision Tree
Image · PNG

| Step | Node | Key Content |
|---|---|---|
| 1 | Entry / Presentation | MDI defined: subluxation/dislocation in ≥2 directions; inferior component obligatory (Neer & Foster 1980) |
| 2 | Initial Screening | Exclude voluntary dislocators and patients with psychological issues or secondary gain - absolute contraindications to surgery |
| 3 | Nonoperative Treatment | Mandatory first-line for ALL patients; structured PT ≥6-12 months |
| 4 | PT Programme Detail | Rotator cuff strengthening + scapular stabilisation (serratus ant., trapezius, rhomboids) + proprioceptive retraining |
| 5 | Response to PT Diamond | Adequate response → continue PT / activity modification. Failure after >1 year → proceed to surgery |
| 6 | Pre-Surgical Counselling | Counsel on inconsistent surgical outcomes; activity/occupation modification as alternative |
| 7 | EUA + Sulcus Sign | Confirm direction under anaesthesia; sulcus persisting in ER → add Rotator Interval Closure |
| 8 | Direction Branch (3 arms) | Anteroinferior / Posteroinferior / Pan-MDI (ant+post+inf) - each with arthroscopic vs open options |
| 9 | Rehabilitation Phases | Phase I-IV: immobilisation → passive ROM → active strengthening → sport-specific training (0-12 months) |