Who pain ladder

Reading File
Searching the Web

WHO pain ladder three steps analgesic ladder 2024

Finding Sources
Reading File
Finding Sources
Reading File
Reading File
Loading Image
Here is a full breakdown of the WHO Pain (Analgesic) Ladder:

WHO Analgesic Ladder

Introduced by the World Health Organization in 1986, the pain ladder is a stepwise framework for managing cancer pain (and widely applied to other pain conditions). It is built on the principle of escalating analgesic potency based on pain intensity, rather than diagnosis.
WHO Analgesic Ladder

The 3 Steps

StepPain LevelDrugs Used
Step 1Mild painNon-opioids: Paracetamol (acetaminophen), NSAIDs (e.g. aspirin, ibuprofen, diclofenac) ± adjuvants
Step 2Mild-to-moderate pain (Step 1 fails)Weak opioids: Codeine, Tramadol + non-opioid ± adjuvants
Step 3Moderate-to-severe pain (Step 2 fails)Strong opioids: Morphine, Oxycodone, Hydromorphone, Fentanyl + non-opioid ± adjuvants
Adjuvants (used at any step as needed): Tricyclic antidepressants (e.g. amitriptyline), anticonvulsants (e.g. gabapentin, carbamazepine), corticosteroids, muscle relaxants - particularly useful for neuropathic pain.

The 5 WHO Principles of Analgesic Administration ("By the 5 A's")

The WHO paired the ladder with five principles for giving analgesics:
  1. By mouth - oral route preferred whenever feasible (simple, cheap, adjustable)
  2. By the clock - give on a regular schedule, not "as needed," to maintain continuous analgesia
  3. By the ladder - select the step based on pain intensity; move up if pain is not controlled
  4. For the individual - doses must be titrated to each patient's needs
  5. Attention to detail - vigilant reassessment of pain relief and side effects

Step 4 (Modified Ladder - widely used extension)

Many modern pain specialists add a 4th step:
  • Interventional procedures: spinal cord stimulation, nerve blocks, intrathecal drug delivery, neurolytic techniques - for refractory or intractable pain that does not respond to maximal pharmacotherapy.

Key Clinical Points

  • Move up, not sideways - if a drug at one step fails, escalate to the next step rather than switching to another drug at the same step.
  • Morphine is the opioid of choice for moderate-to-severe cancer pain (Step 3).
  • Opioid rotation may be considered if a patient has adequate pain relief from one opioid but unacceptable side effects.
  • Breakthrough pain - short-acting opioids (e.g. immediate-release morphine or fentanyl) cover acute flares on top of a stable background regimen.
  • Opioid-induced neurotoxicity (myoclonus, hallucinations, confusion) can occur from accumulation of opioid metabolites - consider dose reduction or opioid switching.
  • Oral morphine: typically started every 4 hours, then converted to slow-release formulation (e.g. MST) every 12 hours once dose is established.
  • Pethidine (meperidine) has been withdrawn from use in chronic cancer pain due to neurotoxic metabolite accumulation.

Sources:
  • Cummings Otolaryngology Head and Neck Surgery (Fig. 14.1; Table 14.2)
  • Bailey and Love's Short Practice of Surgery, 28th Ed.
  • Scott-Brown's Otorhinolaryngology Head & Neck Surgery

Give me in pdf

Reading File
Running Command

mkdir -p /home/daytona/workspace/who-pain-ladder && ls /home/daytona/workspace/who-pain-ladder/

Writing File

~/who-pain-ladder/generate_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import Image as RLImage
import urllib.request
import os

OUTPUT = "/home/daytona/workspace/who-pain-ladder/WHO_Pain_Ladder.pdf"

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=2*cm, leftMargin=2*cm,
    topMargin=2.5*cm, bottomMargin=2.5*cm,
    title="WHO Analgesic (Pain) Ladder",
    author="Orris Medical Reference"
)

W, H = A4
styles = getSampleStyleSheet()

