My mother is suffering from frozen shoulder suggest it's treatment

Reading File
Finding Sources
Searching PubMed

"frozen shoulder" OR "adhesive capsulitis" AND treatment

Searching the Web

frozen shoulder adhesive capsulitis treatment guidelines 2024 2025

Reading File
Finding Sources
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
I now have excellent, comprehensive content from multiple authoritative textbooks plus recent PubMed data. Let me compile the full treatment guide.

Frozen Shoulder (Adhesive Capsulitis) - Treatment Guide

Frozen shoulder (adhesive capsulitis) is a self-limiting condition that causes progressive pain and global loss of shoulder movement. It most commonly affects women in their 40s-50s and is strongly associated with diabetes, thyroid disease, cardiovascular disease, and prolonged immobility. The good news is that the vast majority of patients recover - about 94% regain normal function, though it can take 1-2 years and sometimes longer in diabetics.

Understanding the 3 Stages (Treatment differs by stage)

StageWhat's happeningDurationMain symptom
1. Freezing (Painful)Inflammation, severe pain with any movementWeeks to monthsPain dominates
2. Frozen (Stiffening)Adhesions form, capsule contracts, pain lessens4-12 monthsStiffness dominates
3. Thawing (Resolution)Motion gradually returnsMonths to yearsGradual improvement

Treatment Options (Stage by Stage)

Stage 1 - Freezing Phase: Focus on Pain Control

1. Analgesics & Anti-Inflammatories (NSAIDs)
2. Corticosteroid Injection
  • An injection of steroid (e.g. methylprednisolone) into the shoulder joint (glenohumeral) or the space above the rotator cuff (subacromial)
  • Provides significant short-term pain relief, especially in the painful/freezing phase
  • Effect is stronger in the first 6 weeks - early injection gives better results
  • Usually done under ultrasound guidance for accuracy
  • As per Bailey & Love's Surgery (28th Ed), this is one of the first-line interventions
3. Heat Therapy
  • Self-application of heat 3-5 times daily helps with pain self-management
  • 2025 ACOEM guidelines recommend this as a low-harm adjunct

Stage 2 - Frozen Phase: Focus on Restoring Movement

4. Physiotherapy (Physical Therapy) - MOST IMPORTANT
  • A structured program of stretching, range-of-motion exercises, and strengthening
  • Includes: pendulum swings, wall climbing, cross-body stretches, external rotation exercises
  • A 2023 meta-analysis (PMID: 36861780) confirmed manual therapy combined with exercise significantly improves pain and function
  • Key rule: Do NOT immobilize the shoulder - keep using the arm within pain-free range. Immobility makes it worse
  • Avoid painful overhead reaching and sleeping on the affected side
5. Manual Therapy (done by a physiotherapist)
  • Mobilization techniques applied by a trained physiotherapist - especially helpful for moderate-to-severe cases
  • 2025 ACOEM guidelines give this a moderate evidence recommendation (Grade B)
6. Distension Injection (Hydrodilatation)
  • 20-30 mL of saline + local anaesthetic (± steroid) injected into the joint to stretch the capsule
  • A 2023 systematic review (PMID: 37496207) showed hydrodilatation significantly improves both pain and range of motion
  • Particularly useful in the stiffening phase - it facilitates physiotherapy afterward
  • Bailey & Love's recommends this specifically in the second phase

Adjunct Non-Surgical Options

7. Extracorporeal Shockwave Therapy (ESWT)
  • Recommended by 2025 guidelines as a useful option, especially if other treatments have not fully resolved the condition
8. Radiofrequency Ablation

Stage 3 or Prolonged Cases: Operative Treatment

If symptoms persist beyond 6-12 months despite conservative care, surgical options are considered. Both are effective at restoring motion and relieving pain - Campbell's Operative Orthopaedics (15th Ed, 2026) notes that early care-seeking is predictive of faster recovery.
9. Manipulation Under Anaesthesia (MUA)
  • The shoulder is gently but firmly moved through its full range while the patient is under general anaesthesia
  • Breaks down the tight capsule and adhesions
  • Quick recovery; effective for prolonged stiffness
