Glucocorticoids dosing and tapering

Reading File
Finding Sources
Finding Sources
Searching PubMed

glucocorticoid tapering dosing

Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Finding Sources
I now have excellent, detailed textbook content on glucocorticoid dosing and tapering. Let me compile the comprehensive answer.

Glucocorticoids: Dosing and Tapering

1. Relative Potency and Equivalent Doses

Before dosing, understanding equivalencies is essential:
CorticosteroidRelative Anti-inflammatory PotencyEquivalent Dose
Cortisone0.825 mg
Hydrocortisone1.0 (reference)20 mg
Prednisone3.55 mg
Prednisolone4.05 mg
Triamcinolone5.04 mg
Methylprednisolone5.04 mg
Dexamethasone250.6 mg
Betamethasone250.6 mg
Source: Pfenninger and Fowler's Procedures for Primary Care
Key rule: greater water solubility = faster onset, shorter duration. Short-acting agents (hydrocortisone, cortisone) suit acute conditions; intermediate-acting agents (prednisone, triamcinolone) suit chronic conditions.

2. Dose Classification (Prednisone Equivalents)

CategoryDose
Low dose< 7.5 mg/day
Moderate dose7.5 - 30 mg/day
High dose30 - 100 mg/day
Very high / pulse> 100 mg/day (IV methylprednisolone 250-1000 mg/day for 1-3 days)
  • Low dose (e.g. 5-20 mg prednisone/day): connective tissue diseases, RA maintenance, PMR
  • Moderate-high dose (20-60 mg/day): autoimmune conditions (lupus, vasculitis, myositis, pemphigus), severe asthma
  • Pulse dose (IV methylprednisolone 500-1000 mg/day x 3 days): lupus nephritis, severe ANCA vasculitis, acute transplant rejection

3. Dosing Principles

  • Single morning dose is preferred for prolonged therapy - minimizes HPA axis suppression by aligning with the natural cortisol peak.
  • Alternate-day therapy reduces adrenal suppression further; appropriate for chronic low-to-moderate dose regimens using intermediate-acting agents (e.g. prednisone, NOT dexamethasone).
  • Evenings dosing increases the risk of HPA suppression and should be avoided when possible.
  • Adrenal suppression typically occurs after 4 weeks of therapy at doses just above physiologic levels (approx. >7.5 mg/day prednisone), or earlier with higher doses.

4. When to Taper

Tapering is advised after:
  1. 40 mg/day prednisone (or equivalent) for more than 1 week
  2. Any dose of glucocorticoid for more than 3 weeks
  3. Repeated doses given in the evening
  4. A glucocorticoid course within 1 year of stopping long-term therapy, or with other risk factors for adrenal insufficiency
Source: Dermatology 2-Volume Set 5e, Ch. 125

5. Tapering Regimen (General Schema)

For courses longer than 3-4 weeks, taper prednisone (or equivalent) as follows:
Current DoseReduction StepFrequency
> 40 mg/dayDecrease by 5-10 mgEvery 1 week
20-40 mg/dayDecrease by 5 mgEvery 1 week
10-20 mg/dayDecrease by 2.5 mgEvery 1 week
5-10 mg/dayDecrease by 1 mgEvery 2-3 weeks
Rule of thumb: As the dose decreases, the taper rate should slow. The lower the dose, the smaller the reduction intervals.
Source: Dermatology 2-Volume Set 5e, Ch. 125

6. Converting to Alternate-Day Therapy

Once prednisone is at ~20-30 mg/day, consider switching to alternate-day dosing:
  • Simple method: Multiply the previous daily dose by 2-2.5x for the on-day dose, then rapidly taper the off-day dose to zero.
  • Step-down method: Increase on-day dose by 5 mg and decrease off-day dose by 5 mg increments until the full dose is consolidated to every other day.

7. Disease Flares During Tapering

  • If the disease flares during the taper, return to the last dose at which the condition was controlled, then taper more slowly.
  • Factors influencing the regimen: severity and chronicity of the underlying condition, time for steroid-sparing agents to become effective, patient age, and comorbidities (diabetes, hypertension, osteoporosis, psychiatric history).
