Diagnosis management and prescription for a patient with carpal tunnel syndrome. Must include the background like metabolic disease or long-term compression over flexor retinaculum!
"carpal tunnel syndrome"[MeSH Terms] AND management

| Category | Conditions |
|---|---|
| Fluid balance / hormonal | Hypothyroidism, pregnancy, menopause, eclampsia, renal failure, long-term hemodialysis |
| Neuropathic | Diabetes mellitus (peripheral neuropathy), alcoholism, double-crush syndrome |
| Inflammatory | Rheumatoid arthritis, gout, nonspecific tenosynovitis, infection |
| Autoimmune / infiltrative | Amyloidosis (infiltration of the TCL), lupus erythematosus, scleroderma, multiple sclerosis, Paget disease |
| Endocrine/structural | Acromegaly (bony overgrowth narrows tunnel), lysosomal storage disease |
Key point: Bradley and Daroff's Neurology states that pregnancy, diabetes, rheumatoid arthritis, hypothyroidism, sarcoidosis, acromegaly, and amyloid infiltration should be screened with blood studies in ALL newly diagnosed CTS patients. - Bradley and Daroff's Neurology in Clinical Practice, p. 549
| Finding | Notes |
|---|---|
| Tinel's sign | Tap over wrist flexor retinaculum → electric tingling into the median nerve distribution. Most specific but least sensitive |
| Phalen's maneuver | Sustained wrist flexion x60 sec → numbness/paresthesia. Most sensitive (74%), false-positive ~25% |
| Durkan (Carpal Compression) test | Direct compression over TCL x30 sec. Most diagnostically useful: sensitivity 87%, specificity 90% - more accurate than Tinel or Phalen |
| Thenar atrophy | APB wasting in advanced/chronic cases |
| Two-point discrimination >5 mm | Indicates significant sensory fiber loss |
| Finding | Points |
|---|---|
| Numbness predominantly in median nerve distribution | 3.5 |
| Nocturnal symptoms | 4.0 |
| Thenar atrophy or weakness | 5.0 |
| Positive Phalen test | 5.0 |
| Loss of two-point discrimination (>5 mm) | 4.5 |
| Positive Tinel sign | 4.0 |
| Technique | Notes |
|---|---|
| Open CTR (standard or mini-palm) | Longitudinal incision just ulnar to midline of ring finger, 2-3 cm from distal wrist crease. Direct visualization ensures nerve safety. Most widely practiced |
| Endoscopic CTR | 1-2 small portal incisions; faster return to work, less scar tenderness. Meta-analysis (PMID 38768022) shows equivalent long-term outcomes vs. open; endoscopic generally preferred per Goldman-Cecil |

