Methotrexate toxicity
"methotrexate" AND "toxicity"
| Major Criteria |
|---|
| Hypersensitivity pneumonitis on histopathology |
| Radiologic evidence of pulmonary interstitial/alveolar infiltrates |
| Negative blood and sputum cultures |
| Parameter | Frequency |
|---|---|
| CBC + platelet count | Monthly for 3 months at initiation, then periodically |
| LFTs (AST, ALT, albumin) | Monthly for 3 months, then periodically |
| Serum creatinine / eGFR | Before each dose in high-risk |
| Hepatic fibrosis assessment | Serum biomarkers ± FibroScan; biopsy if indicated |
| CXR + baseline PFTs | Before starting (especially if lung disease present) |
| Intervention | Indication / Mechanism |
|---|---|
| Activated charcoal | Early after acute oral overdose (limited benefit) |
| Aggressive IV hydration | All MTX toxicity; promotes renal excretion |
| Urine alkalinization (IV NaHCO₃ to target urine pH 8) | Enhances renal excretion of this weak acid; prevents crystal nephropathy |
| Leucovorin (folinic acid) rescue | Most important antidote; bypasses DHFR block; give promptly after supratherapeutic exposure; most effective when given early |
| Glucarpidase (carboxypeptidase G2) | Recombinant enzyme that catabolizes MTX; used when leucovorin alone is insufficient or patient has AKI |
| Blood product transfusion | For established cytopenias |
| Extracorporeal removal (high-flux IHD, charcoal HP) | For very high serum levels (especially with AKI); charcoal HP and high-flux IHD most effective; indicated when MTX levels >30-300 µmol/L at 24h |
| IT MTX overdose | CSF drainage + exchange ± corticosteroids + leucovorin-glucarpidase |
| Setting | Typical Toxicities |
|---|---|
| Low-dose weekly (RA, psoriasis: 7.5-25 mg/week) | Hepatotoxicity, mucositis, GI upset, pneumonitis, myelosuppression |
| Intermediate dose (20-100 mg/m²) | Myelosuppression, mucositis, hepatotoxicity |
| High dose (>500-1000 mg/m²) with leucovorin rescue | Renal crystal nephropathy, severe mucositis, CNS toxicity, hepatotoxicity |
| Intrathecal | Aseptic meningitis, myelopathy, leukoencephalopathy |
ls /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or not found"
mkdir -p /home/daytona/workspace/methotrexate-toxicity
~/methotrexate-toxicity/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
OUTPUT = "/home/daytona/workspace/methotrexate-toxicity/Methotrexate_Toxicity.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2.2*cm, bottomMargin=2.2*cm,
title="Methotrexate Toxicity",
author="Orris Medical Reference"
)
W = A4[0] - 4*cm # usable width
styles = getSampleStyleSheet()
# Custom styles
NAVY = colors.HexColor("#1B3A6B")
TEAL = colors.HexColor("#1A7A8A")
LIGHT_BLUE = colors.HexColor("#E8F4F8")
ORANGE = colors.HexColor("#C0392B")
LIGHT_ORANGE = colors.HexColor("#FDECEA")
LIGHT_GREEN = colors.HexColor("#EAF7EA")
LIGHT_YELLOW = colors.HexColor("#FFFBEA")
MID_GRAY = colors.HexColor("#F2F4F6")
BORDER_GRAY = colors.HexColor("#CDD3DA")
h1 = ParagraphStyle("H1", parent=styles["Normal"],
fontSize=20, textColor=colors.white, fontName="Helvetica-Bold",
spaceAfter=6, spaceBefore=0, leading=24, alignment=TA_LEFT)
h2 = ParagraphStyle("H2", parent=styles["Normal"],
fontSize=13, textColor=NAVY, fontName="Helvetica-Bold",
spaceAfter=4, spaceBefore=12, leading=17)
h3 = ParagraphStyle("H3", parent=styles["Normal"],
fontSize=11, textColor=TEAL, fontName="Helvetica-Bold",
spaceAfter=3, spaceBefore=8, leading=15)
body = ParagraphStyle("Body", parent=styles["Normal"],
fontSize=9.5, textColor=colors.HexColor("#222222"),
fontName="Helvetica", leading=14, spaceAfter=4, alignment=TA_JUSTIFY)
bullet = ParagraphStyle("Bullet", parent=styles["Normal"],
fontSize=9.5, textColor=colors.HexColor("#222222"),
fontName="Helvetica", leading=14, spaceAfter=2,
leftIndent=14, firstLineIndent=-10)
sub_bullet = ParagraphStyle("SubBullet", parent=styles["Normal"],
fontSize=9, textColor=colors.HexColor("#444444"),
fontName="Helvetica", leading=13, spaceAfter=1,
leftIndent=28, firstLineIndent=-10)
caption = ParagraphStyle("Caption", parent=styles["Normal"],
fontSize=8, textColor=colors.HexColor("#666666"),
fontName="Helvetica-Oblique", leading=11, spaceAfter=2)
bold_inline = ParagraphStyle("BoldInline", parent=body,
fontName="Helvetica-Bold")
def B(text):
return f"<b>{text}</b>"
def C(text, col="#C0392B"):
return f'<font color="{col}">{text}</font>'
def section_header(title, subtitle=None):
"""Returns a navy banner header."""
content = f'<font size="14" color="white"><b>{title}</b></font>'
if subtitle:
content += f'<br/><font size="9" color="#AACCEE">{subtitle}</font>'
data = [[Paragraph(content, ParagraphStyle("BH", parent=styles["Normal"],
fontSize=14, textColor=colors.white, fontName="Helvetica-Bold",
leading=18, spaceAfter=0, spaceBefore=0))]]
t = Table(data, colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("ROUNDEDCORNERS", [4,4,4,4]),
]))
return t
def subsection_bar(title):
data = [[Paragraph(f'<b>{title}</b>', ParagraphStyle("SB", parent=styles["Normal"],
fontSize=10.5, textColor=NAVY, fontName="Helvetica-Bold", leading=14))]]
t = Table(data, colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BLUE),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("LINEBELOW", (0,0), (-1,-1), 1.5, TEAL),
]))
return t
def info_box(text, bg=LIGHT_YELLOW, border=colors.HexColor("#F0C040")):
data = [[Paragraph(text, ParagraphStyle("IB", parent=styles["Normal"],
fontSize=9, fontName="Helvetica", leading=13))]]
t = Table(data, colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING", (0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 1, border),
("ROUNDEDCORNERS", [3,3,3,3]),
]))
return t
def bp(text):
return Paragraph(f"• {text}", bullet)
def sbp(text):
return Paragraph(f"– {text}", sub_bullet)
story = []
# ── TITLE BANNER ──────────────────────────────────────────────────────────────
title_data = [[
Paragraph('<font size="22" color="white"><b>Methotrexate Toxicity</b></font><br/>'
'<font size="10" color="#AAD4E8">Comprehensive Clinical Reference</font>',
ParagraphStyle("Title", parent=styles["Normal"], leading=28, spaceAfter=0))
]]
title_table = Table(title_data, colWidths=[W])
title_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 18),
("BOTTOMPADDING", (0,0), (-1,-1), 18),
("LEFTPADDING", (0,0), (-1,-1), 16),
("RIGHTPADDING", (0,0), (-1,-1), 16),
]))
story.append(title_table)
story.append(Spacer(1, 12))
# ── MECHANISM BOX ─────────────────────────────────────────────────────────────
story.append(section_header("Mechanism of Action & Basis of Toxicity"))
story.append(Spacer(1, 6))
story.append(Paragraph(
"MTX is a <b>folate analog</b> that competitively inhibits <b>dihydrofolate reductase (DHFR)</b>, "
"blocking conversion of dihydrofolate → tetrahydrofolate. This depletes the folate pool required for "
"purine and thymidylate synthesis, halting DNA/RNA replication. <b>Intracellular polyglutamation</b> "
"traps MTX within cells, prolonging its effect. Toxicity stems from this antifolate action on rapidly "
"dividing host cells: bone marrow, GI mucosa, and liver.", body))
story.append(Spacer(1, 4))
story.append(info_box(
"⚕ <b>Key Point:</b> Leucovorin (N⁵-formyltetrahydrofolate) bypasses the DHFR block by acting as a "
"direct synthetic folate substrate — this is the basis for leucovorin rescue.",
bg=LIGHT_GREEN, border=colors.HexColor("#2E8B57")))
story.append(Spacer(1, 10))
# ── TOXICOKINETICS ────────────────────────────────────────────────────────────
story.append(section_header("Toxicokinetics"))
story.append(Spacer(1, 6))
tkin_data = [
[Paragraph("<b>Parameter</b>", body), Paragraph("<b>Detail</b>", body)],
["Oral absorption", "Saturable at doses >30 mg/m²; single acute oral ingestion unlikely toxic if renal function normal"],
["Volume of distribution", "0.4–0.8 L/kg"],
["Protein binding", "~50%"],
["Elimination", "80–90% excreted unchanged in urine (glomerular filtration + active tubular secretion)"],
["Metabolism", "Hepatic + intracellular metabolism to active metabolites"],
["Toxic levels\n(chemo doses)", ">5–10 µmol/L at 24h | >1 µmol/L at 48h | >0.1 µmol/L at 72h"],
["Non-oncologic target", "Should not exceed 0.01 µmol/L"],
["Critical risk", "Renal failure → rapid accumulation (vicious cycle)"],
]
col_w = [4*cm, W - 4*cm]
t = Table(tkin_data, colWidths=col_w, repeatRows=1)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("LEADING", (0,0), (-1,-1), 13),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, MID_GRAY]),
("GRID", (0,0), (-1,-1), 0.4, BORDER_GRAY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), NAVY),
]))
story.append(t)
story.append(Spacer(1, 12))
# ── ORGAN TOXICITIES ──────────────────────────────────────────────────────────
story.append(section_header("Organ-System Toxicities"))
story.append(Spacer(1, 8))
# 1. Bone Marrow
story.append(subsection_bar("1. Bone Marrow Suppression (Myelosuppression)"))
story.append(Spacer(1, 4))
for item in [
"<b>Pancytopenia</b> — most acute and life-threatening complication",
"Mucositis and pancytopenia manifest <b>1–2 weeks</b> after high-dose exposure",
"<b>Macrocytosis</b> may precede frank pancytopenia",
"Folate supplementation reduces but does not eliminate risk",
]:
story.append(bp(item))
story.append(Spacer(1, 8))
# 2. Hepatotoxicity
story.append(subsection_bar("2. Hepatotoxicity"))
story.append(Spacer(1, 4))
for item in [
"<b>Transaminase elevation</b> — most common, often transient",
"<b>Hepatic steatosis → fibrosis → cirrhosis</b> — cumulative dose-dependent; may take years",
"Liver biopsy is gold standard but no longer done routinely — replaced by serum biomarker panels (FibroTest) and elastography (FibroScan)",
]:
story.append(bp(item))
story.append(Spacer(1, 5))
rf_data = [
[Paragraph("<b>Risk Factors for MTX Hepatotoxicity</b>", ParagraphStyle("RFH", parent=styles["Normal"],
fontSize=9.5, fontName="Helvetica-Bold", textColor=ORANGE, leading=13)), ""],
["• Persistent abnormal LFTs", "• Diabetes mellitus"],
["• Pre-existing liver disease (hepatitis B/C, NASH)", "• Obesity / hyperlipidemia"],
["• Excessive alcohol intake", "• Lack of folate supplementation"],
["• Family history of inheritable liver disease", "• Prior hepatotoxic drug exposure"],
]
rf_col = [W/2, W/2]
rf_t = Table(rf_data, colWidths=rf_col)
rf_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_ORANGE),
("SPAN", (0,0), (1,0)),
("FONTSIZE", (0,0), (-1,-1), 9),
("LEADING", (0,0), (-1,-1), 14),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, MID_GRAY]),
("GRID", (0,0), (-1,-1), 0.4, BORDER_GRAY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
story.append(rf_t)
story.append(Spacer(1, 8))
# 3. Pulmonary
story.append(subsection_bar("3. Pulmonary Toxicity"))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Occurs in approximately <b>10%</b> of treated patients; rarely fatal. "
"Eosinophilia is present in >50% of cases, suggesting a <b>hypersensitivity mechanism</b>. "
"A key feature: the drug may sometimes be reintroduced after resolution of pneumonitis without "
"triggering recurrence.", body))
story.append(Spacer(1, 4))
pulm_syndromes = [
("<b>Methotrexate pneumonitis</b>", "Generally reversible; dyspnea, dry cough, fever; onset days–weeks after starting therapy"),
("<b>Pulmonary fibrosis</b>", "Less common; can be irreversible"),
("<b>Hypersensitivity lung disease</b>", "Often accompanied by pleural effusions"),
("<b>Noncardiogenic pulmonary edema</b>", "Associated with intrathecal administration"),
("<b>Acute chest pain syndrome</b>", "Less common presentation"),
]
for s, d in pulm_syndromes:
story.append(Paragraph(f"• {s}: {d}", bullet))
story.append(Spacer(1, 5))
# Kremer criteria box
story.append(info_box(
"<b>Diagnostic Criteria for MTX Pulmonary Toxicity (Kremer/Searles-McKendry):</b><br/>"
"Major: (1) Hypersensitivity pneumonitis on histopathology "
"(2) Radiologic interstitial/alveolar infiltrates "
"(3) Negative blood and sputum cultures<br/>"
"Risk factors: older age, pre-existing lung disease, diabetes, prior DMARDs, hypoalbuminemia",
bg=LIGHT_BLUE, border=TEAL))
story.append(Spacer(1, 8))
# 4. Renal
story.append(subsection_bar("4. Renal Toxicity"))
story.append(Spacer(1, 4))
for item in [
"MTX is a <b>weak acid (pKa 5)</b>; at high concentrations precipitates in renal tubules → <b>crystal nephropathy and AKI</b>",
"Renal impairment causes further MTX accumulation — creates a <b>vicious cycle</b>",
"Monitor creatinine/eGFR before each dose; reduce dose in renal impairment",
]:
story.append(bp(item))
story.append(Spacer(1, 8))
# 5. Neurotoxicity
story.append(subsection_bar("5. Neurotoxicity"))
story.append(Spacer(1, 4))
neuro_data = [
[Paragraph("<b>Type</b>", body), Paragraph("<b>Route / Timing</b>", body), Paragraph("<b>Features</b>", body)],
["Acute encephalopathy", "IT or high-dose IV; ~12h after HD-IV", "Confusion, seizures, focal deficits"],
["Aseptic meningitis", "Intrathecal", "Headache, fever, meningismus"],
["Myelopathy", "Intrathecal", "Limb weakness, sensory changes"],
["Leukoencephalopathy", "Months–years post-treatment", "Diffuse white matter injury; synergistic with cranial irradiation"],
]
n_col = [4*cm, 4.5*cm, W - 8.5*cm]
nt = Table(neuro_data, colWidths=n_col, repeatRows=1)
nt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("LEADING", (0,0), (-1,-1), 13),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, MID_GRAY]),
("GRID", (0,0), (-1,-1), 0.4, BORDER_GRAY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(nt)
story.append(Spacer(1, 8))
# 6. GI
story.append(subsection_bar("6. Gastrointestinal Toxicity"))
story.append(Spacer(1, 4))
for item in [
"<b>Nausea and vomiting</b> — begin 2–4h after high-dose therapy",
"<b>Oral mucositis / ulcerative stomatitis</b> — common and dose-limiting",
"<b>Diarrhea</b>",
"Often mitigated by folic acid supplementation (1–5 mg/day orally)",
]:
story.append(bp(item))
story.append(Spacer(1, 8))
# 7. Teratogenicity
story.append(subsection_bar("7. Teratogenicity & Reproductive Toxicity"))
story.append(Spacer(1, 4))
story.append(info_box(
"⚠ <b>Absolute contraindication in pregnancy</b> — MTX is an abortifacient and potent teratogen. "
"Contraindicated during breastfeeding (immune suppression, growth retardation, carcinogenesis risk).<br/>"
"Both female and male patients must discontinue MTX for <b>at least 3 months</b> before attempting conception.<br/>"
"May cause reversible oligospermia at very high doses.",
bg=LIGHT_ORANGE, border=ORANGE))
story.append(Spacer(1, 10))
# Other AEs
story.append(subsection_bar("Other Adverse Effects"))
story.append(Spacer(1, 4))
other_ae = [
["• Alopecia (usually reversible)", "• Photosensitivity — sun precautions needed"],
["• Accelerated rheumatoid nodulosis", "• EBV-mediated reversible lymphoproliferative disorders"],
["• Immunosuppression / increased infection risk", "• Macrocytosis (early sign of folate depletion)"],
]
ot = Table(other_ae, colWidths=[W/2, W/2])
ot.setStyle(TableStyle([
("FONTSIZE", (0,0), (-1,-1), 9),
("LEADING", (0,0), (-1,-1), 14),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("ROWBACKGROUNDS", (0,0), (-1,-1), [colors.white, MID_GRAY]),
("GRID", (0,0), (-1,-1), 0.4, BORDER_GRAY),
]))
story.append(ot)
story.append(Spacer(1, 12))
# ── MONITORING ────────────────────────────────────────────────────────────────
story.append(section_header("Monitoring"))
story.append(Spacer(1, 6))
mon_data = [
[Paragraph("<b>Parameter</b>", body), Paragraph("<b>Frequency</b>", body)],
["CBC + platelet count", "Monthly × 3 months at initiation; monthly after dose changes; then every 1–3 months"],
["LFTs (AST, ALT, albumin, bilirubin)", "Monthly × 3 months, then every 1–3 months"],
["Serum creatinine / eGFR", "Before each dose (especially high-dose or renal-impaired patients)"],
["Hepatic fibrosis assessment", "Serum biomarkers (FibroTest) ± FibroScan; liver biopsy if indicated"],
["Chest X-ray + baseline PFTs", "Before starting (especially if pre-existing lung disease)"],
["Serum MTX levels", "Mandatory with high-dose chemotherapy protocols at 24h, 48h, 72h"],
["Urine pH (during HD-MTX)", "Target urine pH ≥8 with sodium bicarbonate infusion"],
]
m_col = [5*cm, W - 5*cm]
mt = Table(mon_data, colWidths=m_col, repeatRows=1)
mt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("LEADING", (0,0), (-1,-1), 13),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, MID_GRAY]),
("GRID", (0,0), (-1,-1), 0.4, BORDER_GRAY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), NAVY),
]))
story.append(mt)
story.append(Spacer(1, 12))
# ── DRUG INTERACTIONS ─────────────────────────────────────────────────────────
story.append(section_header("Drug Interactions Increasing Toxicity"))
story.append(Spacer(1, 6))
di_data = [
[Paragraph("<b>Drug / Class</b>", body), Paragraph("<b>Mechanism</b>", body), Paragraph("<b>Result</b>", body)],
["NSAIDs", "Reduce renal MTX clearance", "↑ myelosuppression, mucositis"],
["Probenecid", "Decreases tubular secretion of MTX", "↑ MTX levels"],
["Trimethoprim", "Additive DHFR inhibition", "↑ myelosuppression"],
["Penicillins", "Reduce renal excretion", "↑ MTX accumulation"],
["Leflunomide", "Additive hepatotoxicity", "↑ hepatotoxicity risk"],
["Alcohol", "Additive hepatotoxicity", "↑ fibrosis risk"],
["PPIs (omeprazole)", "May reduce renal MTX excretion", "↑ MTX levels"],
]
di_col = [3.5*cm, 5*cm, W - 8.5*cm]
dit = Table(di_data, colWidths=di_col, repeatRows=1)
dit.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("LEADING", (0,0), (-1,-1), 13),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, MID_GRAY]),
("GRID", (0,0), (-1,-1), 0.4, BORDER_GRAY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(dit)
story.append(Spacer(1, 12))
# ── TREATMENT ─────────────────────────────────────────────────────────────────
story.append(section_header("Treatment of MTX Toxicity"))
story.append(Spacer(1, 6))
tx_data = [
[Paragraph("<b>Intervention</b>", body), Paragraph("<b>Indication / Mechanism</b>", body)],
[Paragraph("<b>Activated charcoal</b>", body),
"Early after acute oral overdose only (limited benefit); not for parenteral overdose"],
[Paragraph("<b>Aggressive IV hydration</b>", body),
"All significant MTX toxicity; promotes renal excretion; prevents crystal nephropathy"],
[Paragraph('<b>Urine alkalinization</b>\n(IV NaHCO₃, target pH ≥8)', body),
"Enhances renal excretion of this weak acid (pKa 5); prevents tubular precipitation"],
[Paragraph('<b>Leucovorin (folinic acid) rescue</b>', body),
"MOST IMPORTANT antidote. Bypasses DHFR block. Give promptly — most effective early. Always give after supratherapeutic exposure. Continues until MTX levels <0.05 µmol/L"],
[Paragraph('<b>Glucarpidase (CPDG2)</b>', body),
"Recombinant enzyme that catabolizes MTX. Used when leucovorin is insufficient or AKI is present. Rapidly reduces plasma MTX by >95%"],
[Paragraph('<b>Blood product transfusion</b>', body),
"For established cytopenias (packed RBCs, platelets, G-CSF if needed)"],
[Paragraph('<b>High-flux IHD / Charcoal hemoperfusion</b>', body),
"Extracorporeal removal for very high levels (especially with AKI). Indicated if MTX >30–300 µmol/L at 24h or >3–30 µmol/L at 48h. Continue until <0.1 µmol/L. Beware of rebound."],
[Paragraph('<b>IT MTX overdose</b>', body),
"CSF drainage + exchange ± dexamethasone + leucovorin/glucarpidase via IT route"],
]
tx_col = [4.5*cm, W - 4.5*cm]
txt = Table(tx_data, colWidths=tx_col, repeatRows=1)
txt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("LEADING", (0,0), (-1,-1), 13),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, MID_GRAY]),
("BACKGROUND", (0,4), (-1,4), colors.HexColor("#E8F5E9")), # highlight leucovorin
("GRID", (0,0), (-1,-1), 0.4, BORDER_GRAY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(txt)
story.append(Spacer(1, 12))
# ── DOSE-BASED TOXICITY SUMMARY ───────────────────────────────────────────────
story.append(section_header("Toxicity by Dose Setting"))
story.append(Spacer(1, 6))
dose_data = [
[Paragraph("<b>Setting</b>", body), Paragraph("<b>Dose Range</b>", body), Paragraph("<b>Predominant Toxicities</b>", body)],
["Low-dose weekly\n(RA, psoriasis)", "7.5–25 mg/week", "Hepatotoxicity, mucositis, GI upset, pneumonitis, myelosuppression"],
["Intermediate dose", "20–100 mg/m²", "Myelosuppression, mucositis, hepatotoxicity"],
["High-dose (HD-MTX)\nwith leucovorin rescue", ">500–1000 mg/m²", "Renal crystal nephropathy, severe mucositis, CNS toxicity, hepatotoxicity"],
["Intrathecal", "10–15 mg/dose", "Aseptic meningitis, myelopathy, leukoencephalopathy, noncardiogenic pulmonary edema"],
]
d_col = [3.5*cm, 3.5*cm, W - 7*cm]
dt = Table(dose_data, colWidths=d_col, repeatRows=1)
dt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("LEADING", (0,0), (-1,-1), 13),
("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, MID_GRAY]),
("GRID", (0,0), (-1,-1), 0.4, BORDER_GRAY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), NAVY),
]))
story.append(dt)
story.append(Spacer(1, 12))
# ── CONTRAINDICATIONS ─────────────────────────────────────────────────────────
story.append(section_header("Contraindications"))
story.append(Spacer(1, 6))
ci_data = [
[Paragraph("<b>Absolute</b>", ParagraphStyle("CI", parent=styles["Normal"],
fontSize=10, fontName="Helvetica-Bold", textColor=ORANGE, leading=14)),
Paragraph("<b>Relative</b>", ParagraphStyle("CI2", parent=styles["Normal"],
fontSize=10, fontName="Helvetica-Bold", textColor=TEAL, leading=14))],
[Paragraph("• Pregnancy (abortifacient + teratogen)\n• Breastfeeding\n• Severe hepatic disease", body),
Paragraph("• Significant renal impairment (dose-reduce)\n• Active infection or immunodeficiency\n• Significant liver disease / elevated LFTs\n• Excessive alcohol use\n• Desire for imminent pregnancy", body)],
]
cit = Table(ci_data, colWidths=[W/2, W/2])
cit.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), LIGHT_ORANGE),
("BACKGROUND", (1,0), (1,0), LIGHT_BLUE),
("GRID", (0,0), (-1,-1), 0.4, BORDER_GRAY),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "TOP"),
("FONTSIZE", (0,1), (-1,-1), 9),
]))
story.append(cit)
story.append(Spacer(1, 14))
# ── FOOTER ────────────────────────────────────────────────────────────────────
story.append(HRFlowable(width=W, thickness=1, color=BORDER_GRAY))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Sources: Harrison's Principles of Internal Medicine 22E (2025) | Brenner & Rector's The Kidney | "
"Murray & Nadel's Respiratory Medicine | Fishman's Pulmonary Diseases | Bradley & Daroff's Neurology | "
"Goodman & Gilman's Pharmacological Basis of Therapeutics | Dermatology 5e | Firestein & Kelley's Rheumatology | "
"Goldman-Cecil Medicine | Tietz Textbook of Laboratory Medicine 7e",
ParagraphStyle("Footer", parent=styles["Normal"],
fontSize=7.5, textColor=colors.HexColor("#888888"), fontName="Helvetica-Oblique",
leading=11, alignment=TA_CENTER)))
doc.build(story)
print(f"PDF written to: {OUTPUT}")
cd /home/daytona/workspace/methotrexate-toxicity && python generate_pdf.py
Methotrexate Toxicity
PDF Document · PDF