Duration by condition type:
  • Acute conditions (e.g. allergic contact dermatitis, moderate severity): 2-3 week course, no slow taper needed
  • Serious chronic conditions (SLE, dermatomyositis, pyoderma gangrenosum, vasculitis): longer courses with slow taper over 6-8+ weeks

8. HPA Axis Monitoring

  • Primary screening test: morning serum cortisol (6-8 AM)
    • Impaired basal HPA axis: cortisol < 10 mcg/dL
  • Confirmatory test: ACTH (cosyntropin) stimulation test - standard dose 250 mcg IV/IM; measure cortisol at baseline and 30/60 minutes
    • Low-dose test (1 mcg) may be more sensitive
  • If stress responsiveness in question, consider endocrinology referral for corticotropin-releasing factor test or insulin hypoglycemia test

9. Special Situations

  • Perioperative ("stress dosing"): For major surgical stress (e.g. liver resection), target 100-150 mg hydrocortisone equivalent on the day of surgery, then taper rapidly over the following days. Typically: preoperative dose + 50 mg hydrocortisone IV intraoperatively.
  • PMR: No standardized tapering regimen; symptoms often wax and wane over years. A meta-analysis suggests that when prednisone reaches 10 mg/day in PMR, the dose should be reduced very slowly (e.g. 1 mg/month). A 2026 systematic review (PMID: 41678240) confirms tapering strategies remain inconsistent and highlights the need for individualized approaches.
  • Lupus nephritis: Standardized tapering regimens now incorporate newer agents (e.g. voclosporin + mycophenolate) that allow more rapid glucocorticoid tapering.
  • ANCA vasculitis (PEXIVAS trial): Compared standard vs. reduced-dose tapering regimens - the reduced regimen was non-inferior for efficacy with fewer serious infections.

10. Key Monitoring During Therapy

SystemSide Effect to Monitor
MetabolicHyperglycemia, dyslipidemia, weight gain
BoneOsteoporosis (start bisphosphonate + calcium/vitamin D if > 3 months use)
HPA axisAdrenal insufficiency symptoms, morning cortisol
CardiovascularHypertension, fluid retention
GIPeptic ulceration (especially with concurrent NSAIDs)
PsychiatricMood changes, anxiety, insomnia, psychosis
OphthalmologicCataracts, glaucoma (long-term use)

Create a quick-reference tapering calculator PDF for common doses

Reading File
Running Command

mkdir -p /tmp/workspace/glucocorticoid-pdf && ls /tmp/workspace/glucocorticoid-pdf/

Writing File

~/glucocorticoid-pdf/make_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
    SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer,
    HRFlowable, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import PageBreak

# ── Colors ────────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#1A3A5C")
MED_BLUE    = colors.HexColor("#2E6DA4")
LIGHT_BLUE  = colors.HexColor("#D6E8F7")
TEAL        = colors.HexColor("#0E7B82")
LIGHT_TEAL  = colors.HexColor("#D0F0F2")
AMBER       = colors.HexColor("#E87722")
AMBER_LIGHT = colors.HexColor("#FDF0E0")
RED         = colors.HexColor("#C0392B")
RED_LIGHT   = colors.HexColor("#FADBD8")
GREEN       = colors.HexColor("#1E8449")
GREEN_LIGHT = colors.HexColor("#D5F5E3")
GRAY_DARK   = colors.HexColor("#333333")
GRAY_MID    = colors.HexColor("#666666")
GRAY_LIGHT  = colors.HexColor("#F2F4F6")
WHITE       = colors.white

OUTPUT = "/tmp/workspace/glucocorticoid-pdf/Glucocorticoid_Tapering_Reference.pdf"

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=14*mm,
    rightMargin=14*mm,
    topMargin=14*mm,
    bottomMargin=14*mm,
    title="Glucocorticoid Tapering Quick Reference",
    author="Orris Medical Reference",
)

W = A4[0] - 28*mm   # usable width

styles = getSampleStyleSheet()

def style(name, **kw):
    s = ParagraphStyle(name, parent=styles["Normal"], **kw)
    return s

H1 = style("H1", fontSize=18, textColor=WHITE, fontName="Helvetica-Bold",
           alignment=TA_CENTER, spaceAfter=2)