CONSERVATIVE PHASE:
1. Neutral wrist splint – wear nightly; can use during provoking activities
2. Nerve gliding exercises – daily programme, refer to hand therapist
3. Ergonomic assessment – workplace wrist positioning
INJECTION (moderate symptoms or diagnostic):
4. Methylprednisolone acetate 40 mg (1 mL) + 1% lidocaine 1 mL
→ Ultrasound-guided injection into carpal tunnel (palmar-ulnar to palmaris longus)
→ May repeat once if partial relief; limit to 2-3 total injections
PHARMACOLOGICAL ADJUNCTS:
5. Prednisolone 20 mg oral once daily x10-14 days (for acute flares)
[NSAIDs – not recommended; no better than placebo for CTS]
6. Treat underlying cause:
- Hypothyroidism → Levothyroxine titrated to TSH 0.5-2.0 mIU/L
- Diabetes → Optimize glycemic control (HbA1c <7%)
- RA → DMARDs per rheumatology; consider concurrent tenosynovectomy if surgery needed
- Renal failure / dialysis amyloidosis → dialysis optimization; early surgery referral
SURGICAL REFERRAL (if ≥3 failure predictors, or progressive motor signs):
7. Carpal tunnel release – endoscopic or open mini-palm technique
(preoperative NCS mandatory)
| Scenario | Management |
|---|---|
| Pregnancy | Splinting + local injection; usually resolves post-delivery |
| Hypothyroid CTS | Thyroid replacement first - may resolve CTS without surgery |
| Diabetic CTS | NCS may underestimate severity; surgical outcome still good |
| Dialysis / amyloid CTS | Early CTR recommended; do not delay - amyloid rarely responds to conservative care |
| Post-Colles fracture CTS | Loosen cast, change wrist position to neutral; if persists → urgent surgery |
| RA with tenosynovitis | CTR + concurrent tenosynovectomy ± opponensplasty (elderly with thenar wasting) |
Generate a prescription template (PDF) for CTS management by severity level
ls -la /home/daytona/workspace/ 2>/dev/null && mkdir -p /home/daytona/workspace/…
~/cts-prescription/generate_cts_rx.py
"""
CTS Prescription Template PDF Generator
Uses reportlab for professional clinical layout
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT, TA_JUSTIFY
from reportlab.platypus import PageBreak
from reportlab.lib.colors import HexColor
import os
OUTPUT_PATH = "/home/daytona/workspace/cts-prescription/CTS_Prescription_Template.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
C_DARK_BLUE = HexColor("#1a3a5c") # header, section titles
C_MED_BLUE = HexColor("#2e6da4") # sub-headers, accents
C_MILD_GREEN = HexColor("#e8f5e9") # mild severity bg
C_MOD_YELLOW = HexColor("#fffde7") # moderate severity bg
C_SEV_RED = HexColor("#fce4ec") # severe severity bg
C_LIGHT_GRAY = HexColor("#f5f7fa") # alternating row
C_MID_GRAY = HexColor("#90a4ae") # secondary text
C_WHITE = colors.white
C_BLACK = colors.black
C_BORDER = HexColor("#b0bec5")
# ── Build document ───────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT_PATH,
pagesize=A4,
rightMargin=18*mm, leftMargin=18*mm,
topMargin=14*mm, bottomMargin=18*mm,
title="Carpal Tunnel Syndrome – Prescription Template",
author="Orris Medical AI"
)
W = A4[0] - 36*mm # usable width
styles = getSampleStyleSheet()
# Custom paragraph styles
def make_style(name, parent="Normal", **kw):
return ParagraphStyle(name, parent=styles[parent], **kw)
hdr_title = make_style("HdrTitle", fontSize=17, textColor=C_WHITE,
fontName="Helvetica-Bold", leading=22, alignment=TA_CENTER)
hdr_sub = make_style("HdrSub", fontSize=9, textColor=HexColor("#cfe4ff"),
fontName="Helvetica", leading=13, alignment=TA_CENTER)
sec_title = make_style("SecTitle", fontSize=11, textColor=C_WHITE,
fontName="Helvetica-Bold", leading=15, alignment=TA_LEFT,
leftIndent=4)
sev_label = make_style("SevLabel", fontSize=10, textColor=C_DARK_BLUE,
fontName="Helvetica-Bold", leading=14)
body = make_style("Body", fontSize=8.5, leading=13, textColor=C_BLACK)
body_bold = make_style("BodyBold", fontSize=8.5, leading=13,
textColor=C_DARK_BLUE, fontName="Helvetica-Bold")
small = make_style("Small", fontSize=7.5, leading=11, textColor=HexColor("#546e7a"))
rx_item = make_style("RxItem", fontSize=8.5, leading=13,
leftIndent=8, firstLineIndent=-8)
note_style = make_style("Note", fontSize=7.8, leading=11.5,
textColor=HexColor("#37474f"), fontName="Helvetica-Oblique")
footer_s = make_style("Footer", fontSize=7, textColor=C_MID_GRAY,
alignment=TA_CENTER)
# ── Helper: coloured section banner ─────────────────────────────────────────
def section_banner(text, bg=C_DARK_BLUE, width=None):
w = width or W
return Table(
[[Paragraph(text, sec_title)]],
colWidths=[w],
style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
])
)
def severity_banner(text, bg, text_color=C_DARK_BLUE):
st = make_style(f"SevBan_{text}", fontSize=11, textColor=text_color,
fontName="Helvetica-Bold", leading=16, alignment=TA_LEFT)
return Table(
[[Paragraph(text, st)]],
colWidths=[W],
style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 0.8, C_BORDER),
])
)
def rx_table(rows, col_widths=None):
"""Render a 2-column key/value table for prescriptions."""
cw = col_widths or [50*mm, W - 50*mm]
data = []
for label, val, color in rows:
data.append([
Paragraph(f"<b>{label}</b>", body_bold),
Paragraph(val, body)
])
style = TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("GRID", (0,0), (-1,-1), 0.4, C_BORDER),
])
# Alternating row backgrounds
for i, (_, _, c) in enumerate(rows):
bg = c if c else (C_LIGHT_GRAY if i % 2 == 0 else C_WHITE)
style.add("BACKGROUND", (0, i), (-1, i), bg)
return Table(data, colWidths=cw, style=style, hAlign="LEFT")
def drug_box(lines, bg=C_WHITE):
"""A bordered box listing drug entries."""
rows = [[Paragraph(l, body)] for l in lines]
t = Table(rows, colWidths=[W],
style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("BOX", (0,0), (-1,-1), 0.8, C_MED_BLUE),
("INNERGRID", (0,0), (-1,-1), 0.3, C_BORDER),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 10),
])
)
return t
# ═══════════════════════════════════════════════════════════════════════════════
# CONTENT
# ═══════════════════════════════════════════════════════════════════════════════
story = []
# ── HEADER ───────────────────────────────────────────────────────────────────
header_data = [[
Paragraph("CARPAL TUNNEL SYNDROME", hdr_title),
],[
Paragraph("Clinical Prescription Template · Stratified by Severity Level", hdr_sub),
]]
header = Table(header_data, colWidths=[W],
style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_DARK_BLUE),
("TOPPADDING", (0,0), (0,0), 10),
("BOTTOMPADDING", (0,1), (0,1), 10),
("LEFTPADDING", (0,0), (-1,-1), 6),
("BOX", (0,0), (-1,-1), 1.5, C_MED_BLUE),
])
)
story.append(header)
story.append(Spacer(1, 4*mm))
# ── PATIENT DETAILS BOX ──────────────────────────────────────────────────────
story.append(section_banner("▸ PATIENT & CLINICIAN DETAILS"))
story.append(Spacer(1, 1*mm))
pt_fields = [
["Patient Name:", "_______________________________", "Date:", "____________"],
["Age / Sex:", "____________ / ____________", "MRN/ID:", "____________"],
["Clinician:", "_______________________________", "Signature:", "____________"],
["Facility:", "_______________________________", "Stamp:", ""],
]
pt_tbl = Table(pt_fields,
colWidths=[28*mm, 60*mm, 22*mm, 60*mm],
style=TableStyle([
("FONTNAME", (0,0), (-1,-1), "Helvetica"),
("FONTNAME", (0,0), (0,-1), "Helvetica-Bold"), # labels bold
("FONTNAME", (2,0), (2,-1), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 4),
("GRID", (0,0), (-1,-1), 0.4, C_BORDER),
("BACKGROUND", (0,0), (-1,-1), C_LIGHT_GRAY),
])
)
story.append(pt_tbl)
story.append(Spacer(1, 3*mm))
# ── ASSESSMENT SECTION ───────────────────────────────────────────────────────
story.append(section_banner("▸ CLINICAL ASSESSMENT"))
story.append(Spacer(1, 1*mm))
assess_rows = [
("Dominant Hand", "Right / Left / Bilateral", None),
("CTS-6 Score", "_______ /26 (≥12 = high probability CTS)", None),
("Phalen Test", "Positive / Negative — onset at ______ seconds", None),
("Tinel Sign", "Positive / Negative", None),
("Durkan Test", "Positive / Negative", None),
("Thenar Atrophy", "None / Mild / Moderate / Severe", None),
("2-Point Discrimination", "_____ mm (>5 mm = abnormal)", None),
("Symptom Duration", "_______ months", None),
("Symptom Pattern", "Intermittent / Constant", None),
("NCS / EMG", "Not done / Pending / Done: DML _____ ms, Sensory latency _____ ms", None),
("Ultrasound CSA", "Not done / Done: _____ mm² at pisiform level", None),
("Underlying Cause", "Idiopathic / DM / Hypothyroid / RA / Pregnancy / Amyloid / CKD / Other: _________", None),
]
story.append(rx_table(assess_rows, col_widths=[55*mm, W-55*mm]))
story.append(Spacer(1, 3*mm))
# ── SEVERITY CLASSIFICATION ──────────────────────────────────────────────────
story.append(section_banner("▸ SEVERITY CLASSIFICATION"))
story.append(Spacer(1, 1*mm))
sev_data = [
[Paragraph("<b>Severity</b>", body_bold),
Paragraph("<b>Clinical Features</b>", body_bold),
Paragraph("<b>NCS Findings</b>", body_bold),
Paragraph("<b>Circled Level</b>", body_bold)],
[Paragraph("<b>MILD</b>", make_style("M", fontSize=8.5, textColor=HexColor("#2e7d32"), fontName="Helvetica-Bold")),
Paragraph("Intermittent paresthesia, no atrophy, nocturnal symptoms only, normal grip strength", body),
Paragraph("Mildly prolonged sensory latency; normal or borderline motor latency", body),
Paragraph("MILD", make_style("M2", fontSize=9, alignment=TA_CENTER, fontName="Helvetica-Bold", textColor=HexColor("#2e7d32")))],
[Paragraph("<b>MODERATE</b>", make_style("Mo", fontSize=8.5, textColor=HexColor("#e65100"), fontName="Helvetica-Bold")),
Paragraph("Frequent paresthesia, daytime symptoms, mild thenar weakness, positive Phalen <30 s", body),
Paragraph("Prolonged DML (>4.5 ms) and/or sensory latency (>3.5 ms)", body),
Paragraph("MODERATE", make_style("Mo2", fontSize=9, alignment=TA_CENTER, fontName="Helvetica-Bold", textColor=HexColor("#e65100")))],
[Paragraph("<b>SEVERE</b>", make_style("S", fontSize=8.5, textColor=HexColor("#b71c1c"), fontName="Helvetica-Bold")),
Paragraph("Constant paresthesia, thenar atrophy, objective sensory loss, grip weakness, symptoms >10 months", body),
Paragraph("Markedly prolonged latencies; fibrillations / positive waves in APB on EMG", body),
Paragraph("SEVERE", make_style("S2", fontSize=9, alignment=TA_CENTER, fontName="Helvetica-Bold", textColor=HexColor("#b71c1c")))],
]
sev_tbl = Table(sev_data, colWidths=[24*mm, 70*mm, 54*mm, 22*mm],
style=TableStyle([
("BACKGROUND", (0,0), (-1,0), C_DARK_BLUE),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("BACKGROUND", (0,1), (-1,1), C_MILD_GREEN),
("BACKGROUND", (0,2), (-1,2), C_MOD_YELLOW),
("BACKGROUND", (0,3), (-1,3), C_SEV_RED),
("GRID", (0,0), (-1,-1), 0.5, C_BORDER),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("ALIGN", (3,0), (3,-1), "CENTER"),
("BOX", (3,1), (3,1), 1.5, HexColor("#2e7d32")),
("BOX", (3,2), (3,2), 1.5, HexColor("#e65100")),
("BOX", (3,3), (3,3), 1.5, HexColor("#b71c1c")),
])
)
story.append(sev_tbl)
story.append(Spacer(1, 4*mm))
# ══════════════════════════════════════════════════════════════════════════════
# PAGE 2 START — Prescription by severity
# ══════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
# ── PAGE 2 MINI HEADER ───────────────────────────────────────────────────────
mini_hdr = Table([[Paragraph("CTS PRESCRIPTION — BY SEVERITY LEVEL",
make_style("MH", fontSize=12, fontName="Helvetica-Bold", textColor=C_WHITE, alignment=TA_CENTER))]],
colWidths=[W],
style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING", (0,0), (-1,-1), 7),
])
)
story.append(mini_hdr)
story.append(Spacer(1, 3*mm))
# ────────────────────────────────────────────────────────────────────────────
# MILD CTS
# ────────────────────────────────────────────────────────────────────────────
story.append(KeepTogether([
severity_banner("🟢 MILD CTS — Intermittent symptoms, no motor deficit", C_MILD_GREEN),
Spacer(1, 2*mm),
section_banner("Non-Pharmacological", bg=HexColor("#43a047"), width=W),
]))
story.append(Spacer(1, 1*mm))
mild_nonpharm = [
("<b>1.</b> Neutral wrist splint",
"Wear nightly (6–8 h). May also wear during provoking activities. "
"Splint should hold wrist at 0° (neutral), not extended or flexed.", None),
("<b>2.</b> Activity modification",
"Avoid sustained wrist flexion/extension. Ergonomic review of keyboard/workstation. "
"Wrist rests during typing. Reduce vibratory tool use.", None),
("<b>3.</b> Nerve gliding exercises",
"Daily programme × 10 repetitions each. Refer to hand therapist if available. "
"Tendon gliding + median nerve mobilisation sequence.", None),
]
story.append(rx_table(mild_nonpharm, col_widths=[40*mm, W-40*mm]))
story.append(Spacer(1, 2*mm))
story.append(section_banner("Pharmacological", bg=HexColor("#43a047"), width=W))
story.append(Spacer(1, 1*mm))
mild_pharm_lines = [
"💊 <b>Rx 1 — Corticosteroid Injection</b> (first-line if splinting fails at 4–6 weeks)",
" Drug: Methylprednisolone acetate 40 mg (1 mL) + 1% Lidocaine HCl 1 mL",
" Route: Intracarpal (palmar approach, ulnar to palmaris longus tendon)",
" Technique: Ultrasound-guided preferred; needle directed distally at 30–45° angle",
" Frequency: Single injection; may repeat once after 4–6 weeks if partial response",
" Max: 2–3 total injections — do NOT inject directly into the median nerve",
"",
"💊 <b>Rx 2 — Oral Prednisolone</b> (if injection declined or for acute flare)",
" Prednisolone 20 mg orally once daily × 10–14 days (taper not required for short course)",
" Take with food to reduce GI irritation",
"",
"⚠️ <b>NSAIDs:</b> Not recommended — evidence shows no benefit over placebo for CTS symptoms",
" (May be used adjunctively for coexisting tenosynovitis at clinician's discretion)",
]
story.append(drug_box(mild_pharm_lines, bg=HexColor("#f1f8e9")))
story.append(Spacer(1, 2*mm))
story.append(section_banner("Investigations / Workup for Underlying Cause", bg=HexColor("#43a047"), width=W))
story.append(Spacer(1, 1*mm))
mild_ix_lines = [
"□ TSH (hypothyroidism) □ Fasting glucose + HbA1c (diabetes)",
"□ Renal function / eGFR (CKD) □ RF / anti-CCP (rheumatoid arthritis)",
"□ Pregnancy test (if applicable) □ Consider ESR, CRP, ANA if autoimmune suspected",
]
story.append(drug_box(mild_ix_lines, bg=HexColor("#f1f8e9")))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
"📅 <b>Follow-up:</b> Review at 4–6 weeks. If no improvement with splint + injection → upgrade to moderate protocol.",
note_style))
story.append(Spacer(1, 4*mm))
# ────────────────────────────────────────────────────────────────────────────
# MODERATE CTS
# ────────────────────────────────────────────────────────────────────────────
story.append(KeepTogether([
severity_banner("🟡 MODERATE CTS — Frequent symptoms, mild motor signs", C_MOD_YELLOW),
Spacer(1, 2*mm),
section_banner("Non-Pharmacological", bg=HexColor("#f9a825"), width=W),
]))
story.append(Spacer(1, 1*mm))
mod_nonpharm = [
("<b>1.</b> Neutral wrist splint",
"Full-time splinting for 4–6 weeks (day + night), then reassess. "
"Removable thermoplastic splint preferred.", None),
("<b>2.</b> Workplace ergonomics",
"Formal occupational therapy referral. Workstation redesign, modified duties if required.", None),
("<b>3.</b> Nerve gliding exercises",
"Twice daily. Include tendon gliding, nerve mobilisation, and opposition strengthening.", None),
("<b>4.</b> Treat underlying cause",
"Optimise thyroid replacement, glycaemic control, RA disease-modifying therapy, "
"or diuresis (pregnancy/renal).", None),
]
story.append(rx_table(mod_nonpharm, col_widths=[40*mm, W-40*mm]))
story.append(Spacer(1, 2*mm))
story.append(section_banner("Pharmacological", bg=HexColor("#f9a825"), width=W))
story.append(Spacer(1, 1*mm))
mod_pharm_lines = [
"💊 <b>Rx 1 — Corticosteroid Injection (First-line)</b>",
" Methylprednisolone acetate 40 mg + 1% Lidocaine 1 mL — intracarpal, as above",
" If 90% improvement → continues conservative; if partial → plan surgical referral",
"",
"💊 <b>Rx 2 — Oral Prednisolone (bridge or injection not feasible)</b>",
" Prednisolone 25 mg once daily × 14 days; reduce to 12.5 mg × 7 days, then stop",
"",
"💊 <b>Rx 3 — Treat underlying metabolic disease (examples):</b>",
" Hypothyroidism: Levothyroxine — start 25–50 mcg/day; titrate to TSH 0.5–2.0 mIU/L",
" Diabetes mellitus: Optimise HbA1c to <7%; add or adjust antidiabetic agent",
" Rheumatoid arthritis: Continue/escalate DMARDs per rheumatology; consider MTX ± biologic",
" Pregnancy: Neutral splint + single injection safe; most cases resolve post-partum",
" CKD / dialysis: Optimise dialysis adequacy; early surgical referral (amyloid-related CTS)",
"",
"💊 <b>Neuropathic pain adjunct</b> (if burning/dysaesthetic component prominent):",
" Gabapentin 100–300 mg at night; titrate cautiously. Or Amitriptyline 10 mg nocte.",
" Use with caution in elderly; monitor for sedation.",
]
story.append(drug_box(mod_pharm_lines, bg=HexColor("#fffde7")))
story.append(Spacer(1, 2*mm))
story.append(section_banner("Investigations", bg=HexColor("#f9a825"), width=W))
story.append(Spacer(1, 1*mm))
mod_ix_lines = [
"□ NCS / EMG — mandatory before surgical referral (DML, sensory latency, APB EMG)",
"□ Wrist ultrasound — median nerve CSA (cutoff >10 mm² at pisiform)",
"□ Blood: TSH, HbA1c, RF/anti-CCP, renal panel, FBC, SPEP if amyloid suspected",
"□ Wrist X-ray — if post-traumatic or arthropathy suspected",
]
story.append(drug_box(mod_ix_lines, bg=HexColor("#fffde7")))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
"📅 <b>Follow-up:</b> 4–6 weeks. If ≥3 failure predictors present (age >50, duration >10 months, "
"constant paresthesia, stenosing tenosynovitis, Phalen <30 s) → refer for surgery.",
note_style))
story.append(Spacer(1, 4*mm))
# ────────────────────────────────────────────────────────────────────────────
# SEVERE CTS (page 3)
# ────────────────────────────────────────────────────────────────────────────
story.append(PageBreak())
# Mini repeat header
story.append(mini_hdr)
story.append(Spacer(1, 3*mm))
story.append(KeepTogether([
severity_banner("🔴 SEVERE CTS — Constant symptoms, thenar atrophy, motor deficit", C_SEV_RED),
Spacer(1, 2*mm),
section_banner("Immediate Management", bg=HexColor("#c62828"), width=W),
]))
story.append(Spacer(1, 1*mm))
sev_immediate = [
("<b>URGENT surgical referral</b>",
"Refer to hand surgery / orthopaedic surgery for carpal tunnel release (CTR). "
"Thenar atrophy and motor weakness indicate irreversible nerve damage risk.", None),
("<b>Cease provoking activities</b>",
"Modified duties or temporary work cessation if occupation involves repetitive wrist use.", None),
("<b>Full-time neutral wrist splint</b>",
"Continue while awaiting surgery to limit further compression.", None),
("<b>Corticosteroid injection</b>",
"May provide temporary relief and confirms diagnosis (90% who respond will benefit from surgery). "
"Do NOT delay surgical referral awaiting injection response.", None),
]
story.append(rx_table(sev_immediate, col_widths=[45*mm, W-45*mm]))
story.append(Spacer(1, 2*mm))
story.append(section_banner("Surgical Options", bg=HexColor("#c62828"), width=W))
story.append(Spacer(1, 1*mm))
sev_surg_lines = [
"🔪 <b>Option 1 — Open Carpal Tunnel Release (standard / mini-palm)</b>",
" Longitudinal incision distal to wrist crease, ulnar to ring finger midline (~2–3 cm)",
" Division of flexor retinaculum (TCL) under direct vision; nerve safety confirmed before release",
" Preferred when anatomy uncertain, revision case, or concurrent tenosynovectomy needed",
"",
"🔪 <b>Option 2 — Endoscopic CTR (ECTR)</b>",
" 1–2 portal technique; faster return to function, less pillar pain",
" Equivalent long-term outcomes to open CTR (meta-analysis 2024, PMID 38768022)",
" Generally preferred when straightforward anatomy",
"",
"⚕️ <b>Special surgical considerations by underlying cause:</b>",
" RA / tenosynovitis: CTR + concurrent tenosynovectomy; if thenar atrophy + poor opposition",
" → Camitz palmaris longus opponensplasty (especially in elderly patients)",
" Post-Colles fracture: Loosen cast → change wrist to neutral; if persists → urgent CTR",
" Dialysis amyloid: Bilateral staged CTR; do not delay — amyloid does not respond conservatively",
" Age >70 / advanced compression: Counsel that thenar atrophy may not fully resolve post-CTR",
]
story.append(drug_box(sev_surg_lines, bg=HexColor("#ffebee")))
story.append(Spacer(1, 2*mm))
story.append(section_banner("Pre-operative Investigations", bg=HexColor("#c62828"), width=W))
story.append(Spacer(1, 1*mm))
sev_ix_lines = [
"□ NCS / EMG — mandatory (DML >4.5 ms, sensory latency >3.5 ms; fibrillations in APB on EMG)",
"□ Wrist ultrasound (median nerve CSA) if NCS equivocal",
"□ FBC, coagulation (INR/APTT), renal/liver function, blood glucose",
"□ Wrist X-ray (PA + lateral) — assess carpal anatomy, osteophytes, fracture deformity",
"□ MRI — only if space-occupying lesion (ganglion, lipoma, tumour) suspected",
"□ Anaesthetic review if indicated (comorbidities)",
]
story.append(drug_box(sev_ix_lines, bg=HexColor("#ffebee")))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
"📅 <b>Post-operative follow-up:</b> Wound review at 10–14 days. Maximum improvement expected within "
"first 6 months post-CTR. Sensory recovery precedes motor recovery. Physiotherapy for grip strengthening "
"and scar management. Thenar atrophy resolves slowly and may be incomplete.",
note_style))
story.append(Spacer(1, 4*mm))
# ────────────────────────────────────────────────────────────────────────────
# UNDERLYING CAUSE TREATMENT QUICK REFERENCE
# ────────────────────────────────────────────────────────────────────────────
story.append(section_banner("▸ TREATMENT OF UNDERLYING CAUSE — QUICK REFERENCE"))
story.append(Spacer(1, 1*mm))
cause_data = [
[Paragraph("<b>Condition</b>", body_bold),
Paragraph("<b>Target / Goal</b>", body_bold),
Paragraph("<b>First-line Treatment</b>", body_bold),
Paragraph("<b>Notes</b>", body_bold)],
[Paragraph("Hypothyroidism", body),
Paragraph("TSH 0.5–2.0 mIU/L", body),
Paragraph("Levothyroxine 25–100 mcg/day PO", body),
Paragraph("CTS may resolve with euthyroid state alone", small)],
[Paragraph("Diabetes mellitus", body),
Paragraph("HbA1c <7%", body),
Paragraph("Optimise antidiabetic regimen per guidelines", body),
Paragraph("NCS may underestimate severity; surgical outcome still favourable", small)],
[Paragraph("Rheumatoid arthritis", body),
Paragraph("DAS28 remission", body),
Paragraph("Methotrexate ± biologic DMARD", body),
Paragraph("Concurrent tenosynovectomy at CTR", small)],
[Paragraph("Pregnancy", body),
Paragraph("Symptom control", body),
Paragraph("Neutral splint; single intracarpal steroid injection if needed", body),
Paragraph("Usually resolves post-partum; avoid surgery unless severe", small)],
[Paragraph("CKD / Dialysis amyloid", body),
Paragraph("Symptom control; prevent progression", body),
Paragraph("Optimise dialysis; early CTR referral", body),
Paragraph("Amyloid infiltration of TCL does not respond to conservative care", small)],
[Paragraph("Acromegaly", body),
Paragraph("Normalise IGF-1 / GH", body),
Paragraph("Somatostatin analogue (octreotide) or surgery", body),
Paragraph("CTS from bony tunnel narrowing; CTR often required regardless", small)],
[Paragraph("Obesity", body),
Paragraph("BMI <30", body),
Paragraph("Lifestyle modification; bariatric referral if BMI >40", body),
Paragraph("Weight loss may reduce tunnel pressure and fluid retention", small)],
]
cause_tbl = Table(cause_data, colWidths=[28*mm, 28*mm, 62*mm, 52*mm],
style=TableStyle([
("BACKGROUND", (0,0), (-1,0), C_DARK_BLUE),
("TEXTCOLOR", (0,0), (-1,0), C_WHITE),
("GRID", (0,0), (-1,-1), 0.4, C_BORDER),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [C_WHITE, C_LIGHT_GRAY]),
])
)
story.append(cause_tbl)
story.append(Spacer(1, 4*mm))
# ────────────────────────────────────────────────────────────────────────────
# CLINICIAN NOTES BOX
# ────────────────────────────────────────────────────────────────────────────
story.append(section_banner("▸ CLINICIAN NOTES"))
story.append(Spacer(1, 1*mm))
notes_lines = ["" for _ in range(5)]
notes_data = [[Paragraph("____________________________________________________________________________________"
"____________________________________________________________________________________",
small)] for _ in range(5)]
notes_tbl = Table(notes_data, colWidths=[W],
style=TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_LIGHT_GRAY),
("BOX", (0,0), (-1,-1), 0.8, C_BORDER),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 8),
])
)
story.append(notes_tbl)
story.append(Spacer(1, 4*mm))
# ── FOOTER ───────────────────────────────────────────────────────────────────
story.append(HRFlowable(width=W, thickness=0.5, color=C_BORDER))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
"Sources: Campbell's Operative Orthopaedics 15e | Goldman-Cecil Medicine | Bradley and Daroff's Neurology | "
"Textbook of Family Medicine 9e | Tintinalli's Emergency Medicine · Generated by Orris Medical AI · May 2026",
footer_s
))
story.append(Paragraph(
"⚠ This template is a clinical aide-memoire. All prescriptions must be verified by a licensed clinician. "
"Doses should be adjusted for individual patient factors including renal/hepatic function, age, weight and comorbidities.",
make_style("Disclaimer", fontSize=7, textColor=HexColor("#b71c1c"), alignment=TA_CENTER, leading=10)
))
# ── BUILD ────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF generated: {OUTPUT_PATH}")
cd /home/daytona/workspace/cts-prescription && python generate_cts_rx.py
ls -lh /home/daytona/workspace/cts-prescription/CTS_Prescription_Template.pdf
CTS Prescription Template
PDF Document · PDF