make a case presentation on osteo arthritis and back pain

Your credits are exhausted. You can purchase a top-up or subscribe to a plan to continue using Orris. If you're already subscribed, your daily credits will reset tomorrow.

make a case presentation on osteo arthritis and back pain

Asking for Preferences
Reading File
Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Running Command

mkdir -p /tmp/workspace/oa-backpain-case && ls /tmp/workspace/oa-backpain-case/

Writing File

~/oa-backpain-case/build_pptx.py

from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.util import Inches, Pt
import copy

# ─── Colour palette ───────────────────────────────────────────────────────────
NAVY     = RGBColor(0x1A, 0x37, 0x6C)   # dark blue – header bars
TEAL     = RGBColor(0x00, 0x86, 0x9B)   # accent / sub-headers
ORANGE   = RGBColor(0xE8, 0x6B, 0x1E)   # highlights / badge
WHITE    = RGBColor(0xFF, 0xFF, 0xFF)
LIGHT_BG = RGBColor(0xF0, 0xF5, 0xFA)   # slide background
DARK_TXT = RGBColor(0x22, 0x22, 0x22)
MID_GRAY = RGBColor(0x88, 0x88, 0x88)

W = Inches(13.333)
H = Inches(7.5)

prs = Presentation()
prs.slide_width = W
prs.slide_height = H
blank = prs.slide_layouts[6]   # fully blank

# ─── Helper functions ─────────────────────────────────────────────────────────

def add_rect(slide, x, y, w, h, fill_rgb, alpha=None):
    shape = slide.shapes.add_shape(1, x, y, w, h)   # MSO_SHAPE_TYPE.RECTANGLE = 1
    shape.fill.solid()
    shape.fill.fore_color.rgb = fill_rgb
    shape.line.fill.background()
    return shape

def add_text(slide, text, x, y, w, h, size, bold=False, color=DARK_TXT,
             align=PP_ALIGN.LEFT, wrap=True, italic=False, anchor=MSO_ANCHOR.TOP):
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = wrap
    tf.auto_size = None
    tf.vertical_anchor = anchor
    tf.margin_left = 0; tf.margin_right = 0
    tf.margin_top = Pt(2); tf.margin_bottom = 0
    p = tf.paragraphs[0]
    p.alignment = align
    run = p.add_run()
    run.text = text
    run.font.size = Pt(size)
    run.font.bold = bold
    run.font.italic = italic
    run.font.color.rgb = color
    run.font.name = "Calibri"
    return tb

def add_multiline(slide, lines, x, y, w, h, size, color=DARK_TXT,
                  bold_first=False, bullet=False, line_spacing_pt=None):
    """Add a text box with multiple lines (list of strings)."""
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = True
    tf.margin_left = 0; tf.margin_right = 0
    tf.margin_top = Pt(2); tf.margin_bottom = 0
    for i, line in enumerate(lines):
        if i == 0:
            p = tf.paragraphs[0]
        else:
            p = tf.add_paragraph()
        p.alignment = PP_ALIGN.LEFT
        if line_spacing_pt:
            p.line_spacing = Pt(line_spacing_pt)
        run = p.add_run()
        prefix = "• " if bullet else ""
        run.text = prefix + line
        run.font.size = Pt(size)
        run.font.bold = (i == 0 and bold_first)
        run.font.color.rgb = color
        run.font.name = "Calibri"
    return tb

def header_bar(slide, title, subtitle=None):
    """Dark navy bar at top with white title."""
    add_rect(slide, 0, 0, W, Inches(1.15), NAVY)
    add_text(slide, title, Inches(0.4), Inches(0.08), Inches(12.5), Inches(0.65),
             size=30, bold=True, color=WHITE, align=PP_ALIGN.LEFT)
    if subtitle:
        add_text(slide, subtitle, Inches(0.4), Inches(0.72), Inches(12.5), Inches(0.38),
                 size=16, bold=False, color=RGBColor(0xAA, 0xCC, 0xEE), align=PP_ALIGN.LEFT)