H2 = style("H2", fontSize=11, textColor=WHITE, fontName="Helvetica-Bold",
           alignment=TA_LEFT, spaceAfter=2, spaceBefore=2)
H3 = style("H3", fontSize=9.5, textColor=DARK_BLUE, fontName="Helvetica-Bold",
           alignment=TA_LEFT, spaceAfter=1, spaceBefore=4)
BODY = style("BODY", fontSize=8.5, textColor=GRAY_DARK, fontName="Helvetica",
             leading=12, spaceAfter=2)
SMALL = style("SMALL", fontSize=7.5, textColor=GRAY_MID, fontName="Helvetica",
              leading=10, spaceAfter=1)
FOOTER = style("FOOTER", fontSize=7, textColor=GRAY_MID, fontName="Helvetica-Oblique",
               alignment=TA_CENTER)
CELL = style("CELL", fontSize=8, textColor=GRAY_DARK, fontName="Helvetica", leading=11)
CELL_B = style("CELL_B", fontSize=8, textColor=GRAY_DARK, fontName="Helvetica-Bold", leading=11)
CELL_H = style("CELL_H", fontSize=8, textColor=WHITE, fontName="Helvetica-Bold",
               alignment=TA_CENTER, leading=11)
WARN = style("WARN", fontSize=8, textColor=RED, fontName="Helvetica-Bold", leading=11)
NOTE = style("NOTE", fontSize=7.5, textColor=GRAY_MID, fontName="Helvetica-Oblique", leading=10)

def section_header(text, color=MED_BLUE):
    t = Table([[Paragraph(text, H2)]], colWidths=[W])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), color),
        ("TOPPADDING",   (0,0), (-1,-1), 5),
        ("BOTTOMPADDING",(0,0), (-1,-1), 5),
        ("LEFTPADDING",  (0,0), (-1,-1), 8),
        ("RIGHTPADDING", (0,0), (-1,-1), 8),
        ("ROUNDEDCORNERS", [3]),
    ]))
    return t

def col_header_row(cells, bg=DARK_BLUE):
    return [Paragraph(c, CELL_H) for c in cells]

def body_cell(text, bold=False):
    return Paragraph(text, CELL_B if bold else CELL)

def tbl_style(row_data, col_widths, header_color=DARK_BLUE, alt_color=GRAY_LIGHT,
              alt_color2=WHITE, zebra=True, font_size=8):
    n = len(row_data)
    cmds = [
        ("BACKGROUND",   (0,0), (-1,0), header_color),
        ("TEXTCOLOR",    (0,0), (-1,0), WHITE),
        ("FONTNAME",     (0,0), (-1,0), "Helvetica-Bold"),
        ("FONTSIZE",     (0,0), (-1,-1), font_size),
        ("ALIGN",        (0,0), (-1,-1), "CENTER"),
        ("VALIGN",       (0,0), (-1,-1), "MIDDLE"),
        ("TOPPADDING",   (0,0), (-1,-1), 4),
        ("BOTTOMPADDING",(0,0), (-1,-1), 4),
        ("LEFTPADDING",  (0,0), (-1,-1), 5),
        ("RIGHTPADDING", (0,0), (-1,-1), 5),
        ("GRID",         (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
        ("LINEBELOW",    (0,0), (-1,0), 1.2, header_color),
    ]
    if zebra:
        for i in range(1, n):
            bg = alt_color if i % 2 == 1 else alt_color2
            cmds.append(("BACKGROUND", (0,i), (-1,i), bg))
    return cmds

# ═══════════════════════════════════════════════════════════════════════
# BUILD CONTENT
# ═══════════════════════════════════════════════════════════════════════
story = []

# ── TITLE BANNER ──────────────────────────────────────────────────────
title_data = [[
    Paragraph("GLUCOCORTICOID", H1),
    Paragraph("Dosing &amp; Tapering Quick Reference", H1),
]]
title_tbl = Table(title_data, colWidths=[W*0.38, W*0.62])
title_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0,0), (-1,-1), DARK_BLUE),
    ("TOPPADDING",    (0,0), (-1,-1), 10),
    ("BOTTOMPADDING", (0,0), (-1,-1), 10),
    ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ("RIGHTPADDING",  (0,0), (-1,-1), 10),
    ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
]))
story.append(title_tbl)
story.append(Spacer(1, 5*mm))