10. Arthroscopic Capsular Release
  • A keyhole surgery where the contracted, thickened shoulder capsule is surgically cut and released
  • Gold standard for refractory cases
  • Faster return of motion vs MUA; lower risk of fracture
  • Bailey & Love's and Campbell's both recommend this for prolonged stiffness that does not respond to conservative measures

Home Exercise Program (Daily Routine for Your Mother)

These exercises should be done gently, slowly, within pain-free range - 2-3 times daily:
  1. Pendulum swings - Lean forward, let the arm hang, swing it in small circles
  2. Wall walking - Stand facing a wall, walk fingers up slowly as high as comfortable
  3. Cross-body stretch - Gently pull the affected arm across the chest with the other hand
  4. External rotation stretch - Stand in a doorway, elbow at 90°, gently push the forearm outward
  5. Towel stretch - Hold a towel behind the back with both hands and gently pull upward

Important Notes for Diabetic Patients

If your mother has diabetes, frozen shoulder tends to last longer (sometimes over 2 years), can be bilateral (both shoulders), and responds less completely to manipulation. Blood sugar control is important alongside shoulder treatment, as poor control is linked to worse outcomes.

When to See a Doctor Urgently

  • Sudden worsening of pain
  • Redness, warmth, or swelling (could indicate infection)
  • Fever with shoulder pain
  • Suspected fracture after a fall

Summary of Treatment by Priority

PriorityTreatmentWhen to use
FirstNSAIDs + physiotherapy + heatAll stages
SecondCorticosteroid injectionPainful/freezing phase
ThirdHydrodilatation (distension injection)Frozen/stiffening phase
FourthManual therapy + structured PTFrozen phase
FifthShockwave therapyAdjunct if needed
SixthMUA or arthroscopic releaseIf >6-12 months, no improvement
Sources: Bailey and Love's Short Practice of Surgery 28th Ed, Campbell's Operative Orthopaedics 15th Ed (2026), Firestein & Kelley's Textbook of Rheumatology, ACOEM 2025 Guidelines, and recent PubMed systematic reviews (PMIDs: 36861780, 37496207, 38538951).

Please encourage your mother to start physiotherapy as early as possible - early intervention is one of the strongest predictors of faster recovery. A consultation with an orthopedic surgeon or sports medicine physician would help determine which stage she is in and tailor the most appropriate treatment.

Create a PDF guide with home exercises and stretches she can print

Reading File
Running Command

ls -la /tmp/workspace/ 2>/dev/null || echo "workspace empty or missing"

Running Command

mkdir -p /tmp/workspace/frozen-shoulder && python3 -c "from reportlab.pdfgen import canvas; print('reportlab ok')"

Writing File

~/frozen-shoulder/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.lib.colors import HexColor

OUTPUT = "/tmp/workspace/frozen-shoulder/Frozen_Shoulder_Exercise_Guide.pdf"

# ── Colours ────────────────────────────────────────────────────────────────
DARK_BLUE   = HexColor("#1A3A5C")
MED_BLUE    = HexColor("#2E6DA4")
LIGHT_BLUE  = HexColor("#D6E8F7")
ACCENT      = HexColor("#E8A020")
LIGHT_GREY  = HexColor("#F5F5F5")
MID_GREY    = HexColor("#CCCCCC")
TEXT_DARK   = HexColor("#1C1C1C")
GREEN       = HexColor("#2E7D32")
RED         = HexColor("#C62828")
WHITE       = colors.white

# ── Document ───────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=1.8*cm, leftMargin=1.8*cm,
    topMargin=2*cm, bottomMargin=2*cm,
    title="Frozen Shoulder Home Exercise Guide",
    author="Orris Medical"
)

W, H = A4
CONTENT_W = W - 3.6*cm

# ── Styles ─────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

def style(name, **kw):
    return ParagraphStyle(name, **kw)

S_TITLE = style("MainTitle",
    fontName="Helvetica-Bold", fontSize=22,
    textColor=WHITE, alignment=TA_CENTER, leading=28,
    spaceAfter=4)

S_SUBTITLE = style("SubTitle",
    fontName="Helvetica", fontSize=11,
    textColor=LIGHT_BLUE, alignment=TA_CENTER, leading=16)