# ── Custom styles ────────────────────────────────────────────────────────────
BLUE   = colors.HexColor("#1a3a5c")
ORANGE = colors.HexColor("#e07b2a")
LIGHT  = colors.HexColor("#fdf3e7")
STEP1C = colors.HexColor("#fff3e0")
STEP2C = colors.HexColor("#ffe0b2")
STEP3C = colors.HexColor("#e07b2a")
HEADBG = colors.HexColor("#1a3a5c")

title_style = ParagraphStyle(
    "Title", parent=styles["Title"],
    textColor=colors.white, fontSize=22, leading=28,
    alignment=TA_CENTER, spaceAfter=4
)
subtitle_style = ParagraphStyle(
    "Sub", parent=styles["Normal"],
    textColor=colors.HexColor("#bbcfe0"), fontSize=10,
    alignment=TA_CENTER, spaceAfter=2
)
section_style = ParagraphStyle(
    "Section", parent=styles["Heading2"],
    textColor=BLUE, fontSize=13, leading=16,
    spaceBefore=14, spaceAfter=4,
    borderPad=2
)
body_style = ParagraphStyle(
    "Body", parent=styles["Normal"],
    fontSize=10, leading=14, alignment=TA_JUSTIFY,
    textColor=colors.HexColor("#2c2c2c"), spaceAfter=4
)
bullet_style = ParagraphStyle(
    "Bullet", parent=styles["Normal"],
    fontSize=10, leading=13,
    leftIndent=16, bulletIndent=4,
    textColor=colors.HexColor("#2c2c2c"), spaceAfter=3
)
table_header_style = ParagraphStyle(
    "TH", parent=styles["Normal"],
    fontSize=10, leading=13, textColor=colors.white,
    alignment=TA_CENTER, fontName="Helvetica-Bold"
)
table_cell_style = ParagraphStyle(
    "TC", parent=styles["Normal"],
    fontSize=9, leading=12, textColor=colors.HexColor("#2c2c2c"),
    alignment=TA_LEFT
)
footer_style = ParagraphStyle(
    "Footer", parent=styles["Normal"],
    fontSize=7.5, textColor=colors.grey,
    alignment=TA_CENTER
)
principle_label = ParagraphStyle(
    "PL", parent=styles["Normal"],
    fontSize=10, fontName="Helvetica-Bold",
    textColor=BLUE, spaceAfter=1
)

story = []

# ── HEADER BANNER ────────────────────────────────────────────────────────────
header_data = [[
    Paragraph("WHO Analgesic (Pain) Ladder", title_style),
]]
header_sub = [[
    Paragraph("World Health Organization | Introduced 1986 | Cancer & Chronic Pain Management", subtitle_style),
]]

header_table = Table([[
    Paragraph("WHO Analgesic (Pain) Ladder", title_style),
]], colWidths=[W - 4*cm])
header_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), HEADBG),
    ("ROUNDEDCORNERS", [8]),
    ("TOPPADDING",    (0,0), (-1,-1), 16),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ("RIGHTPADDING",  (0,0), (-1,-1), 10),
]))

sub_table = Table([[
    Paragraph("World Health Organization  |  Introduced 1986  |  Cancer & Chronic Pain Management", subtitle_style),
]], colWidths=[W - 4*cm])
sub_table.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), HEADBG),
    ("ROUNDEDCORNERS", [8]),
    ("TOPPADDING",    (0,0), (-1,-1), 2),
    ("BOTTOMPADDING", (0,0), (-1,-1), 16),
    ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ("RIGHTPADDING",  (0,0), (-1,-1), 10),
]))

story.append(header_table)
story.append(sub_table)
story.append(Spacer(1, 0.4*cm))