# ── ROW 1: two columns layout ─────────────────────────────────────────
# LEFT: Potency & Equivalence  |  RIGHT: Dose Classification

# --- POTENCY TABLE ---
pot_data = [
    [Paragraph("Agent", CELL_H), Paragraph("Relative\nPotency", CELL_H),
     Paragraph("Equiv.\nDose (mg)", CELL_H), Paragraph("Duration", CELL_H)],
    # Short-acting
    [body_cell("Cortisone", bold=True), body_cell("0.8"), body_cell("25"), body_cell("Short")],
    [body_cell("Hydrocortisone"), body_cell("1.0 ★"), body_cell("20"), body_cell("Short")],
    # Intermediate
    [body_cell("Prednisone", bold=True), body_cell("3.5"), body_cell("5"), body_cell("Interm.")],
    [body_cell("Prednisolone"), body_cell("4.0"), body_cell("5"), body_cell("Interm.")],
    [body_cell("Triamcinolone"), body_cell("5.0"), body_cell("4"), body_cell("Interm.")],
    [body_cell("Methylprednisolone"), body_cell("5.0"), body_cell("4"), body_cell("Interm.")],
    # Long-acting
    [body_cell("Dexamethasone", bold=True), body_cell("25"), body_cell("0.6"), body_cell("Long")],
    [body_cell("Betamethasone"), body_cell("25"), body_cell("0.6"), body_cell("Long")],
]

CW_pot = [W*0.21, W*0.11, W*0.12, W*0.11]  # total ~0.55*W

pot_cmds = tbl_style(pot_data, CW_pot, header_color=DARK_BLUE, alt_color=LIGHT_BLUE, alt_color2=WHITE)
# Shade short-acting rows
pot_cmds += [
    ("BACKGROUND", (0,1), (-1,2), colors.HexColor("#EAF4FB")),
    ("BACKGROUND", (0,3), (-1,6), LIGHT_BLUE),
    ("BACKGROUND", (0,7), (-1,8), colors.HexColor("#E8F4D0")),
    ("FONTNAME",   (0,1), (-1,2), "Helvetica"),
    ("TEXTCOLOR",  (1,2), (1,2), AMBER),
    ("FONTNAME",   (1,2), (1,2), "Helvetica-Bold"),
]

pot_tbl = Table(pot_data, colWidths=CW_pot)
pot_tbl.setStyle(TableStyle(pot_cmds))

# Separator label rows for short/intermediate/long
def section_row(label, ncols, bg_color):
    row = [[Paragraph(label, style("SL", fontSize=7, textColor=WHITE,
                                   fontName="Helvetica-BoldOblique",
                                   alignment=TA_CENTER))
            ] + [""] * (ncols - 1)]
    return row

# --- DOSE CLASSIFICATION TABLE ---
cls_data = [
    [Paragraph("Category", CELL_H), Paragraph("Prednisone\nEquivalent", CELL_H),
     Paragraph("Typical Use", CELL_H)],
    [body_cell("Low dose"),        body_cell("< 7.5 mg/day"),   body_cell("RA maintenance, PMR")],
    [body_cell("Moderate dose"),   body_cell("7.5–30 mg/day"),  body_cell("SLE, vasculitis")],
    [body_cell("High dose"),       body_cell("30–100 mg/day"),  body_cell("Severe autoimmune")],
    [body_cell("Very high / pulse"), body_cell("> 100 mg/day\n(or IV MP 500–1000 mg\n× 1–3 d)"),
     body_cell("Lupus nephritis,\nAAV, transplant\nrejection")],
]
CW_cls = [W*0.13, W*0.16, W*0.15]

cls_cmds = tbl_style(cls_data, CW_cls, header_color=TEAL, alt_color=LIGHT_TEAL, alt_color2=WHITE)
cls_cmds += [
    ("BACKGROUND", (0,4), (-1,4), RED_LIGHT),
    ("TEXTCOLOR",  (0,4), (0,4), RED),
    ("FONTNAME",   (0,4), (0,4), "Helvetica-Bold"),
]
cls_tbl = Table(cls_data, colWidths=CW_cls)
cls_tbl.setStyle(TableStyle(cls_cmds))