S_SECTION = style("Section",
    fontName="Helvetica-Bold", fontSize=13,
    textColor=WHITE, alignment=TA_LEFT, leading=18,
    spaceBefore=4, spaceAfter=4)

S_EXERCISE_TITLE = style("ExTitle",
    fontName="Helvetica-Bold", fontSize=11,
    textColor=DARK_BLUE, leading=14, spaceBefore=2)

S_BODY = style("Body",
    fontName="Helvetica", fontSize=9.5,
    textColor=TEXT_DARK, leading=14, alignment=TA_JUSTIFY)

S_BULLET = style("Bullet",
    fontName="Helvetica", fontSize=9.5,
    textColor=TEXT_DARK, leading=13,
    leftIndent=12, firstLineIndent=0)

S_WARNING = style("Warning",
    fontName="Helvetica-Bold", fontSize=9,
    textColor=RED, leading=13)

S_TIP = style("Tip",
    fontName="Helvetica-Oblique", fontSize=9,
    textColor=GREEN, leading=13)

S_NOTE = style("Note",
    fontName="Helvetica", fontSize=8.5,
    textColor=HexColor("#555555"), leading=12, alignment=TA_CENTER)

S_TABLE_HDR = style("TblHdr",
    fontName="Helvetica-Bold", fontSize=9,
    textColor=WHITE, alignment=TA_CENTER, leading=12)

S_TABLE_CELL = style("TblCell",
    fontName="Helvetica", fontSize=9,
    textColor=TEXT_DARK, leading=12)

S_SMALL_BOLD = style("SmBold",
    fontName="Helvetica-Bold", fontSize=8.5,
    textColor=DARK_BLUE, leading=12)

story = []

# ══════════════════════════════════════════════════════════════════════════
# HEADER BANNER (title block as a table)
# ══════════════════════════════════════════════════════════════════════════
header_data = [[
    Paragraph("Frozen Shoulder", S_TITLE),
], [
    Paragraph("Home Exercise & Stretch Guide", S_TITLE),
], [
    Paragraph("A printable daily programme for recovery from adhesive capsulitis", S_SUBTITLE),
]]

header_table = Table(header_data, colWidths=[CONTENT_W])
header_table.setStyle(TableStyle([
    ("BACKGROUND",  (0,0), (-1,-1), DARK_BLUE),
    ("TOPPADDING",  (0,0), (-1,0),  16),
    ("BOTTOMPADDING",(0,-1),(-1,-1), 14),
    ("LEFTPADDING", (0,0), (-1,-1), 10),
    ("RIGHTPADDING",(0,0), (-1,-1), 10),
    ("ROWBACKGROUNDS",(0,0),(-1,-1),[DARK_BLUE]),
]))
story.append(header_table)
story.append(Spacer(1, 10))

# ══════════════════════════════════════════════════════════════════════════
# IMPORTANT NOTICE BOX
# ══════════════════════════════════════════════════════════════════════════
notice_data = [[
    Paragraph(
        "<b>Before You Start:</b> Always warm the shoulder with a heat pack or warm shower for "
        "5-10 minutes before exercising. Work within a <b>pain-free or mild-discomfort range</b> only. "
        "Stop immediately if you feel sharp pain. Do each session <b>2-3 times daily.</b>",
        style("NoticeText", fontName="Helvetica", fontSize=9.5,
              textColor=HexColor("#7B3F00"), leading=14)
    )
]]
notice_table = Table(notice_data, colWidths=[CONTENT_W])
notice_table.setStyle(TableStyle([
    ("BACKGROUND",  (0,0), (-1,-1), HexColor("#FFF3CD")),
    ("BOX",         (0,0), (-1,-1), 1.2, HexColor("#E8A020")),
    ("TOPPADDING",  (0,0), (-1,-1), 8),
    ("BOTTOMPADDING",(0,0),(-1,-1), 8),
    ("LEFTPADDING", (0,0), (-1,-1), 10),
    ("RIGHTPADDING",(0,0), (-1,-1), 10),
]))
story.append(notice_table)
story.append(Spacer(1, 12))


