Glucocorticoids dosing and tapering
glucocorticoid tapering dosing
| Corticosteroid | Relative Anti-inflammatory Potency | Equivalent Dose |
|---|---|---|
| Cortisone | 0.8 | 25 mg |
| Hydrocortisone | 1.0 (reference) | 20 mg |
| Prednisone | 3.5 | 5 mg |
| Prednisolone | 4.0 | 5 mg |
| Triamcinolone | 5.0 | 4 mg |
| Methylprednisolone | 5.0 | 4 mg |
| Dexamethasone | 25 | 0.6 mg |
| Betamethasone | 25 | 0.6 mg |
| Category | Dose |
|---|---|
| Low dose | < 7.5 mg/day |
| Moderate dose | 7.5 - 30 mg/day |
| High dose | 30 - 100 mg/day |
| Very high / pulse | > 100 mg/day (IV methylprednisolone 250-1000 mg/day for 1-3 days) |
| Current Dose | Reduction Step | Frequency |
|---|---|---|
| > 40 mg/day | Decrease by 5-10 mg | Every 1 week |
| 20-40 mg/day | Decrease by 5 mg | Every 1 week |
| 10-20 mg/day | Decrease by 2.5 mg | Every 1 week |
| 5-10 mg/day | Decrease by 1 mg | Every 2-3 weeks |
| System | Side Effect to Monitor |
|---|---|
| Metabolic | Hyperglycemia, dyslipidemia, weight gain |
| Bone | Osteoporosis (start bisphosphonate + calcium/vitamin D if > 3 months use) |
| HPA axis | Adrenal insufficiency symptoms, morning cortisol |
| Cardiovascular | Hypertension, fluid retention |
| GI | Peptic ulceration (especially with concurrent NSAIDs) |
| Psychiatric | Mood changes, anxiety, insomnia, psychosis |
| Ophthalmologic | Cataracts, glaucoma (long-term use) |
Create a quick-reference tapering calculator PDF for common doses
mkdir -p /tmp/workspace/glucocorticoid-pdf && ls /tmp/workspace/glucocorticoid-pdf/
~/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 & 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 > 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>< 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 & Kelley's Textbook of Rheumatology | "
"Pfenninger & 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}")
cd /tmp/workspace/glucocorticoid-pdf && python make_pdf.py 2>&1
ls -lh /tmp/workspace/glucocorticoid-pdf/Glucocorticoid_Tapering_Reference.pdf
Glucocorticoid Tapering Reference
PDF Document · PDF
| Section | Content |
|---|---|
| Potency & Equivalence | All 9 major agents with relative potency, equivalent dose, and duration class |
| Dose Classification | Low / moderate / high / pulse with typical mg/day ranges and use cases |
| Administration Tips | Morning dosing, alternate-day guidance, evening dosing warning |
| Tapering Regimen | Step-down table: >40 / 20-40 / 10-20 / 5-10 mg/day with reduction steps and clinical notes |
| Flare Warning | Highlighted box with action if disease flares during taper |
| Alternate-Day Conversion | Simple and step-down methods, when to switch (~20-30 mg/day) |
| Common Starting Doses | 9 conditions (asthma, SLE, PMR, vasculitis, perioperative, pulse, etc.) |
| When to Taper | 5 endocrinology triggers |
| HPA Axis Monitoring | Morning cortisol, standard & low-dose ACTH stimulation, adrenal crisis action |
| Side Effect Monitoring | 8 systems with specific actions (bisphosphonate, PPI, PJP prophylaxis, etc.) |