# ── OVERVIEW ─────────────────────────────────────────────────────────────────
story.append(Paragraph("Overview", section_style))
story.append(HRFlowable(width="100%", thickness=1.5, color=ORANGE, spaceAfter=6))
story.append(Paragraph(
    "The WHO Pain Ladder is a stepwise framework for managing pain — originally developed for cancer pain "
    "and now widely applied across chronic pain conditions. It advocates selecting analgesics based on "
    "<b>pain intensity</b>, not diagnosis, escalating through three steps until pain is controlled. "
    "Adjuvant medications may be added at any step.",
    body_style
))
story.append(Spacer(1, 0.3*cm))

# ── LADDER VISUAL (table) ─────────────────────────────────────────────────────
story.append(Paragraph("The Three Steps", section_style))
story.append(HRFlowable(width="100%", thickness=1.5, color=ORANGE, spaceAfter=8))

step_header = [
    Paragraph("Step", table_header_style),
    Paragraph("Pain Level", table_header_style),
    Paragraph("Drugs", table_header_style),
    Paragraph("Examples", table_header_style),
]

step1 = [
    Paragraph("<b>Step 1</b>", ParagraphStyle("s1", parent=styles["Normal"], fontSize=11,
              fontName="Helvetica-Bold", textColor=colors.HexColor("#6d3a00"), alignment=TA_CENTER)),
    Paragraph("Mild pain\n(1–3 / 10)", table_cell_style),
    Paragraph("<b>Non-opioids</b>\n± Adjuvants", table_cell_style),
    Paragraph("Paracetamol, Aspirin, NSAIDs\n(ibuprofen, diclofenac, naproxen)", table_cell_style),
]
step2 = [
    Paragraph("<b>Step 2</b>", ParagraphStyle("s2", parent=styles["Normal"], fontSize=11,
              fontName="Helvetica-Bold", textColor=colors.HexColor("#7d3b00"), alignment=TA_CENTER)),
    Paragraph("Mild-to-moderate\npain (4–6 / 10)\nStep 1 fails", table_cell_style),
    Paragraph("<b>Weak opioid</b>\n+ Non-opioid\n± Adjuvants", table_cell_style),
    Paragraph("Codeine, Tramadol\n+ Paracetamol / NSAID", table_cell_style),
]
step3 = [
    Paragraph("<b>Step 3</b>", ParagraphStyle("s3", parent=styles["Normal"], fontSize=11,
              fontName="Helvetica-Bold", textColor=colors.white, alignment=TA_CENTER)),
    Paragraph("<font color='white'>Moderate-to-severe\npain (7–10 / 10)\nStep 2 fails</font>", table_cell_style),
    Paragraph("<font color='white'><b>Strong opioid</b>\n+ Non-opioid\n± Adjuvants</font>", table_cell_style),
    Paragraph("<font color='white'>Morphine*, Oxycodone,\nHydromorphone, Fentanyl\n+ Paracetamol / NSAID\n(*drug of choice)</font>", table_cell_style),
]

ladder_table = Table(
    [step_header, step1, step2, step3],
    colWidths=[2.2*cm, 3.8*cm, 4.5*cm, 6.3*cm]
)
ladder_table.setStyle(TableStyle([
    # Header
    ("BACKGROUND",    (0,0), (-1,0), HEADBG),
    ("TEXTCOLOR",     (0,0), (-1,0), colors.white),
    ("ALIGN",         (0,0), (-1,0), "CENTER"),
    ("FONTNAME",      (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE",      (0,0), (-1,0), 10),
    # Step rows background
    ("BACKGROUND",    (0,1), (-1,1), STEP1C),
    ("BACKGROUND",    (0,2), (-1,2), STEP2C),
    ("BACKGROUND",    (0,3), (-1,3), STEP3C),
    # Grid
    ("GRID",          (0,0), (-1,-1), 0.5, colors.white),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [STEP1C, STEP2C, STEP3C]),
    # Padding
    ("TOPPADDING",    (0,0), (-1,-1), 8),
    ("BOTTOMPADDING", (0,0), (-1,-1), 8),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("RIGHTPADDING",  (0,0), (-1,-1), 8),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
]))

story.append(ladder_table)
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph(
    "<i>Note: Move <b>up</b> the ladder if pain is uncontrolled — do not switch sideways to another drug at the same step.</i>",
    ParagraphStyle("note", parent=styles["Normal"], fontSize=8.5, textColor=colors.grey, spaceAfter=4)
))
story.append(Spacer(1, 0.3*cm))