# ══════════════════════════════════════════════════════════════════════════
# HELPER: section header
# ══════════════════════════════════════════════════════════════════════════
def section_header(text, color=MED_BLUE):
    data = [[Paragraph(text, S_SECTION)]]
    t = Table(data, colWidths=[CONTENT_W])
    t.setStyle(TableStyle([
        ("BACKGROUND",  (0,0),(-1,-1), color),
        ("TOPPADDING",  (0,0),(-1,-1), 6),
        ("BOTTOMPADDING",(0,0),(-1,-1), 6),
        ("LEFTPADDING", (0,0),(-1,-1), 10),
    ]))
    return t

# ── Helper: exercise card ──────────────────────────────────────────────────
def exercise_card(number, name, reps, duration, how_to, tip=None, warning=None):
    """Returns a KeepTogether block for one exercise."""
    items = []

    # Title row: number badge + name + reps
    badge_data = [[
        Paragraph(f"<b>{number}</b>",
                  style("Badge", fontName="Helvetica-Bold", fontSize=12,
                        textColor=WHITE, alignment=TA_CENTER, leading=14)),
        Paragraph(f"<b>{name}</b>",
                  style("EName", fontName="Helvetica-Bold", fontSize=11,
                        textColor=DARK_BLUE, leading=14)),
        Paragraph(f"{reps}<br/><font size='8' color='#555555'>{duration}</font>",
                  style("Reps", fontName="Helvetica-Bold", fontSize=10,
                        textColor=MED_BLUE, alignment=TA_CENTER, leading=13)),
    ]]
    badge_table = Table(badge_data, colWidths=[1.2*cm, CONTENT_W - 4.5*cm, 3.3*cm])
    badge_table.setStyle(TableStyle([
        ("BACKGROUND",  (0,0),(0,0), MED_BLUE),
        ("BACKGROUND",  (1,0),(2,0), LIGHT_BLUE),
        ("VALIGN",      (0,0),(-1,-1), "MIDDLE"),
        ("TOPPADDING",  (0,0),(-1,-1), 6),
        ("BOTTOMPADDING",(0,0),(-1,-1), 6),
        ("LEFTPADDING", (0,0),(0,0), 4),
        ("RIGHTPADDING",(2,0),(2,0), 8),
        ("LEFTPADDING", (1,0),(1,0), 8),
    ]))
    items.append(badge_table)

    # Steps box
    steps_lines = [Paragraph(f"<bullet>&bull;</bullet> {step}", S_BULLET)
                   for step in how_to]
    inner = [Spacer(1,4)] + steps_lines + [Spacer(1,4)]

    if tip:
        inner.append(Paragraph(f"<b>Tip:</b> {tip}", S_TIP))
    if warning:
        inner.append(Paragraph(f"<b>Caution:</b> {warning}", S_WARNING))
    inner.append(Spacer(1,2))

    steps_data = [[inner_item] for inner_item in inner]
    steps_table = Table([[inner]], colWidths=[CONTENT_W])
    steps_table.setStyle(TableStyle([
        ("BACKGROUND",  (0,0),(-1,-1), LIGHT_GREY),
        ("BOX",         (0,0),(-1,-1), 0.5, MID_GREY),
        ("TOPPADDING",  (0,0),(-1,-1), 2),
        ("BOTTOMPADDING",(0,0),(-1,-1), 4),
        ("LEFTPADDING", (0,0),(-1,-1), 10),
        ("RIGHTPADDING",(0,0),(-1,-1), 10),
    ]))
    items.append(steps_table)
    items.append(Spacer(1, 8))

    return KeepTogether(items)


# ══════════════════════════════════════════════════════════════════════════
# SECTION 1 - WARM-UP
# ══════════════════════════════════════════════════════════════════════════
story.append(section_header("WARM-UP  (Do this before every session)"))
story.append(Spacer(1, 6))

story.append(exercise_card(
    "W", "Heat Application", "5-10 min", "Once before session",
    [
        "Apply a warm heat pack or hot water bottle to the shoulder.",
        "Alternatively, stand under a warm shower and let the water run over the shoulder.",
        "This loosens the joint and reduces pain before stretching.",
    ],
    tip="Never apply heat directly to bare skin - wrap in a thin towel."
))