# Place side by side
left_col = [
    section_header("POTENCY & EQUIVALENCE", MED_BLUE),
    Spacer(1, 2*mm),
    pot_tbl,
    Spacer(1, 1*mm),
    Paragraph("★ Reference standard. MP = methylprednisolone. Short < 12 h, Interm. 12–36 h, Long > 48 h.", NOTE),
]
right_col = [
    section_header("DOSE CLASSIFICATION", TEAL),
    Spacer(1, 2*mm),
    cls_tbl,
    Spacer(1, 2*mm),
    section_header("ADMINISTRATION TIPS", TEAL),
    Spacer(1, 2*mm),
    Paragraph("• <b>Single morning dose</b> preferred — aligns with natural cortisol peak, reduces HPA suppression.", BODY),
    Paragraph("• <b>Alternate-day therapy:</b> use intermediate-acting agents (prednisone / prednisolone). NOT dexamethasone.", BODY),
    Paragraph("• Avoid <b>evening dosing</b> — significantly increases adrenal suppression risk.", BODY),
    Paragraph("• Adrenal suppression typically occurs after <b>4 weeks</b> at doses &gt; 7.5 mg/day prednisone equiv.", BODY),
]

CW_left  = W * 0.55 - 3*mm
CW_right = W * 0.45 - 3*mm

def mini_story_to_flowable(items, w):
    tbl = Table([[items]], colWidths=[w])
    tbl.setStyle(TableStyle([
        ("VALIGN", (0,0), (-1,-1), "TOP"),
        ("LEFTPADDING",  (0,0), (-1,-1), 0),
        ("RIGHTPADDING", (0,0), (-1,-1), 0),
        ("TOPPADDING",   (0,0), (-1,-1), 0),
        ("BOTTOMPADDING",(0,0), (-1,-1), 0),
    ]))
    return tbl

from reportlab.platypus import BalancedColumns