# ── ADJUVANTS ─────────────────────────────────────────────────────────────────
story.append(Paragraph("Adjuvant Medications (any step)", section_style))
story.append(HRFlowable(width="100%", thickness=1.5, color=ORANGE, spaceAfter=6))

adj_data = [
    [Paragraph("<b>Class</b>", table_header_style), Paragraph("<b>Examples</b>", table_header_style), Paragraph("<b>Use</b>", table_header_style)],
    ["Tricyclic antidepressants", "Amitriptyline, Nortriptyline", "Neuropathic pain"],
    ["Anticonvulsants", "Gabapentin, Pregabalin, Carbamazepine", "Neuropathic pain"],
    ["Corticosteroids", "Dexamethasone, Prednisolone", "Bone pain, raised ICP, inflammation"],
    ["Muscle relaxants", "Baclofen, Diazepam", "Muscle spasm pain"],
    ["Bisphosphonates", "Zoledronic acid, Pamidronate", "Bone metastasis pain"],
]
adj_table = Table(adj_data, colWidths=[4.5*cm, 6.0*cm, 6.3*cm])
adj_table.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,0), HEADBG),
    ("TEXTCOLOR",     (0,0), (-1,0), colors.white),
    ("FONTNAME",      (0,0), (-1,0), "Helvetica-Bold"),
    ("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.HexColor("#f5f9fd"), colors.white]),
    ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#c0d0e0")),
    ("FONTSIZE",      (0,1), (-1,-1), 9),
    ("TOPPADDING",    (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING",   (0,0), (-1,-1), 7),
    ("RIGHTPADDING",  (0,0), (-1,-1), 7),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
]))
story.append(adj_table)
story.append(Spacer(1, 0.35*cm))

# ── 5 PRINCIPLES ──────────────────────────────────────────────────────────────
story.append(Paragraph("WHO's 5 Principles of Analgesic Administration", section_style))
story.append(HRFlowable(width="100%", thickness=1.5, color=ORANGE, spaceAfter=6))

principles = [
    ("1. By Mouth",      "Oral route preferred whenever feasible — simple, cheap, and easily adjusted."),
    ("2. By the Clock",  "Give on a regular schedule (not PRN) to maintain continuous analgesia and prevent pain breakthrough."),
    ("3. By the Ladder", "Select the analgesic step based on pain intensity; escalate if uncontrolled."),
    ("4. For the Individual", "Titrate doses to each patient — there is no standard dose for opioids."),
    ("5. Attention to Detail", "Reassess pain relief and monitor for adverse effects vigilantly after every change."),
]

pr_data = [[
    Paragraph(f"<b>{p[0]}</b>", ParagraphStyle("pl", parent=styles["Normal"], fontSize=10,
              fontName="Helvetica-Bold", textColor=BLUE, alignment=TA_CENTER)),
    Paragraph(p[1], table_cell_style)
] for p in principles]

pr_table = Table(pr_data, colWidths=[4.5*cm, 12.3*cm])
pr_table.setStyle(TableStyle([
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [colors.HexColor("#eaf2fb"), colors.white]),
    ("GRID",           (0,0), (-1,-1), 0.4, colors.HexColor("#c0d0e0")),
    ("TOPPADDING",     (0,0), (-1,-1), 7),
    ("BOTTOMPADDING",  (0,0), (-1,-1), 7),
    ("LEFTPADDING",    (0,0), (-1,-1), 8),
    ("RIGHTPADDING",   (0,0), (-1,-1), 8),
    ("VALIGN",         (0,0), (-1,-1), "MIDDLE"),
]))
story.append(pr_table)
story.append(Spacer(1, 0.35*cm))