story.append(exercise_card(
    "W2", "Neck & Upper Trap Release", "5 slow rolls each side", "60 seconds",
    [
        "Sit upright in a chair. Gently drop your ear toward your shoulder.",
        "Hold 10 seconds, then slowly roll your chin toward your chest.",
        "Roll to the other side and hold 10 seconds.",
        "This relaxes the muscles around the shoulder girdle.",
    ],
    tip="Keep the shoulders relaxed and low - do not shrug."
))

story.append(Spacer(1, 4))

# ══════════════════════════════════════════════════════════════════════════
# SECTION 2 - RANGE OF MOTION EXERCISES
# ══════════════════════════════════════════════════════════════════════════
story.append(section_header("RANGE OF MOTION EXERCISES"))
story.append(Spacer(1, 6))

story.append(exercise_card(
    "1", "Pendulum Swings", "10 circles each direction", "2 min",
    [
        "Stand beside a table or chair and lean forward, resting your good arm on the surface.",
        "Let the affected arm hang down loosely - completely relaxed.",
        "Gently swing the arm in small clockwise circles (10 times), then counter-clockwise (10 times).",
        "Let gravity do the work - do not actively move the shoulder muscles.",
        "You can also swing forward/backward and side-to-side (10 reps each).",
    ],
    tip="The smaller the circle, the better to start. Gradually increase size over weeks.",
    warning="Do not swing forcefully. This is a passive, gentle movement only."
))

story.append(exercise_card(
    "2", "Wall Finger Walk (Forward)", "10 steps up, 2-3 sets", "2 min",
    [
        "Stand facing a wall, about arm's length away.",
        "Place the fingertips of your affected hand on the wall at waist height.",
        "Walk your fingers slowly up the wall as high as comfortable, without raising your shoulder.",
        "Hold at the top for 5 seconds, then slowly walk fingers back down.",
        "Mark your highest point each day to track progress.",
    ],
    tip="Stand closer to the wall as flexibility improves to increase the stretch.",
))

story.append(exercise_card(
    "3", "Wall Finger Walk (Side)", "10 steps up, 2-3 sets", "2 min",
    [
        "Stand with your affected side facing the wall, about arm's length away.",
        "Place fingertips on the wall at hip level.",
        "Walk fingers sideways and upward as high as comfortable.",
        "Hold 5 seconds at the top, then walk slowly back down.",
    ],
    tip="This targets abduction (side lifting) which is usually the most restricted direction.",
))

story.append(exercise_card(
    "4", "Pendulum Horizontal Swing", "20 swings", "1-2 min",
    [
        "In the same leaning position as Exercise 1 (supported by good arm).",
        "Swing the affected arm gently forward and backward like a pendulum.",
        "Then swing side to side (across your body and outward).",
        "Keep the movement smooth and rhythmic.",
    ],
))

# ══════════════════════════════════════════════════════════════════════════
# SECTION 3 - STRETCHES
# ══════════════════════════════════════════════════════════════════════════
story.append(section_header("STRETCHING EXERCISES  (Hold each stretch gently)"))
story.append(Spacer(1, 6))

story.append(exercise_card(
    "5", "Cross-Body (Horizontal Adduction) Stretch", "3 x 30 sec holds", "2-3 min",
    [
        "Sit or stand upright.",
        "Use your good hand to gently grasp the elbow of the affected arm.",
        "Slowly pull the affected arm across your chest toward the opposite shoulder.",
        "Hold for 30 seconds. You should feel a gentle stretch in the back of the shoulder.",
        "Release slowly. Repeat 3 times.",
    ],
    tip="Only pull until you feel a mild stretch - never force it.",
    warning="Stop if you feel sharp pain radiating down the arm."
))

story.append(exercise_card(
    "6", "External Rotation Stretch (Doorway)", "3 x 20-30 sec holds", "2 min",
    [
        "Stand in a doorway with your elbow bent at 90 degrees.",
        "Place your forearm against the door frame vertically.",
        "Gently lean your body forward slightly until you feel a stretch at the front of the shoulder.",
        "Hold 20-30 seconds. Repeat 3 times.",
        "Alternatively: Lie on your back, elbow at 90 degrees - gently lower the back of your hand toward the floor.",
    ],
    tip="External rotation is the most important direction to regain - prioritise this stretch.",
))