def bg_fill(slide):
    add_rect(slide, 0, 0, W, H, LIGHT_BG)

def footer(slide, text="Case Presentation | Osteoarthritis & Back Pain"):
    add_rect(slide, 0, Inches(7.15), W, Inches(0.35), NAVY)
    add_text(slide, text, Inches(0.3), Inches(7.17), Inches(10), Inches(0.3),
             size=9, color=RGBColor(0xAA, 0xCC, 0xEE))

def section_badge(slide, label, x, y):
    add_rect(slide, x, y, Inches(2.4), Inches(0.38), TEAL)
    add_text(slide, label, x + Inches(0.12), y + Inches(0.04), Inches(2.2), Inches(0.32),
             size=13, bold=True, color=WHITE)

def divider(slide, y):
    add_rect(slide, Inches(0.4), y, Inches(12.5), Pt(2), TEAL)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 1 – TITLE SLIDE
# ══════════════════════════════════════════════════════════════════════════════
s1 = prs.slides.add_slide(blank)
add_rect(s1, 0, 0, W, H, NAVY)                         # full navy background
add_rect(s1, 0, Inches(2.8), W, Inches(2.1), TEAL)     # teal band
# Title
add_text(s1, "CASE PRESENTATION", Inches(1), Inches(1.0), Inches(11.3), Inches(0.7),
         size=22, bold=False, color=RGBColor(0xAA, 0xCC, 0xEE), align=PP_ALIGN.CENTER)