# ── STEP 4 (extended) ─────────────────────────────────────────────────────────
story.append(Paragraph("Step 4 — Interventional Pain Management (Modified Ladder)", section_style))
story.append(HRFlowable(width="100%", thickness=1.5, color=ORANGE, spaceAfter=6))
story.append(Paragraph(
    "A fourth step is widely recognised for <b>refractory or intractable pain</b> not controlled by maximal "
    "pharmacotherapy. Options include:",
    body_style
))
step4_items = [
    "Spinal cord stimulation (SCS)",
    "Nerve blocks (regional anaesthesia)",
    "Intrathecal / epidural drug delivery systems",
    "Neurolytic procedures (chemical or surgical nerve ablation)",
    "Transcutaneous electrical nerve stimulation (TENS)",
]
for item in step4_items:
    story.append(Paragraph(f"\u2022  {item}", bullet_style))
story.append(Spacer(1, 0.3*cm))

# ── CLINICAL PEARLS ───────────────────────────────────────────────────────────
story.append(Paragraph("Clinical Pearls", section_style))
story.append(HRFlowable(width="100%", thickness=1.5, color=ORANGE, spaceAfter=6))

pearls = [
    ("<b>Morphine</b> is the opioid of choice for moderate-to-severe cancer pain (Step 3)."),
    ("<b>Breakthrough pain</b>: add short-acting opioid (immediate-release morphine / fentanyl) on top of regular background dose."),
    ("<b>Oral morphine dosing</b>: start every 4 hours, then convert to slow-release (MST) every 12 hours once stable dose established."),
    ("<b>Opioid-induced neurotoxicity</b>: myoclonus, hallucinations, confusion from metabolite accumulation — consider dose reduction or opioid rotation."),
    ("<b>Opioid rotation</b>: switch opioids if adequate analgesia with unacceptable side effects. Use equianalgesic dose tables."),
    ("<b>Pethidine (meperidine)</b>: no longer recommended for chronic cancer pain — neurotoxic metabolite (norpethidine) accumulates."),
    ("<b>Constipation</b>: near-universal with opioids — always prescribe a laxative prophylactically."),
    ("<b>Nausea</b> is common initially but usually resolves; treat with antiemetics."),
    ("Addiction vs dependence: <b>dependence</b> is a physiological opioid response; <b>addiction</b> is a psychosocial phenomenon — distinguish carefully."),
]
for pearl in pearls:
    story.append(Paragraph(f"\u2022  {pearl}", bullet_style))

story.append(Spacer(1, 0.5*cm))

# ── FOOTER ────────────────────────────────────────────────────────────────────
story.append(HRFlowable(width="100%", thickness=0.5, color=colors.grey, spaceAfter=4))
story.append(Paragraph(
    "Sources: Cummings Otolaryngology Head &amp; Neck Surgery | Bailey &amp; Love's Short Practice of Surgery, 28th Ed. | "
    "Scott-Brown's Otorhinolaryngology | WHO Cancer Pain Relief and Palliative Care, 1996",
    footer_style
))
story.append(Paragraph(
    "Generated by Orris Medical Reference  |  June 2026",
    footer_style
))

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

python /home/daytona/workspace/who-pain-ladder/generate_pdf.py

Your PDF is ready! Download it here:

WHO Pain Ladder

PDF Document · PDF

The document includes:
  • Header banner with title and source info
  • 3-Step ladder table with pain levels, drug classes, and examples (color-coded by step)
  • Adjuvant medications table by drug class
  • WHO's 5 Principles of analgesic administration
  • Step 4 interventional options
  • Clinical pearls (morphine dosing, breakthrough pain, opioid rotation, side effects)
  • Source citations at the footer
This is a shared conversation. Sign in to Orris to start your own chat.