story.append(exercise_card(
    "7", "Towel Internal Rotation Stretch", "3 x 20 sec holds", "2 min",
    [
        "Hold a bath towel with both hands behind your back - good arm on top, affected arm below.",
        "Use the good arm to gently pull the towel upward, lifting the affected arm slightly.",
        "Hold for 20 seconds. You will feel a stretch at the shoulder and upper arm.",
        "Slowly lower and repeat 3 times.",
    ],
    tip="Do not jerk or pull sharply - smooth, sustained stretch only.",
    warning="If you cannot reach behind your back, skip this exercise until mobility improves."
))

story.append(exercise_card(
    "8", "Overhead Reach (Supine)", "10 reps, 2 sets", "2 min",
    [
        "Lie on your back on a firm surface (bed or floor with a yoga mat).",
        "Clasp both hands together, interlinking fingers.",
        "Use the good arm to slowly assist the affected arm to raise both arms up overhead.",
        "Go as far as comfortable. Hold 5 seconds. Slowly lower back down.",
    ],
    tip="Gravity assists the stretch in this position - much easier than standing.",
))

# ══════════════════════════════════════════════════════════════════════════
# SECTION 4 - STRENGTHENING (Phase 2/3 only)
# ══════════════════════════════════════════════════════════════════════════
story.append(section_header("GENTLE STRENGTHENING  (Begin only when pain is manageable)", color=HexColor("#5C3A1A")))
story.append(Spacer(1, 6))

story.append(Paragraph(
    "Only start these when you can move the arm with mild discomfort only (not sharp pain). "
    "These help restore muscle strength and prevent weakness from prolonged reduced use.",
    S_BODY))
story.append(Spacer(1, 6))

story.append(exercise_card(
    "9", "Isometric External Rotation", "10 x 5 sec holds, 2 sets", "2 min",
    [
        "Stand sideways next to a wall, affected arm closest to the wall.",
        "Bend the elbow at 90 degrees, keep the elbow close to your side.",
        "Press the back of your hand gently into the wall (as if trying to rotate outward).",
        "Hold 5 seconds. Release. Repeat 10 times.",
        "No movement occurs - this is an isometric (static) exercise.",
    ],
    tip="Isometric exercises build strength without moving the joint - perfect for painful phases.",
))

story.append(exercise_card(
    "10", "Isometric Abduction", "10 x 5 sec holds, 2 sets", "2 min",
    [
        "Stand with your affected arm resting by your side.",
        "Press the outside of your arm gently against the wall or a door frame.",
        "Push outward (as if lifting the arm sideways) but keep the arm still.",
        "Hold 5 seconds. Release. Repeat 10 times.",
    ],
))

story.append(exercise_card(
    "11", "Scapular Retraction (Shoulder Blade Squeeze)", "15 reps, 3 sets", "2 min",
    [
        "Sit or stand upright with arms relaxed at sides.",
        "Gently squeeze your shoulder blades together as if trying to hold a pencil between them.",
        "Hold 5 seconds. Slowly release.",
        "This strengthens the postural muscles around the shoulder blade.",
    ],
    tip="Keep shoulders relaxed (not hunched up) and breathe normally throughout.",
))

# ══════════════════════════════════════════════════════════════════════════
# SECTION 5 - DAILY SCHEDULE
# ══════════════════════════════════════════════════════════════════════════
story.append(Spacer(1, 4))
story.append(section_header("RECOMMENDED DAILY SCHEDULE"))
story.append(Spacer(1, 8))

schedule_data = [
    [Paragraph("<b>Session</b>", S_TABLE_HDR),
     Paragraph("<b>Exercises</b>", S_TABLE_HDR),
     Paragraph("<b>Time</b>", S_TABLE_HDR)],
    [Paragraph("Morning (after warm shower)", S_TABLE_CELL),
     Paragraph("Warm-up + Exercises 1, 2, 5, 6", S_TABLE_CELL),
     Paragraph("~15 min", S_TABLE_CELL)],
    [Paragraph("Afternoon", S_TABLE_CELL),
     Paragraph("Exercises 3, 4, 7, 8", S_TABLE_CELL),
     Paragraph("~10 min", S_TABLE_CELL)],
    [Paragraph("Evening (before bed)", S_TABLE_CELL),
     Paragraph("Exercises 5, 6, 9, 10, 11 (if pain allows)", S_TABLE_CELL),
     Paragraph("~10 min", S_TABLE_CELL)],
]