add_text(s1, "Osteoarthritis &\nLow Back Pain", Inches(0.5), Inches(1.7), Inches(12.3), Inches(1.2),
         size=46, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
# Teal band text
add_text(s1, "A Clinical Case for Medical Students", Inches(1), Inches(3.0), Inches(11.3), Inches(0.5),
         size=20, bold=False, color=WHITE, align=PP_ALIGN.CENTER)
add_text(s1, "Department of Internal Medicine / Orthopaedics", Inches(1), Inches(3.45), Inches(11.3), Inches(0.4),
         size=15, bold=False, color=RGBColor(0xDD, 0xEE, 0xFF), align=PP_ALIGN.CENTER)
# Bottom info
add_text(s1, "July 2026", Inches(1), Inches(5.7), Inches(11.3), Inches(0.4),
         size=14, bold=False, color=MID_GRAY, align=PP_ALIGN.CENTER)
add_text(s1, "References: Robbins & Kumar Basic Pathology | Goldman-Cecil Medicine | Bradley & Daroff's Neurology",
         Inches(1), Inches(6.2), Inches(11.3), Inches(0.4),
         size=11, bold=False, color=MID_GRAY, align=PP_ALIGN.CENTER)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 2 – PATIENT PRESENTATION
# ══════════════════════════════════════════════════════════════════════════════
s2 = prs.slides.add_slide(blank)
bg_fill(s2)
header_bar(s2, "Patient Presentation", "Chief Complaint & History of Present Illness")
footer(s2)

section_badge(s2, "PATIENT DEMOGRAPHICS", Inches(0.4), Inches(1.3))
demo_lines = [
    "Name: Mrs. E.A. (anonymized)",
    "Age: 65 years",
    "Sex: Female",
    "Occupation: Retired teacher",
    "BMI: 30.4 kg/m² (obese class I)",
]
add_multiline(s2, demo_lines, Inches(0.5), Inches(1.75), Inches(4.5), Inches(2.0),
              size=15, color=DARK_TXT, bullet=True)

section_badge(s2, "CHIEF COMPLAINT", Inches(5.2), Inches(1.3))
add_multiline(s2, [
    '"Persistent pain in both knees and lower back',
    ' for the past 3 years, worsening over 6 months."',
], Inches(5.3), Inches(1.75), Inches(7.5), Inches(0.9), size=15, color=DARK_TXT)

section_badge(s2, "HISTORY OF PRESENT ILLNESS", Inches(5.2), Inches(2.75))
hpi_lines = [
    "Bilateral knee pain – worse with walking & climbing stairs",
    "Morning stiffness lasting < 30 minutes",
    "Low back pain – dull, aching; radiates to left buttock",
    "No bowel or bladder dysfunction",
    "Occasional knee swelling after prolonged activity",
    "No fever, no significant trauma",
    "Pain scale: 6–7/10 at rest, 9/10 on exertion",
]
add_multiline(s2, hpi_lines, Inches(5.3), Inches(3.2), Inches(7.5), Inches(3.0),
              size=14, color=DARK_TXT, bullet=True)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 3 – PAST HISTORY & RISK FACTORS
# ══════════════════════════════════════════════════════════════════════════════
s3 = prs.slides.add_slide(blank)
bg_fill(s3)
header_bar(s3, "Medical History & Risk Factors", "Past Medical, Surgical & Social History")
footer(s3)

# Left column
section_badge(s3, "PAST MEDICAL HISTORY", Inches(0.4), Inches(1.3))
pmh = ["Type 2 Diabetes Mellitus (10 years)",
       "Hypertension",
       "Dyslipidaemia",
       "Menopause (age 52)"]
add_multiline(s3, pmh, Inches(0.5), Inches(1.75), Inches(5.5), Inches(1.8),
              size=15, bullet=True, color=DARK_TXT)

section_badge(s3, "MEDICATIONS", Inches(0.4), Inches(3.7))
meds = ["Metformin 1000 mg BD",
        "Amlodipine 5 mg OD",
        "Atorvastatin 20 mg ON",
        "PRN Ibuprofen (self-medicated)"]
add_multiline(s3, meds, Inches(0.5), Inches(4.15), Inches(5.5), Inches(1.8),
              size=15, bullet=True, color=DARK_TXT)

# Right column
section_badge(s3, "RISK FACTORS FOR OA", Inches(6.5), Inches(1.3))
rf_oa = ["Age > 50 (prevalence ~40% beyond age 70)",
         "Female sex – disproportionately affected",
         "Obesity (increased mechanical load)",
         "Diabetes mellitus (secondary OA trigger)",
         "No prior joint surgery or fracture"]
add_multiline(s3, rf_oa, Inches(6.6), Inches(1.75), Inches(6.3), Inches(2.0),
              size=14, bullet=True, color=DARK_TXT)

section_badge(s3, "RISK FACTORS FOR BACK PAIN", Inches(6.5), Inches(3.9))
rf_bp = ["Sedentary lifestyle post-retirement",
         "Obesity – increased lumbar axial load",
         "Facet joint arthropathy (age-related)",
         "Possible lumbar disc degeneration",
         "Prolonged standing history (teaching career)"]
add_multiline(s3, rf_bp, Inches(6.6), Inches(4.35), Inches(6.3), Inches(2.0),
              size=14, bullet=True, color=DARK_TXT)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 4 – PHYSICAL EXAMINATION
# ══════════════════════════════════════════════════════════════════════════════
s4 = prs.slides.add_slide(blank)
bg_fill(s4)
header_bar(s4, "Physical Examination", "Musculoskeletal & Neurological Findings")
footer(s4)

# Vitals strip
add_rect(s4, Inches(0.4), Inches(1.3), Inches(12.5), Inches(0.6), TEAL)
vitals = "BP: 148/90 mmHg   |   HR: 78 bpm   |   Temp: 36.8°C   |   SpO₂: 98%   |   BMI: 30.4 kg/m²"
add_text(s4, vitals, Inches(0.6), Inches(1.35), Inches(12.0), Inches(0.5),
         size=14, bold=True, color=WHITE, align=PP_ALIGN.CENTER)

# Left: Knee exam
section_badge(s4, "KNEE EXAMINATION", Inches(0.4), Inches(2.1))
knee_findings = [
    "Bilateral knee: bony enlargement (osteophytes)",
    "Crepitus on passive ROM – bilateral",
    "Mild effusion: left > right",
    "Decreased ROM: flexion 110° (normal 130–140°)",
    "Varus deformity: left knee",
    "McMurray test: negative (no meniscal tear)",
    "Lachman test: negative",
]
add_multiline(s4, knee_findings, Inches(0.5), Inches(2.55), Inches(5.8), Inches(3.5),
              size=13.5, bullet=True, color=DARK_TXT)

# Right: Back exam
section_badge(s4, "LUMBAR SPINE EXAMINATION", Inches(6.8), Inches(2.1))
back_findings = [
    "Paraspinal muscle tenderness: L3–L5 level",
    "Lumbar flexion: restricted (60°, normal 90°)",
    "Straight Leg Raise (SLR): negative bilaterally",
    "Patrick (FABER) test: positive left",
    "Facet loading test: positive – reproduces LBP",
    "Neurological: power 5/5, reflexes intact",
    "No saddle anaesthesia; sphincter tone normal",
]
add_multiline(s4, back_findings, Inches(6.9), Inches(2.55), Inches(6.0), Inches(3.5),
              size=13.5, bullet=True, color=DARK_TXT)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 5 – INVESTIGATIONS
# ══════════════════════════════════════════════════════════════════════════════
s5 = prs.slides.add_slide(blank)
bg_fill(s5)
header_bar(s5, "Investigations", "Laboratory & Imaging Studies")
footer(s5)

# Lab results box (left)
section_badge(s5, "LABORATORY TESTS", Inches(0.4), Inches(1.3))
labs = [
    ("FBC", "Hb 12.6 g/dL – mild anaemia of chronic disease"),
    ("ESR", "28 mm/hr (slightly elevated)"),
    ("CRP", "12 mg/L (mildly elevated)"),
    ("RF / Anti-CCP", "NEGATIVE – rules out RA"),
    ("Uric Acid", "4.8 mg/dL – normal"),
    ("HbA1c", "7.4%"),
    ("Urea / Creatinine", "Normal"),
    ("Synovial fluid", "Non-inflammatory: WBC < 2000/mm³"),
]
y = Inches(1.8)
for label, value in labs:
    add_rect(s5, Inches(0.5), y, Inches(1.6), Inches(0.35), NAVY)
    add_text(s5, label, Inches(0.55), y + Pt(4), Inches(1.5), Inches(0.32),
             size=12, bold=True, color=WHITE)
    add_text(s5, value, Inches(2.25), y + Pt(4), Inches(4.1), Inches(0.32),
             size=12.5, color=DARK_TXT)
    y += Inches(0.42)

# Imaging results box (right)
section_badge(s5, "IMAGING FINDINGS", Inches(7.0), Inches(1.3))
img_lines = [
    "X-ray Knee (Weight-Bearing AP & Lateral):",
    "  • Medial joint space narrowing bilaterally",
    "  • Marginal osteophytes – femoral condyles",
    "  • Subchondral sclerosis",
    "  • No acute fracture",
    "",
    "X-ray Lumbar Spine (AP & Lateral):",
    "  • Disc space narrowing L4–L5, L5–S1",
    "  • Osteophyte formation (anterior/posterior)",
    "  • Facet joint hypertrophy",
    "",
    "MRI Lumbar Spine (if available):",
    "  • Mild disc bulge L4–L5",
    "  • No nerve root compression seen",
    "  • Facet joint arthropathy confirmed",
]
add_multiline(s5, img_lines, Inches(7.1), Inches(1.78), Inches(5.8), Inches(5.0),
              size=13, color=DARK_TXT)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 6 – PATHOPHYSIOLOGY (OA)
# ══════════════════════════════════════════════════════════════════════════════
s6 = prs.slides.add_slide(blank)
bg_fill(s6)
header_bar(s6, "Pathophysiology of Osteoarthritis",
           "Degenerative Joint Disease – Mechanisms & Morphology")
footer(s6)

# Left: mechanism text
section_badge(s6, "DISEASE MECHANISM", Inches(0.4), Inches(1.3))
mech = [
    "OA = failed repair of synovial joint tissues after intra-articular stress",
    "Primary pathogenic mechanism: biomechanical stress on articular cartilage",
    "Chondrocytes release MMPs, TNF, IL-1 – degrade collagen & proteoglycan",
    "Attempted repair exceeds capacity → net cartilage loss",
    "Subchondral bone: sclerosis, cyst formation, osteophyte development",
    "Inflammation is SECONDARY – exacerbates but does not initiate OA",
    "(Unlike RA where autoimmunity drives pannus formation)",
]
add_multiline(s6, mech, Inches(0.5), Inches(1.8), Inches(6.5), Inches(3.5),
              size=13.5, bullet=True, color=DARK_TXT)

# OA stages box
section_badge(s6, "MORPHOLOGICAL STAGES", Inches(0.4), Inches(5.25))
stages = [
    "Early: chondrocyte injury, matrix changes, proteoglycan loss",
    "Established: cartilage fibrillation, clefts, loss of thickness",
    "Late: full-thickness cartilage loss, bone eburnation (ivory-like surface),",
    "       joint mice (loose bodies), subchondral cysts, osteophytes",
]
add_multiline(s6, stages, Inches(0.5), Inches(5.7), Inches(6.2), Inches(1.5),
              size=13, bullet=True, color=DARK_TXT)

# Right: OA vs RA comparison table
section_badge(s6, "OA vs RA – KEY DIFFERENCES", Inches(7.2), Inches(1.3))
headers = ["Feature", "OA", "RA"]
rows = [
    ["Pathology", "Mechanical / degenerative", "Autoimmune"],
    ["Inflammation", "Secondary", "Primary driver"],
    ["Joints", "Weight-bearing (knees, hips)", "Small joints (MCP, PIP)"],
    ["Morning stiffness", "< 30 minutes", "> 1 hour"],
    ["Serology", "RF / Anti-CCP: negative", "RF / Anti-CCP: positive"],
    ["Systemic features", "None", "Fever, nodules, systemic"],
    ["Treatment", "NSAIDs, PT, joint replacement", "DMARDs, biologics"],
]
col_w = [Inches(2.0), Inches(2.2), Inches(2.2)]
col_x = [Inches(7.3), Inches(9.35), Inches(11.6)]
row_h = Inches(0.42)
# header row
for ci, (txt, cw, cx) in enumerate(zip(headers, col_w, col_x)):
    add_rect(s6, cx, Inches(1.78), cw - Inches(0.05), row_h, NAVY)
    add_text(s6, txt, cx + Inches(0.05), Inches(1.82), cw - Inches(0.1), row_h - Pt(4),
             size=12, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
for ri, row in enumerate(rows):
    ry = Inches(1.78) + row_h * (ri + 1)
    bg = LIGHT_BG if ri % 2 == 0 else WHITE
    for ci, (txt, cw, cx) in enumerate(zip(row, col_w, col_x)):
        add_rect(s6, cx, ry, cw - Inches(0.05), row_h, bg)
        add_text(s6, txt, cx + Inches(0.07), ry + Pt(4), cw - Inches(0.12), row_h - Pt(4),
                 size=11.5, color=DARK_TXT)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 7 – PATHOPHYSIOLOGY (BACK PAIN)
# ══════════════════════════════════════════════════════════════════════════════
s7 = prs.slides.add_slide(blank)
bg_fill(s7)
header_bar(s7, "Pathophysiology of Low Back Pain",
           "Lumbar Facet Arthropathy & Disc Degeneration")
footer(s7)

add_text(s7, "Low back pain affects 60–80% of the US population at some point in life and is the most common condition seen in pain clinics.",
         Inches(0.4), Inches(1.22), Inches(12.5), Inches(0.45),
         size=14, italic=True, color=TEAL)

# 3-column boxes
boxes = [
    ("MUSCLE STRAIN / SPASM",
     ["Acute injury or chronic overuse", "Paraspinal tenderness & spasm",
      "No neurological deficit", "Responds to NSAIDs, muscle relaxants, PT"]),
    ("LUMBAR FACET SYNDROME (35%)",
     ["Arthritis or injury in facet joints", "Pain: low back ± referred to thigh (≤ knee)",
      "Back extension worsens pain", "SLR: NEGATIVE", "Tx: NSAIDs → medial branch blocks → RFA"]),
    ("DISC HERNIATION / RADICULOPATHY",
     ["L4–L5 / L5–S1 most common levels", "Shooting pain → foot (dorsomedial = L5; lateral = S1)",
      "SLR: POSITIVE", "MRI confirms; EMG/NCV may help",
      "Tx: NSAIDs → LESI → surgery if neurological deficit"]),
]
bx_starts = [Inches(0.3), Inches(4.55), Inches(8.8)]
bw = Inches(4.1)

for (title, bullets), bx in zip(boxes, bx_starts):
    add_rect(s7, bx, Inches(1.8), bw, Inches(0.45), NAVY)
    add_text(s7, title, bx + Inches(0.08), Inches(1.84), bw - Inches(0.1), Inches(0.38),
             size=12.5, bold=True, color=WHITE)
    add_multiline(s7, bullets, bx + Inches(0.1), Inches(2.32), bw - Inches(0.15), Inches(3.0),
                  size=13, bullet=True, color=DARK_TXT)

# Red flags box
add_rect(s7, Inches(0.3), Inches(5.55), Inches(12.6), Inches(1.35), RGBColor(0xFF, 0xEE, 0xEE))
add_rect(s7, Inches(0.3), Inches(5.55), Inches(2.0), Inches(1.35), RGBColor(0xCC, 0x00, 0x00))
add_text(s7, "⚠ RED\nFLAGS", Inches(0.35), Inches(5.62), Inches(1.9), Inches(1.2),
         size=16, bold=True, color=WHITE, align=PP_ALIGN.CENTER)
red_flags = ("Cauda equina syndrome (bowel/bladder dysfunction, saddle anaesthesia) – EMERGENCY   |   "
             "Progressive neurological deficit   |   Fever + back pain (infective)   |   "
             "Weight loss + night pain (malignancy)   |   Fracture risk (osteoporosis, trauma)")
add_text(s7, red_flags, Inches(2.45), Inches(5.65), Inches(10.3), Inches(1.2),
         size=13, color=RGBColor(0x88, 0x00, 0x00), wrap=True)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 8 – DIAGNOSIS
# ══════════════════════════════════════════════════════════════════════════════
s8 = prs.slides.add_slide(blank)
bg_fill(s8)
header_bar(s8, "Diagnosis", "Clinical & Radiological Criteria for OA")
footer(s8)

# Final diagnosis banner
add_rect(s8, Inches(0.4), Inches(1.25), Inches(12.5), Inches(0.7), ORANGE)
add_text(s8, "FINAL DIAGNOSIS:  Bilateral Knee Osteoarthritis  +  Lumbar Facet Arthropathy (Secondary LBP)",
         Inches(0.6), Inches(1.3), Inches(12.0), Inches(0.6),
         size=18, bold=True, color=WHITE, align=PP_ALIGN.CENTER)

# Left: ACR criteria
section_badge(s8, "ACR CRITERIA FOR KNEE OA", Inches(0.4), Inches(2.15))
acr = [
    "Knee pain + at least 3 of 6:",
    "  1. Age > 50 years  ✓",
    "  2. Morning stiffness < 30 min  ✓",
    "  3. Crepitus on motion  ✓",
    "  4. Bony tenderness  ✓",
    "  5. Bony enlargement  ✓",
    "  6. No palpable warmth  ✓",
    "",
    "This patient meets ALL 6 criteria",
    "Sensitivity: 95% | Specificity: 69%",
]
add_multiline(s8, acr, Inches(0.5), Inches(2.6), Inches(5.8), Inches(4.0),
              size=14, color=DARK_TXT)

# Right: differential diagnoses
section_badge(s8, "DIFFERENTIAL DIAGNOSES", Inches(7.0), Inches(2.15))
dd = [
    ("Rheumatoid Arthritis", "RF negative, no systemic features, no small joint involvement → EXCLUDED"),
    ("Gout / Pseudogout", "Uric acid normal, synovial fluid non-inflammatory → EXCLUDED"),
    ("Disc Herniation (LBP)", "SLR negative, no radiculopathy → EXCLUDED as primary cause"),
    ("Lumbar Facet Syndrome", "Patrick + ve, extension worsens pain, normal neurology → INCLUDED"),
    ("Malignancy / Infection", "No constitutional symptoms, fever, weight loss → EXCLUDED"),
]
y = Inches(2.6)
for dx, comment in dd:
    add_rect(s8, Inches(7.1), y, Inches(2.4), Inches(0.55), TEAL)
    add_text(s8, dx, Inches(7.15), y + Pt(4), Inches(2.3), Inches(0.48), size=12, bold=True, color=WHITE)
    add_text(s8, comment, Inches(9.58), y + Pt(4), Inches(3.8), Inches(0.48), size=12, color=DARK_TXT, wrap=True)
    y += Inches(0.65)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 9 – MANAGEMENT
# ══════════════════════════════════════════════════════════════════════════════
s9 = prs.slides.add_slide(blank)
bg_fill(s9)
header_bar(s9, "Management Plan", "Non-Pharmacological | Pharmacological | Interventional | Surgical")
footer(s9)

# 4-tier boxes
tiers = [
    ("NON-PHARMACOLOGICAL",
     TEAL,
     ["Weight reduction (BMI target < 25)",
      "Physiotherapy: quad strengthening, core exercises",
      "Walking aids (cane/walker if needed)",
      "Heat/cold therapy for pain relief",
      "Activity modification – avoid high-impact",
      "Patient education & self-management"]),
    ("PHARMACOLOGICAL",
     NAVY,
     ["Paracetamol: first-line analgesic",
      "NSAIDs (oral/topical): ibuprofen, naproxen",
      "Caution: renal, GI, cardiovascular risk",
      "Duloxetine: for chronic neuropathic component",
      "Muscle relaxants: cyclobenzaprine (back spasm)",
      "Topical diclofenac gel (knee)"]),
    ("INTERVENTIONAL",
     ORANGE,
     ["Intra-articular corticosteroid injection",
      "  (knee: short-term relief 4–8 wks)",
      "Hyaluronic acid injection (controversial)",
      "Medial branch block (facet LBP)",
      "Radiofrequency ablation (RFA) if MBB +ve",
      "Lumbar epidural steroid injection (if radiculopathy)"]),
    ("SURGICAL",
     RGBColor(0x55, 0x44, 0x88),
     ["Total Knee Replacement (TKR):",
      "  • Failed conservative Rx ≥ 3–6 months",
      "  • Functional limitation affecting ADLs",
      "  • Severe structural damage on X-ray",
      "Lumbar fusion / discectomy:",
      "  • Only for failed conservative Rx + imaging correlation"]),
]

bw2 = Inches(3.05)
starts2 = [Inches(0.2), Inches(3.38), Inches(6.55), Inches(9.72)]
for (title, col, bullets), bx in zip(tiers, starts2):
    add_rect(s9, bx, Inches(1.25), bw2, Inches(0.45), col)
    add_text(s9, title, bx + Inches(0.07), Inches(1.28), bw2 - Inches(0.1), Inches(0.4),
             size=11.5, bold=True, color=WHITE)
    add_multiline(s9, bullets, bx + Inches(0.1), Inches(1.76), bw2 - Inches(0.15), Inches(5.0),
                  size=12.5, bullet=True, color=DARK_TXT)

# ══════════════════════════════════════════════════════════════════════════════
# SLIDE 10 – LEARNING POINTS & SUMMARY
# ══════════════════════════════════════════════════════════════════════════════
s10 = prs.slides.add_slide(blank)
bg_fill(s10)
header_bar(s10, "Key Learning Points", "Summary for Medical Students")
footer(s10)

points = [
    ("OA Definition", "Degenerative disease of articular cartilage. Primary pathogenic mechanism is MECHANICAL STRESS. Inflammation is secondary."),
    ("Epidemiology", "Most common joint disease; prevalence ~40% in >70 yr. Female sex, obesity, DM, age are major risk factors."),
    ("Clinical Features", "Pain ↑ with use, morning stiffness <30 min, crepitus, osteophytes (Heberden nodes in DIP), decreased ROM."),
    ("OA vs RA", "OA: seronegative, weight-bearing joints, no systemic features. RA: autoimmune, small joints, RF +ve, systemic."),
    ("LBP Causes", "Muscle strain, lumbar facet syndrome (35%), disc herniation (radiculopathy), SI joint syndrome, spinal stenosis."),
    ("Red Flags", "Cauda equina = surgical EMERGENCY. Always screen: bowel/bladder, saddle anaesthesia, progressive weakness."),
    ("Management", "Step-up: weight loss + PT → NSAIDs/paracetamol → injections → surgery when ADLs affected and conservative Rx fails."),
    ("Joint Replacement", "TKR is indicated when functional status interferes with ADLs and supportive/pharmacological care is ineffective."),
]

y = Inches(1.28)
for i, (heading, body) in enumerate(points):
    col = NAVY if i % 2 == 0 else TEAL
    add_rect(s10, Inches(0.35), y, Inches(2.5), Inches(0.65), col)
    add_text(s10, heading, Inches(0.42), y + Pt(4), Inches(2.38), Inches(0.58),
             size=13, bold=True, color=WHITE, align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
    add_text(s10, body, Inches(2.95), y + Pt(4), Inches(10.0), Inches(0.58),
             size=13, color=DARK_TXT, wrap=True, anchor=MSO_ANCHOR.MIDDLE)
    y += Inches(0.68)

# Reference strip
add_rect(s10, 0, Inches(6.85), W, Inches(0.3), TEAL)
add_text(s10, "Sources: Robbins & Kumar Basic Pathology 10e  |  Goldman-Cecil Medicine 27e  |  Bradley & Daroff Neurology 8e  |  Textbook of Family Medicine 9e",
         Inches(0.3), Inches(6.87), Inches(12.6), Inches(0.28),
         size=9.5, color=WHITE, align=PP_ALIGN.CENTER)

# ─── Save ─────────────────────────────────────────────────────────────────────
out = "/tmp/workspace/oa-backpain-case/OA_BackPain_Case_Presentation.pptx"
prs.save(out)
print(f"Saved → {out}")
Running Command

cd /tmp/workspace/oa-backpain-case && python build_pptx.py 2>&1

Running Command

python -c " from pptx import Presentation prs = Presentation('/tmp/workspace/oa-backpain-case/OA_BackPain_Case_Presentation.pptx') print(f'Slides: {len(prs.slides)}') for i, slide in enumerate(prs.slides, 1): texts = [s.text_frame.text[:60].replace(chr(10),' ') for s in slide.shapes if s.has_text_frame and s.text_frame.text.strip()] print(f' Slide {i}: {texts[0] if texts else \"(empty)\"}') "

Your case presentation is ready:

OA BackPain Case Presentation

Presentation · PPTX


What's inside (10 slides, 16:9 widescreen, navy/teal/orange theme):
SlideContent
1Title slide
2Patient Presentation - Chief Complaint & HPI (65F, bilateral knee pain + LBP x 3 years)
3Medical History & Risk Factors (DM, HTN, obesity; risk factors for OA and LBP)
4Physical Examination - Knee & Lumbar findings with vitals strip
5Investigations - Lab results table + X-ray / MRI findings
6Pathophysiology of OA - Mechanisms, stages, OA vs RA comparison table
7Pathophysiology of LBP - 3 cause boxes (strain, facet syndrome, disc) + Red Flags alert
8Diagnosis - ACR Criteria (all 6 met) + Differential diagnoses with exclusion reasoning
9Management Plan - 4-tier layout: Non-pharmacological, Pharmacological, Interventional, Surgical
10Key Learning Points - 8 takeaways for medical students with textbook references
Content sourced from: Robbins & Kumar Basic Pathology 10e, Goldman-Cecil Medicine 27e, Bradley & Daroff's Neurology in Clinical Practice 8e, and Textbook of Family Medicine 9e.
This is a shared conversation. Sign in to Orris to start your own chat.