two_col = Table(
    [[left_col, right_col]],
    colWidths=[CW_left + 3*mm, CW_right + 3*mm]
)
two_col.setStyle(TableStyle([
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(two_col)
story.append(Spacer(1, 4*mm))

# ── TAPERING REGIMEN ──────────────────────────────────────────────────
story.append(section_header("TAPERING REGIMEN  (for courses > 3–4 weeks)", AMBER))
story.append(Spacer(1, 2*mm))

tap_data = [
    [Paragraph("Current Prednisone Dose", CELL_H),
     Paragraph("Reduction per Step", CELL_H),
     Paragraph("Frequency", CELL_H),
     Paragraph("Clinical Note", CELL_H)],
    [body_cell("> 40 mg/day", bold=True),
     body_cell("↓ 5–10 mg"),
     body_cell("Every 1 week"),
     body_cell("Disease usually controlled; rapid initial reduction acceptable")],
    [body_cell("20–40 mg/day", bold=True),
     body_cell("↓ 5 mg"),
     body_cell("Every 1 week"),
     body_cell("Monitor for flare; add steroid-sparing agent if not started")],
    [body_cell("10–20 mg/day", bold=True),
     body_cell("↓ 2.5 mg"),
     body_cell("Every 1 week"),
     body_cell("HPA axis begins to recover; slow taper critical here")],
    [body_cell("5–10 mg/day", bold=True),
     body_cell("↓ 1 mg"),
     body_cell("Every 2–3 weeks"),
     body_cell("Near-physiologic range; very slow reduction to prevent adrenal crisis")],
]

CW_tap = [W*0.22, W*0.14, W*0.14, W*0.50]
tap_cmds = tbl_style(tap_data, CW_tap, header_color=AMBER, alt_color=AMBER_LIGHT, alt_color2=WHITE)
tap_cmds += [
    ("TEXTCOLOR",  (0,4), (1,4), RED),
    ("FONTNAME",   (0,4), (0,4), "Helvetica-Bold"),
]
tap_tbl = Table(tap_data, colWidths=CW_tap)
tap_tbl.setStyle(TableStyle(tap_cmds))
story.append(tap_tbl)
story.append(Spacer(1, 1*mm))
story.append(Paragraph(
    "⚠ If disease <b>flares</b> during taper: resume the last dose that controlled disease, then taper MORE slowly. "
    "As dose decreases, always slow the rate of reduction.",
    style("FLARE", fontSize=8, textColor=RED, fontName="Helvetica-Bold",
          backColor=RED_LIGHT, borderPadding=(4,6,4,6), leading=11)
))
story.append(Spacer(1, 4*mm))

# ── ROW 3: Alternate-day + Taper schedule cards ───────────────────────
# Left: Alternate-day conversion | Right: Common starting doses by disease

altday_content = [
    section_header("ALTERNATE-DAY CONVERSION", MED_BLUE),
    Spacer(1, 2*mm),
    Paragraph("Switch when prednisone reaches <b>~20–30 mg/day</b>:", BODY),
    Spacer(1, 1*mm),
]

ad_data = [
    [Paragraph("Method", CELL_H), Paragraph("How to Do It", CELL_H)],
    [body_cell("Simple\n(Quick)"),
     body_cell("Multiply daily dose × 2–2.5 for the ON day. Taper OFF day rapidly to zero.")],
    [body_cell("Step-down\n(Gradual)"),
     body_cell("Increase ON day by +5 mg and decrease OFF day by –5 mg each week, until OFF day = 0.")],
]
CW_ad = [W*0.17, W*0.38]
ad_tbl = Table(ad_data, colWidths=CW_ad)
ad_tbl.setStyle(TableStyle(tbl_style(ad_data, CW_ad, header_color=MED_BLUE,
                                      alt_color=LIGHT_BLUE, alt_color2=WHITE)))
altday_content.append(ad_tbl)
altday_content += [
    Spacer(1, 2*mm),
    Paragraph("• Only intermediate-acting agents (prednisone, prednisolone) are suitable.", BODY),
    Paragraph("• NOT suitable for dexamethasone or betamethasone (too long-acting).", BODY),
]

# Disease-specific doses
dis_content = [
    section_header("COMMON STARTING DOSES BY CONDITION", TEAL),
    Spacer(1, 2*mm),
]

dis_data = [
    [Paragraph("Condition", CELL_H), Paragraph("Starting Dose\n(Prednisone equiv.)", CELL_H),
     Paragraph("Typical Duration", CELL_H)],
    [body_cell("Allergic contact derm."),   body_cell("40–60 mg/day"),      body_cell("2–3 weeks")],
    [body_cell("Asthma exacerbation"),      body_cell("40–60 mg/day"),      body_cell("5–10 days")],
    [body_cell("PMR"),                      body_cell("12.5–25 mg/day"),    body_cell("12–18+ months")],
    [body_cell("RA flare"),                 body_cell("5–20 mg/day"),       body_cell("Weeks–months")],
    [body_cell("SLE / vasculitis"),         body_cell("0.5–1 mg/kg/day"),   body_cell("Months; slow taper")],
    [body_cell("Dermatomyositis / PG"),     body_cell("1 mg/kg/day"),       body_cell("6–8+ weeks taper")],
    [body_cell("Lupus nephritis"),          body_cell("0.5–1 mg/kg/day"),   body_cell("+ steroid-sparing")],
    [body_cell("Pulse (severe disease)"),   body_cell("IV MP 500–1000 mg/day × 3"), body_cell("Then oral taper")],
    [body_cell("Perioperative (major Sx)"), body_cell("HC 100–150 mg equiv on day"), body_cell("Taper rapidly post-op")],
]

CW_dis = [W*0.27, W*0.22, W*0.17]
dis_tbl = Table(dis_data, colWidths=CW_dis)
dis_cmds = tbl_style(dis_data, CW_dis, header_color=TEAL, alt_color=LIGHT_TEAL, alt_color2=WHITE)
dis_cmds += [("BACKGROUND", (0,8), (-1,8), colors.HexColor("#F9E9D0")),
             ("BACKGROUND", (0,9), (-1,9), colors.HexColor("#EAF0E8"))]
dis_tbl.setStyle(TableStyle(dis_cmds))
dis_content.append(dis_tbl)
dis_content += [
    Spacer(1, 1*mm),
    Paragraph("PG = pyoderma gangrenosum. MP = methylprednisolone. HC = hydrocortisone.", NOTE),
]

three_col = Table(
    [[altday_content, dis_content]],
    colWidths=[W*0.57 + 3*mm, W*0.43 + 3*mm]
)
three_col.setStyle(TableStyle([
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(three_col)
story.append(Spacer(1, 4*mm))

# ── WHEN TO TAPER + HPA MONITORING ───────────────────────────────────
when_hpa_left = [
    section_header("WHEN TO TAPER (Endocrinology Guidance)", DARK_BLUE),
    Spacer(1, 2*mm),
    Paragraph("Tapering advised after ANY of the following:", BODY),
]

wt_data = [
    [Paragraph("#", CELL_H), Paragraph("Trigger", CELL_H)],
    [body_cell("1"), body_cell("≥ 40 mg/day prednisone (equiv.) for <b>more than 1 week</b>")],
    [body_cell("2"), body_cell("<b>Any dose</b> of glucocorticoid for <b>more than 3 weeks</b>")],
    [body_cell("3"), body_cell("Repeated glucocorticoid doses given in the <b>evening</b>")],
    [body_cell("4"), body_cell("Glucocorticoid course within <b>1 year</b> of stopping long-term therapy")],
    [body_cell("5"), body_cell("Other <b>risk factors</b> for adrenal insufficiency present")],
]
CW_wt = [W*0.05, W*0.40]
wt_tbl = Table(wt_data, colWidths=CW_wt)
wt_tbl.setStyle(TableStyle(tbl_style(wt_data, CW_wt, header_color=DARK_BLUE,
                                      alt_color=GRAY_LIGHT, alt_color2=WHITE)))
when_hpa_left += [wt_tbl]

hpa_right = [
    section_header("HPA AXIS MONITORING", DARK_BLUE),
    Spacer(1, 2*mm),
]

hpa_data = [
    [Paragraph("Test", CELL_H), Paragraph("Detail", CELL_H)],
    [body_cell("Morning cortisol\n(6–8 AM)", bold=True),
     body_cell("Impaired basal HPA: cortisol <b>&lt; 10 mcg/dL</b>. Omit morning GC dose on test day.")],
    [body_cell("Standard ACTH\nstimulation", bold=True),
     body_cell("Cosyntropin <b>250 mcg</b> IV/IM; cortisol at 0, 30, 60 min. Normal = peak > 18 mcg/dL.")],
    [body_cell("Low-dose ACTH\nstimulation", bold=True),
     body_cell("Cosyntropin <b>1 mcg</b> IV. More sensitive for partial adrenal insufficiency.")],
    [body_cell("Adrenal crisis\nrisk factors", bold=True),
     body_cell("Physiologic stress (infection, surgery, trauma). Give stress doses: HC 50–100 mg IV q8h.")],
]
CW_hpa = [W*0.13, W*0.35]
hpa_tbl = Table(hpa_data, colWidths=CW_hpa)
hpa_tbl.setStyle(TableStyle(tbl_style(hpa_data, CW_hpa, header_color=DARK_BLUE,
                                       alt_color=GRAY_LIGHT, alt_color2=WHITE)))
hpa_right += [hpa_tbl]

bot_row = Table(
    [[when_hpa_left, hpa_right]],
    colWidths=[W*0.47 + 3*mm, W*0.53 + 3*mm]
)
bot_row.setStyle(TableStyle([
    ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ("LEFTPADDING",   (0,0), (-1,-1), 0),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("TOPPADDING",    (0,0), (-1,-1), 0),
    ("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(bot_row)
story.append(Spacer(1, 3*mm))

# ── MONITORING TABLE ──────────────────────────────────────────────────
story.append(section_header("SIDE EFFECT MONITORING  (Long-term Use)", GRAY_MID))
story.append(Spacer(1, 2*mm))

mon_data = [
    [Paragraph("System", CELL_H), Paragraph("Adverse Effect", CELL_H),
     Paragraph("Action", CELL_H),
     Paragraph("System", CELL_H), Paragraph("Adverse Effect", CELL_H),
     Paragraph("Action", CELL_H)],
    [body_cell("Bone",    bold=True), body_cell("Osteoporosis"),
     body_cell("Bisphosphonate + Ca²⁺/vit D if > 3 months"),
     body_cell("Metabolic", bold=True), body_cell("Hyperglycemia"),
     body_cell("Monitor BG; adjust anti-diabetic therapy")],
    [body_cell("CV",      bold=True), body_cell("Hypertension, fluid retention"),
     body_cell("BP monitoring; sodium restriction"),
     body_cell("GI",        bold=True), body_cell("PUD / GI bleed"),
     body_cell("PPI if concurrent NSAID use")],
    [body_cell("Ophthalmic", bold=True), body_cell("Cataracts, glaucoma"),
     body_cell("Annual eye exam if > 1 year use"),
     body_cell("Infectious", bold=True), body_cell("Opportunistic infections"),
     body_cell("PJP prophylaxis if > 20 mg/day > 4 weeks")],
    [body_cell("Psych",   bold=True), body_cell("Mood, insomnia, psychosis"),
     body_cell("Counsel patient; lowest effective dose"),
     body_cell("Skin",      bold=True), body_cell("Atrophy, striae, purpura"),
     body_cell("Minimize dose; monitor skin integrity")],
]

CW_mon = [W*0.10, W*0.15, W*0.22, W*0.10, W*0.15, W*0.28]
mon_tbl = Table(mon_data, colWidths=CW_mon)
mon_cmds = tbl_style(mon_data, CW_mon, header_color=colors.HexColor("#555555"),
                     alt_color=GRAY_LIGHT, alt_color2=WHITE)
mon_cmds += [("ALIGN", (0,0), (-1,-1), "LEFT")]
mon_tbl.setStyle(TableStyle(mon_cmds))
story.append(mon_tbl)
story.append(Spacer(1, 3*mm))

# ── FOOTER ────────────────────────────────────────────────────────────
story.append(HRFlowable(width=W, color=GRAY_MID, thickness=0.5))
story.append(Spacer(1, 1*mm))
story.append(Paragraph(
    "Sources: Dermatology 2-Volume Set 5e (Ch. 125) | Firestein &amp; Kelley's Textbook of Rheumatology | "
    "Pfenninger &amp; Fowler's Procedures for Primary Care | Kooijman et al., Rheumatology (Oxford) 2026 (PMID: 41678240). "
    "For educational/clinical decision support only. Always individualise therapy.",
    FOOTER
))

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

cd /tmp/workspace/glucocorticoid-pdf && python make_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/glucocorticoid-pdf/Glucocorticoid_Tapering_Reference.pdf

Your PDF is ready. Here's what's packed onto the single A4 quick-reference page:

Glucocorticoid Tapering Reference

PDF Document · PDF


What's included:
SectionContent
Potency & EquivalenceAll 9 major agents with relative potency, equivalent dose, and duration class
Dose ClassificationLow / moderate / high / pulse with typical mg/day ranges and use cases
Administration TipsMorning dosing, alternate-day guidance, evening dosing warning
Tapering RegimenStep-down table: >40 / 20-40 / 10-20 / 5-10 mg/day with reduction steps and clinical notes
Flare WarningHighlighted box with action if disease flares during taper
Alternate-Day ConversionSimple and step-down methods, when to switch (~20-30 mg/day)
Common Starting Doses9 conditions (asthma, SLE, PMR, vasculitis, perioperative, pulse, etc.)
When to Taper5 endocrinology triggers
HPA Axis MonitoringMorning cortisol, standard & low-dose ACTH stimulation, adrenal crisis action
Side Effect Monitoring8 systems with specific actions (bisphosphonate, PPI, PJP prophylaxis, etc.)
Sources cited at the footer: Dermatology 5e, Firestein & Kelley's Rheumatology, Pfenninger & Fowler, and the 2026 PMR tapering systematic review (PMID: 41678240).
This is a shared conversation. Sign in to Orris to start your own chat.