sched_col_w = [CONTENT_W*0.38, CONTENT_W*0.42, CONTENT_W*0.20]
sched_table = Table(schedule_data, colWidths=sched_col_w)
sched_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0),  MED_BLUE),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, LIGHT_BLUE]),
    ("BOX",           (0,0), (-1,-1), 1, MED_BLUE),
    ("INNERGRID",     (0,0), (-1,-1), 0.5, MID_GREY),
    ("TOPPADDING",    (0,0), (-1,-1), 7),
    ("BOTTOMPADDING", (0,0), (-1,-1), 7),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
]))
story.append(sched_table)
story.append(Spacer(1, 10))

# ══════════════════════════════════════════════════════════════════════════
# SECTION 6 - DO's and DON'Ts
# ══════════════════════════════════════════════════════════════════════════
story.append(section_header("DO'S AND DON'TS"))
story.append(Spacer(1, 8))

dos_donts = [
    [Paragraph("<b>DO</b>", style("DH", fontName="Helvetica-Bold", fontSize=10,
                                   textColor=WHITE, alignment=TA_CENTER)),
     Paragraph("<b>DON'T</b>", style("DH2", fontName="Helvetica-Bold", fontSize=10,
                                      textColor=WHITE, alignment=TA_CENTER))],
    [Paragraph(
        "✔ Warm up before every session<br/>"
        "✔ Exercise 2-3 times daily consistently<br/>"
        "✔ Use the arm for light daily tasks<br/>"
        "✔ Sleep with a pillow supporting the arm<br/>"
        "✔ Take pain relief before exercise if needed<br/>"
        "✔ Keep track of your range each week<br/>"
        "✔ See your physiotherapist regularly",
        style("DoText", fontName="Helvetica", fontSize=9.5,
              textColor=HexColor("#1B5E20"), leading=16)),
     Paragraph(
        "✘ Do not immobilise or rest the shoulder completely<br/>"
        "✘ Do not push through sharp, severe pain<br/>"
        "✘ Do not sleep directly on the affected shoulder<br/>"
        "✘ Do not carry heavy bags on that side<br/>"
        "✘ Do not reach suddenly or jerk the arm<br/>"
        "✘ Do not skip sessions - consistency is key<br/>"
        "✘ Do not give up - recovery takes months",
        style("DontText", fontName="Helvetica", fontSize=9.5,
              textColor=HexColor("#B71C1C"), leading=16))],
]

dd_table = Table(dos_donts, colWidths=[CONTENT_W/2, CONTENT_W/2])
dd_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (0,0),  HexColor("#2E7D32")),
    ("BACKGROUND",    (1,0), (1,0),  HexColor("#C62828")),
    ("BACKGROUND",    (0,1), (0,1),  HexColor("#E8F5E9")),
    ("BACKGROUND",    (1,1), (1,1),  HexColor("#FFEBEE")),
    ("BOX",           (0,0), (-1,-1), 1, MID_GREY),
    ("INNERGRID",     (0,0), (-1,-1), 0.5, MID_GREY),
    ("TOPPADDING",    (0,0), (-1,-1), 8),
    ("BOTTOMPADDING", (0,0), (-1,-1), 8),
    ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ("RIGHTPADDING",  (0,0), (-1,-1), 10),
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
]))
story.append(dd_table)
story.append(Spacer(1, 10))

# ══════════════════════════════════════════════════════════════════════════
# SECTION 7 - PROGRESS TRACKER
# ══════════════════════════════════════════════════════════════════════════
story.append(section_header("WEEKLY PROGRESS TRACKER  (Print and fill in)", color=HexColor("#4A148C")))
story.append(Spacer(1, 8))

tracker_header = [
    Paragraph("<b>Week</b>", S_TABLE_HDR),
    Paragraph("<b>Date</b>", S_TABLE_HDR),
    Paragraph("<b>Pain (0-10)</b>", S_TABLE_HDR),
    Paragraph("<b>Arm raised to</b>", S_TABLE_HDR),
    Paragraph("<b>Exercises done</b>", S_TABLE_HDR),
    Paragraph("<b>Notes</b>", S_TABLE_HDR),
]

tracker_rows = [tracker_header]
for i in range(1, 9):
    tracker_rows.append([
        Paragraph(f"Week {i}", S_TABLE_CELL), "", "", "", "", ""
    ])

tracker_table = Table(tracker_rows,
    colWidths=[1.4*cm, 2.2*cm, 2.5*cm, 2.8*cm, 3.0*cm, CONTENT_W-11.9*cm])
tracker_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0),  HexColor("#4A148C")),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, HexColor("#F3E5F5")]),
    ("BOX",           (0,0), (-1,-1), 1, MID_GREY),
    ("INNERGRID",     (0,0), (-1,-1), 0.5, MID_GREY),
    ("TOPPADDING",    (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ("FONTSIZE",      (0,1), (-1,-1), 9),
]))
story.append(tracker_table)
story.append(Spacer(1, 10))

# ══════════════════════════════════════════════════════════════════════════
# SECTION 8 - WHEN TO SEEK HELP
# ══════════════════════════════════════════════════════════════════════════
story.append(section_header("WHEN TO SEEK MEDICAL ATTENTION", color=HexColor("#B71C1C")))
story.append(Spacer(1, 8))

warning_items = [
    "Sudden severe worsening of pain",
    "Redness, swelling, or warmth around the shoulder joint (may indicate infection)",
    "Fever with shoulder pain",
    "Pain radiating down the arm with tingling or numbness",
    "No improvement after 3-4 months of consistent exercises",
    "A fall or trauma causing sudden increased pain (rule out fracture)",
]
for item in warning_items:
    story.append(Paragraph(f"<font color='#C62828'><b>!</b></font>  {item}", S_BULLET))
    story.append(Spacer(1, 3))

story.append(Spacer(1, 8))

# ══════════════════════════════════════════════════════════════════════════
# FOOTER
# ══════════════════════════════════════════════════════════════════════════
story.append(HRFlowable(width=CONTENT_W, thickness=1, color=MED_BLUE))
story.append(Spacer(1, 6))
story.append(Paragraph(
    "This guide is for general information only and does not replace professional medical advice. "
    "Always consult your doctor or physiotherapist before starting or changing an exercise programme. "
    "Prepared by Orris Medical Assistant - July 2026.",
    S_NOTE
))

# ══════════════════════════════════════════════════════════════════════════
# BUILD
# ══════════════════════════════════════════════════════════════════════════
doc.build(story)
print(f"PDF created: {OUTPUT}")
Running Command

python3 /tmp/workspace/frozen-shoulder/generate_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/frozen-shoulder/Frozen_Shoulder_Exercise_Guide.pdf

The PDF is ready! Here is the download link:

Frozen Shoulder Exercise Guide

PDF Document · PDF


Here's what's included in the printable guide:
Warm-Up (2 exercises)
  • Heat application instructions
  • Neck and upper trap release
Range of Motion Exercises (4 exercises)
  • Pendulum swings
  • Wall finger walk (forward and sideways)
  • Pendulum horizontal swing
Stretching Exercises (4 stretches)
  • Cross-body stretch
  • External rotation doorway stretch
  • Towel internal rotation stretch
  • Overhead reach (lying down)
Gentle Strengthening (3 exercises)
  • Isometric external rotation
  • Isometric abduction
  • Scapular retraction (shoulder blade squeeze)
Plus:
  • Recommended daily 3-session schedule (~35 min total per day)
  • Colour-coded Do's & Don'ts table
  • 8-week progress tracker (fill in weekly pain score, range, notes)
  • When to seek medical attention
It's formatted for A4 printing with clear colour coding, step-by-step instructions, and tips/cautions for each exercise. Best to print in colour but it also reads clearly in black & white.
This is a shared conversation. Sign in to Orris to start your own chat.