treatment protocol to follow with drugs and dosage in detail for imtp in dogs
immune-mediated thrombocytopenia dogs treatment
IMTP immune-mediated thrombocytopenia dogs treatment protocol drugs dosage 2024
https://pmc.ncbi.nlm.nih.gov/articles/PMC11256181
https://www.dvm360.com/view/overcoming-diagnostic-and-therap…
| Category | Definition |
|---|---|
| No response | Platelet count <30,000/µL or ongoing bleeding after 2 weeks |
| Partial response | Platelet count 30,000-100,000/µL with >2-fold increase from baseline, no bleeding |
| Complete response | Platelet count ≥100,000/µL, no bleeding |
| Full remission | Platelet count ≥100,000/µL, no bleeding, off all treatment |
| Drug | Dose | Route | Frequency |
|---|---|---|---|
| Prednisolone (preferred over prednisone) | 2-4 mg/kg/day | PO | Once daily or divided q12h |
| Prednisone | 2-4 mg/kg/day | PO | Once daily or divided q12h |
| Dexamethasone (if cannot take oral) | 0.2-0.3 mg/kg | IV | q24h |
| Drug | Dose | Route | Frequency |
|---|---|---|---|
| Vincristine | 0.02 mg/kg IV (max 0.5 mg/m² for dogs >25 kg) | IV | Single dose only |
| Drug | Dose | Route | Duration |
|---|---|---|---|
| hIVIg | 0.5-1.5 g/kg | IV infusion | Over 6-12 hours (single infusion) |
| Drug | Dose | Route | Schedule |
|---|---|---|---|
| Azathioprine | 2 mg/kg/day | PO | q24h for first 2-4 weeks, then taper to every other day (q48h) |
| Drug | Dose | Route | Schedule |
|---|---|---|---|
| Cyclosporine (modified, e.g., Atopica) | 5 mg/kg | PO | q12-24h |
| Drug | Dose | Route | Schedule |
|---|---|---|---|
| Mycophenolate mofetil | 10-15 mg/kg | PO | q12h |
| Drug | Dose | Route | Schedule |
|---|---|---|---|
| Leflunomide | 2-4 mg/kg/day | PO | Once daily |
| Option | Notes |
|---|---|
| Splenectomy | Reserved for truly refractory cases; removes the primary site of platelet destruction and antiplatelet antibody production |
| Danazol (synthetic androgen) | 5-10 mg/kg PO q12h; reduces platelet destruction; slow onset (weeks to months) |
| Cyclophosphamide | 50 mg/m² PO on days 1-4 of each week; maximum 4-5 months; reserved for refractory cases - less favored due to toxicity |
| Thrombopoietin receptor agonists (e.g., eltrombopag, romiplostim) | Emerging use in refractory IMTP; stimulate platelet production |
| Therapeutic plasma exchange (plasmapheresis) | Not routinely recommended per 2024 ACVIM guidelines |
| Timeframe | Action |
|---|---|
| Initial (platelet count <40,000-50,000/µL) | Hospitalize; CBC every 2-3 days |
| Outpatient (platelet count >40,000-50,000/µL) | Recheck every 1-2 weeks during active treatment |
| During taper | Confirm platelet count immediately before each dose reduction |
| Liver/kidney function | Monitor throughout treatment (baseline, then every 4-8 weeks) |
| Azathioprine monitoring | CBC + liver enzymes q1-2 weeks for first month, then q2-4 weeks |
| Drug | Dose | Route | Notes |
|---|---|---|---|
| Prednisolone | 2-4 mg/kg/day | PO | First-line; continue 2-3+ weeks |
| Dexamethasone | 0.2-0.3 mg/kg | IV | If oral not possible |
| Vincristine | 0.02 mg/kg (max 0.5 mg/m²) | IV | Single dose; for active bleeding |
| hIVIg | 0.5-1.5 g/kg | IV over 6-12h | Expensive; alternative to vincristine |
| Azathioprine | 2 mg/kg/day → q48h | PO | Second-line; onset 2-4 weeks |
| Cyclosporine (modified) | 5 mg/kg q12-24h | PO | Second-line; delay after vincristine |
| MMF | 10-15 mg/kg q12h | PO | Second-line alternative |
| Leflunomide | 2-4 mg/kg/day | PO | Second-line alternative |
| Doxycycline | 5-10 mg/kg q12h | PO/IV | Empirical for tick-borne disease |
| Cyclophosphamide | 50 mg/m² days 1-4/week | PO | Refractory only; max 4-5 months |
| Danazol | 5-10 mg/kg q12h | PO | Refractory adjunct; slow onset |
Create a treatment decision flowchart for IMTP in dogs (PDF)
mkdir -p /tmp/workspace/imtp-flowchart && ls /tmp/workspace/imtp-flowchart/
~/imtp-flowchart/create_flowchart.py
from reportlab.lib.pagesizes import A3, landscape
from reportlab.pdfgen import canvas
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.colors import HexColor
import math
# ── colour palette ──────────────────────────────────────────────────────────
C_TITLE_BG = HexColor("#1A3A5C") # deep navy
C_TITLE_FG = colors.white
C_START = HexColor("#1A3A5C") # oval start
C_EMERGENCY = HexColor("#C0392B") # red
C_FIRST = HexColor("#1A6B3C") # dark green
C_SECOND = HexColor("#1565C0") # deep blue
C_MONITOR = HexColor("#6A0DAD") # purple
C_TAPER = HexColor("#E67E22") # orange
C_REFRACTORY = HexColor("#7F8C8D") # grey
C_DIAMOND = HexColor("#F5A623") # decision yellow
C_REMISSION = HexColor("#27AE60") # bright green
C_LIGHT_GREY = HexColor("#F4F6F9")
C_BOX_STROKE = HexColor("#2C3E50")
WHITE = colors.white
OUTPUT = "/tmp/workspace/imtp-flowchart/IMTP_Treatment_Flowchart.pdf"
PAGE_W, PAGE_H = landscape(A3)
c = canvas.Canvas(OUTPUT, pagesize=landscape(A3))
c.setTitle("IMTP in Dogs – Treatment Decision Flowchart")
# ═══════════════════════════════════════════════════════════════════════════
# Helper functions
# ═══════════════════════════════════════════════════════════════════════════
def rounded_rect(canvas_obj, x, y, w, h, r, fill_color, stroke_color=C_BOX_STROKE,
stroke_width=1.2):
"""Draw a filled rounded rectangle."""
canvas_obj.setFillColor(fill_color)
canvas_obj.setStrokeColor(stroke_color)
canvas_obj.setLineWidth(stroke_width)
canvas_obj.roundRect(x, y, w, h, r, fill=1, stroke=1)
def draw_box(canvas_obj, cx, cy, w, h, title, lines, fill_color,
title_color=WHITE, text_color=WHITE,
font_title="Helvetica-Bold", font_body="Helvetica",
title_size=8, body_size=7, r=5):
"""Draw a labelled process box centred at (cx, cy)."""
x = cx - w / 2
y = cy - h / 2
rounded_rect(canvas_obj, x, y, w, h, r, fill_color)
# title bar
bar_h = title_size + 5
canvas_obj.setFillColor(HexColor("#00000033"))
canvas_obj.roundRect(x, y + h - bar_h, w, bar_h, r, fill=1, stroke=0)
canvas_obj.setFillColor(title_color)
canvas_obj.setFont(font_title, title_size)
canvas_obj.drawCentredString(cx, y + h - bar_h + 3, title)
# body lines
canvas_obj.setFillColor(text_color)
canvas_obj.setFont(font_body, body_size)
start_y = y + h - bar_h - body_size - 3
for line in lines:
canvas_obj.drawCentredString(cx, start_y, line)
start_y -= body_size + 2
def draw_diamond(canvas_obj, cx, cy, w, h, label, sublabel="",
fill_color=C_DIAMOND, text_color=WHITE):
"""Draw a decision diamond centred at (cx, cy)."""
canvas_obj.setFillColor(fill_color)
canvas_obj.setStrokeColor(C_BOX_STROKE)
canvas_obj.setLineWidth(1.2)
path = canvas_obj.beginPath()
path.moveTo(cx, cy + h/2)
path.lineTo(cx + w/2, cy)
path.lineTo(cx, cy - h/2)
path.lineTo(cx - w/2, cy)
path.close()
canvas_obj.drawPath(path, fill=1, stroke=1)
canvas_obj.setFillColor(text_color)
canvas_obj.setFont("Helvetica-Bold", 8)
canvas_obj.drawCentredString(cx, cy + 3, label)
if sublabel:
canvas_obj.setFont("Helvetica", 7)
canvas_obj.drawCentredString(cx, cy - 9, sublabel)
def arrow(canvas_obj, x1, y1, x2, y2, label="", label_side="right",
color=C_BOX_STROKE, lw=1.2):
"""Draw an arrow from (x1,y1) to (x2,y2) with optional label."""
canvas_obj.setStrokeColor(color)
canvas_obj.setLineWidth(lw)
canvas_obj.line(x1, y1, x2, y2)
# arrowhead
angle = math.atan2(y2 - y1, x2 - x1)
ah = 7
aw = 4
ax1 = x2 - ah * math.cos(angle) + aw * math.sin(angle)
ay1 = y2 - ah * math.sin(angle) - aw * math.cos(angle)
ax2 = x2 - ah * math.cos(angle) - aw * math.sin(angle)
ay2 = y2 - ah * math.sin(angle) + aw * math.cos(angle)
canvas_obj.setFillColor(color)
p = canvas_obj.beginPath()
p.moveTo(x2, y2)
p.lineTo(ax1, ay1)
p.lineTo(ax2, ay2)
p.close()
canvas_obj.drawPath(p, fill=1, stroke=0)
if label:
canvas_obj.setFillColor(C_BOX_STROKE)
canvas_obj.setFont("Helvetica-Bold", 7)
mx, my = (x1+x2)/2, (y1+y2)/2
if label_side == "right":
canvas_obj.drawString(mx + 3, my, label)
else:
canvas_obj.drawRightString(mx - 3, my, label)
def oval(canvas_obj, cx, cy, w, h, text, fill_color=C_START, text_color=WHITE):
canvas_obj.setFillColor(fill_color)
canvas_obj.setStrokeColor(C_BOX_STROKE)
canvas_obj.setLineWidth(1.5)
canvas_obj.ellipse(cx - w/2, cy - h/2, cx + w/2, cy + h/2, fill=1, stroke=1)
canvas_obj.setFillColor(text_color)
canvas_obj.setFont("Helvetica-Bold", 9)
canvas_obj.drawCentredString(cx, cy - 3, text)
# ═══════════════════════════════════════════════════════════════════════════
# PAGE BACKGROUND
# ═══════════════════════════════════════════════════════════════════════════
c.setFillColor(C_LIGHT_GREY)
c.rect(0, 0, PAGE_W, PAGE_H, fill=1, stroke=0)
# ── Title bar ───────────────────────────────────────────────────────────────
c.setFillColor(C_TITLE_BG)
c.rect(0, PAGE_H - 48, PAGE_W, 48, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 18)
c.drawCentredString(PAGE_W/2, PAGE_H - 28, "IMTP in Dogs – Treatment Decision Flowchart")
c.setFont("Helvetica", 9)
c.drawCentredString(PAGE_W/2, PAGE_H - 42,
"Immune-Mediated Thrombocytopenia | Based on 2024 ACVIM Consensus Statement")
# ── Footer ───────────────────────────────────────────────────────────────────
c.setFillColor(C_TITLE_BG)
c.rect(0, 0, PAGE_W, 18, fill=1, stroke=0)
c.setFillColor(WHITE)
c.setFont("Helvetica", 7)
c.drawCentredString(PAGE_W/2, 5,
"Reference: LeVine DN, Goggs R, Kohn B et al. ACVIM Consensus Statement on Treatment of ITP. J Vet Intern Med 2024;38(4):1982-2007")
# ═══════════════════════════════════════════════════════════════════════════
# LEGEND
# ═══════════════════════════════════════════════════════════════════════════
legend_items = [
(C_START, "Start / End"),
(C_EMERGENCY, "Emergency Support"),
(C_FIRST, "First-Line Tx"),
(C_SECOND, "Second-Line Tx"),
(C_MONITOR, "Monitoring"),
(C_TAPER, "Taper Protocol"),
(C_REFRACTORY, "Refractory Tx"),
(C_DIAMOND, "Decision Point"),
(C_REMISSION, "Remission"),
]
lx = PAGE_W - 170
ly = PAGE_H - 70
c.setFillColor(WHITE)
c.setStrokeColor(C_BOX_STROKE)
c.setLineWidth(0.8)
c.roundRect(lx - 8, ly - len(legend_items)*14 - 4, 170, len(legend_items)*14 + 20, 4, fill=1, stroke=1)
c.setFillColor(C_TITLE_BG)
c.setFont("Helvetica-Bold", 8)
c.drawString(lx, ly + 4, "LEGEND")
for i, (col, lbl) in enumerate(legend_items):
yy = ly - 12 - i*14
c.setFillColor(col)
c.setStrokeColor(C_BOX_STROKE)
c.setLineWidth(0.5)
c.roundRect(lx, yy, 12, 10, 2, fill=1, stroke=1)
c.setFillColor(C_BOX_STROKE)
c.setFont("Helvetica", 7.5)
c.drawString(lx + 16, yy + 1.5, lbl)
# ═══════════════════════════════════════════════════════════════════════════
# LAYOUT (all coords in points; A3 landscape = 1191 x 842 pt)
# Main column X positions
# ═══════════════════════════════════════════════════════════════════════════
# We lay the flowchart top-to-bottom with some branching left/right.
# ── X coordinates of main lane ───────────────────────────────────────────
MX = 340 # main centre-x
BW = 210 # box width (main)
BH = 60 # box height (main)
BW2 = 175 # second-line box width
BH2 = 75
# ── Y positions (from top of usable area, below title bar) ────────────────
TOP = PAGE_H - 60 # just under title
USABLE = TOP - 22 # above footer
# Row centres (y)
R = {}
R[0] = USABLE - 35 # START oval
R[1] = R[0] - 65 # Emergency stabilisation
R[2] = R[1] - 75 # D1: Bleeding / platelet < 20k?
R[3] = R[2] - 75 # Vincristine / hIVIg box (left branch)
R[4] = R[3] - 10 # merge back
R[5] = R[2] - 65 # Glucocorticoids (first line) ← same level merge
R[6] = R[5] - 75 # D2: Response at day 5-7?
R[7] = R[6] - 70 # Add second-line immunosuppressant
R[8] = R[7] - 80 # Second-line options (multi-box)
R[9] = R[8] - 80 # D3: Response at 2 weeks?
R[10] = R[9] - 70 # Refractory options
R[11] = R[6] - 0 # (right branch of D2 – complete response)
R[12] = R[9] - 0 # (right branch of D3 – complete response merge)
R_MONITOR = R[7] - 15 # monitoring block on right
R_TAPER = R[9] - 140 # taper block (right of D3 yes)
R_REMIS = R_TAPER - 75 # full remission
# ── Recalculate cleaner layout ────────────────────────────────────────────
# Use explicit y values to avoid overlap
y_start = USABLE - 30
y_emerg = y_start - 68
y_d1 = y_emerg - 80 # diamond: clinically significant bleeding?
y_adjunct = y_d1 - 80 # vincristine / hIVIg (left branch)
y_firstl = y_adjunct - 55 # merge → first-line glucocorticoids
y_d2 = y_firstl - 82 # diamond: response day 5-7?
y_second = y_d2 - 82 # add second-line drug
y_opts = y_second - 85 # four option boxes
y_d3 = y_opts - 82 # diamond: complete response at 2 weeks?
y_refrac = y_d3 - 82 # refractory measures
y_end = y_refrac - 65 # refractory end
# Right-side taper track
y_taper = y_d2 - 55 # taper protocol (right of D2 YES)
y_d_rem = y_taper - 80 # diamond: full remission?
y_remis = y_d_rem - 70 # full remission oval
y_relapse = y_d_rem - 0 # relapse path goes right
# Monitor box (far right)
MONX = MX + 290
MON_W = 165
MON_H = 100
# ─────────────────────────────────────────────────────────────────────────
# ROW 0 – START
# ─────────────────────────────────────────────────────────────────────────
oval(c, MX, y_start, 200, 32, "Dog with Suspected IMTP",
fill_color=C_START)
arrow(c, MX, y_start - 16, MX, y_emerg + BH/2)
# ─────────────────────────────────────────────────────────────────────────
# ROW 1 – Emergency Stabilisation
# ─────────────────────────────────────────────────────────────────────────
draw_box(c, MX, y_emerg, BW+30, BH+15, "EMERGENCY STABILISATION",
["IV fluids (crystalloids / plasma if colloid needed)",
"Blood products (pRBC / whole blood) if severe anaemia",
"Doxycycline 5-10 mg/kg PO/IV q12h (pending tick titres)",
"Discontinue NSAIDs / platelet-inhibiting drugs",
"GI protectants if GI haemorrhage suspected"],
C_EMERGENCY, title_size=8, body_size=6.5, r=6)
arrow(c, MX, y_emerg - BH/2 - 7, MX, y_d1 + 32)
# ─────────────────────────────────────────────────────────────────────────
# ROW 2 – DIAMOND 1: Clinically significant bleeding or plt < 20,000?
# ─────────────────────────────────────────────────────────────────────────
draw_diamond(c, MX, y_d1, 260, 60,
"Clinically significant bleeding",
"or platelet count < 20,000/µL?")
# YES branch (left)
LBX = MX - 190 # left branch X
arrow(c, MX - 130, y_d1, LBX + 85, y_d1, label="YES", label_side="left")
arrow(c, LBX, y_d1, LBX, y_adjunct + BH/2)
draw_box(c, LBX, y_adjunct, 165, BH + 5,
"ADJUNCTIVE (choose one)",
["Vincristine 0.02 mg/kg IV (single dose)",
" max 0.5 mg/m² if > 25 kg",
"OR hIVIg 0.5–1.5 g/kg IV over 6-12 h",
" (if not used previously / high cost)"],
C_FIRST, title_size=7.5, body_size=6.5, r=5)
# re-join arrow from adjunct box down to firstl
arrow(c, LBX, y_adjunct - BH/2 - 5, LBX, y_firstl + BH/2,
color=HexColor("#555555"))
arrow(c, LBX, y_firstl, MX - BW/2 - 5, y_firstl,
color=HexColor("#555555"))
# NO branch (straight down)
arrow(c, MX, y_d1 - 30, MX, y_firstl + BH/2, label="NO")
# ─────────────────────────────────────────────────────────────────────────
# ROW 3 – First-line: Glucocorticoids
# ─────────────────────────────────────────────────────────────────────────
draw_box(c, MX, y_firstl, BW + 20, BH + 20,
"FIRST-LINE: GLUCOCORTICOIDS",
["Prednisolone 2–4 mg/kg/day PO (preferred)",
"OR Prednisone 2–4 mg/kg/day PO",
"OR Dexamethasone 0.2–0.3 mg/kg IV q24h",
" (if oral administration not possible)",
"Continue induction dose ≥ 2–3 weeks"],
C_FIRST, title_size=8, body_size=6.8, r=6)
arrow(c, MX, y_firstl - BH/2 - 10, MX, y_d2 + 32)
# ─────────────────────────────────────────────────────────────────────────
# MONITORING BOX (right side, beside first-line)
# ─────────────────────────────────────────────────────────────────────────
mon_cx = MX + 290
mon_cy = y_firstl - 30
draw_box(c, mon_cx, mon_cy, MON_W, MON_H + 10,
"MONITORING",
["CBC every 2-3 days if plt < 40,000/µL",
"Hospitalise if plt < 40-50 × 10⁹/L",
"Outpatient if plt > 40-50 × 10⁹/L",
"Recheck plt every 1-2 wks during taper",
"LFTs + renal panel baseline, then q4-8 wks",
"If azathioprine: CBC + LFTs q1-2 wks × 1 mo"],
C_MONITOR, title_size=8, body_size=6.5, r=5)
# dashed connector
c.setDash(4, 3)
c.setStrokeColor(C_MONITOR)
c.setLineWidth(1)
c.line(MX + BW/2 + 10, y_firstl, mon_cx - MON_W/2, mon_cy + 5)
c.setDash() # reset
# ─────────────────────────────────────────────────────────────────────────
# ROW 4 – DIAMOND 2: Response at day 5-7?
# ─────────────────────────────────────────────────────────────────────────
draw_diamond(c, MX, y_d2, 250, 60,
"Response at Day 5–7?",
"(plt rising / no active bleeding)")
# YES → right to taper track
TAPX = MX + 290 # right track X
arrow(c, MX + 125, y_d2, TAPX - 82, y_d2, label="YES")
draw_box(c, TAPX, y_d2, 160, BH + 15,
"TAPER GLUCOCORTICOIDS",
["Reduce dose ~20-25% every 2-4 wks",
"Confirm plt stable BEFORE each reduction",
"Also taper 2nd-line drug in tandem",
"Total duration: typically 3-6 months",
"More gradual if prior relapse history"],
C_TAPER, title_size=7.5, body_size=6.5, r=5)
# diamond below taper: full remission?
y_d_rem2 = y_d2 - 100
draw_diamond(c, TAPX, y_d_rem2, 175, 52,
"Full Remission?",
"plt ≥ 100k, off all treatment")
arrow(c, TAPX, y_d2 - BH/2 - 8, TAPX, y_d_rem2 + 26)
# YES → remission oval
y_remis2 = y_d_rem2 - 75
oval(c, TAPX, y_remis2, 160, 32,
"FULL REMISSION", fill_color=C_REMISSION)
arrow(c, TAPX, y_d_rem2 - 26, TAPX, y_remis2 + 16, label="YES")
# NO → relapse instruction
y_relapse2 = y_d_rem2 - 40
relapse_x = TAPX + 130
draw_box(c, relapse_x, y_relapse2 - 15, 155, 55,
"RELAPSE MANAGEMENT",
["Mild: return to last effective dose",
"Severe: restart full induction",
"Re-give vincristine ± hIVIg (if not prev. used)",
"Future tapers: more gradual",
"Consider lifelong maintenance therapy"],
C_REFRACTORY, title_size=7.5, body_size=6.2, r=5)
arrow(c, TAPX + 87, y_d_rem2, relapse_x - 77, y_relapse2 - 15 + 55/2,
label="NO")
# NO → second line
arrow(c, MX, y_d2 - 30, MX, y_second + BH2/2, label="NO")
# ─────────────────────────────────────────────────────────────────────────
# ROW 5 – Second-line header
# ─────────────────────────────────────────────────────────────────────────
draw_box(c, MX, y_second, BW, 38,
"ADD SECOND-LINE IMMUNOSUPPRESSANT",
["(Choose ONE based on clinician preference / patient factors)",
"Onset 2–4 weeks – start early if anticipated"],
C_SECOND, title_size=8, body_size=6.8, r=6)
arrow(c, MX, y_second - 19, MX, y_opts + BH2/2)
# ─────────────────────────────────────────────────────────────────────────
# ROW 6 – Four second-line option boxes
# ─────────────────────────────────────────────────────────────────────────
opt_w = 148
opt_h = 80
opt_gap = 12
n_opts = 4
total_w = n_opts * opt_w + (n_opts - 1) * opt_gap
opt_x0 = MX - total_w / 2 + opt_w / 2
opts = [
("AZATHIOPRINE\n(most common)",
["2 mg/kg/day PO × 2-4 wks",
"then q48h (every other day)",
"Onset: 2-4 weeks",
"Monitor: CBC + LFTs q1-2 wks",
"S/E: myelosuppression,",
"hepatotoxicity, pancreatitis"]),
("CYCLOSPORINE\n(modified)",
["5 mg/kg PO q12-24h",
"Trough target 200-400 ng/mL",
"Delay several days post-vincristine",
"S/E: vomiting, diarrhoea,",
"gingival hyperplasia,",
"opportunistic infections"]),
("MYCOPHENOLATE\nMOFETIL (MMF)",
["10-15 mg/kg PO q12h",
"Alternative if azathioprine",
"not tolerated",
"S/E: GI upset (diarrhoea),",
"bone marrow suppression",
""]),
("LEFLUNOMIDE",
["2-4 mg/kg/day PO",
"Once daily",
"Use when other options failed",
"or not tolerated",
"S/E: hepatotoxicity,",
"bone marrow suppression"]),
]
for i, (title_raw, lines) in enumerate(opts):
title = title_raw.replace("\n", " ")
ox = opt_x0 + i * (opt_w + opt_gap)
draw_box(c, ox, y_opts, opt_w, opt_h, title, lines,
C_SECOND, title_size=7, body_size=6.2, r=5)
# small arrow from header to each box
arrow(c, opt_x0 + i*(opt_w+opt_gap), y_second - 19,
opt_x0 + i*(opt_w+opt_gap), y_opts + opt_h/2,
color=HexColor("#1565C0"), lw=0.8)
arrow(c, MX, y_opts - opt_h/2, MX, y_d3 + 30)
# ─────────────────────────────────────────────────────────────────────────
# ROW 7 – DIAMOND 3: Complete response at 2 weeks?
# ─────────────────────────────────────────────────────────────────────────
draw_diamond(c, MX, y_d3, 255, 60,
"Complete Response at 2 Weeks?",
"plt ≥ 100,000/µL, no bleeding")
# YES → right (join taper track)
arrow(c, MX + 127, y_d3, TAPX - 82, y_d2 - 30,
label="YES", color=HexColor("#27AE60"))
# join taper box
arrow(c, TAPX, y_d2 - BH/2 - 3, TAPX, y_d2 - BH/2 - 8,
color=HexColor("#27AE60"), lw=0.8)
# NO → refractory
arrow(c, MX, y_d3 - 30, MX, y_refrac + BH/2, label="NO")
# ─────────────────────────────────────────────────────────────────────────
# ROW 8 – Refractory
# ─────────────────────────────────────────────────────────────────────────
draw_box(c, MX, y_refrac, BW + 40, BH + 20,
"REFRACTORY MEASURES",
["Reassess diagnosis – rule out secondary causes",
"Splenectomy (removes site of plt destruction)",
"Danazol 5-10 mg/kg PO q12h (slow onset, weeks-months)",
"Thrombopoietin receptor agonist (eltrombopag / romiplostim)",
"Cyclophosphamide 50 mg/m² PO days 1-4/wk (max 4-5 mo)"],
C_REFRACTORY, title_size=8, body_size=6.5, r=6)
arrow(c, MX, y_refrac - BH/2 - 10, MX, y_end + 18)
# END oval
oval(c, MX, y_end, 200, 32,
"Reassess & Individualise Care", fill_color=HexColor("#2C3E50"))
# ─────────────────────────────────────────────────────────────────────────
# ABCB1 / MDR1 caution note
# ─────────────────────────────────────────────────────────────────────────
note_x = 22
note_y = y_d1 - 10
c.setFillColor(HexColor("#FFF9C4"))
c.setStrokeColor(HexColor("#F5A623"))
c.setLineWidth(1)
c.roundRect(note_x, note_y - 55, 145, 60, 4, fill=1, stroke=1)
c.setFillColor(HexColor("#7B3F00"))
c.setFont("Helvetica-Bold", 7.5)
c.drawString(note_x + 5, note_y - 8, "⚠ ABCB1 / MDR1 BREEDS")
c.setFont("Helvetica", 6.5)
for i, line in enumerate([
"Collies, Australian Shepherds,",
"Shetland Sheepdogs, Border Collies",
"→ Use CAUTION with vincristine",
"→ Consider genetic testing",
"→ Reduce dose or avoid if mutant"
]):
c.drawString(note_x + 5, note_y - 20 - i * 9, line)
# ─────────────────────────────────────────────────────────────────────────
# RESPONSE CRITERIA side note
# ─────────────────────────────────────────────────────────────────────────
rc_x = 22
rc_y = y_d3 + 50
c.setFillColor(HexColor("#E3F2FD"))
c.setStrokeColor(HexColor("#1565C0"))
c.setLineWidth(1)
c.roundRect(rc_x, rc_y - 75, 155, 82, 4, fill=1, stroke=1)
c.setFillColor(HexColor("#0D2B5C"))
c.setFont("Helvetica-Bold", 7.5)
c.drawString(rc_x + 5, rc_y - 10, "RESPONSE CRITERIA")
c.setFont("Helvetica", 6.5)
rows = [
("No response:", "plt <30k or bleeding at 2 wks"),
("Partial resp.:", "plt 30-100k, >2× baseline,"),
("", "no bleeding"),
("Complete:", "plt ≥100k, no bleeding"),
("Full remission:","plt ≥100k, off all treatment"),
]
yy = rc_y - 23
for label, val in rows:
if label:
c.setFont("Helvetica-Bold", 6.5)
c.drawString(rc_x + 5, yy, label)
c.setFont("Helvetica", 6.5)
c.drawString(rc_x + 62, yy, val)
else:
c.setFont("Helvetica", 6.5)
c.drawString(rc_x + 62, yy, val)
yy -= 10
# ─────────────────────────────────────────────────────────────────────────
# SAVE
# ─────────────────────────────────────────────────────────────────────────
c.save()
print(f"Saved to {OUTPUT}")
cd /tmp/workspace/imtp-flowchart && python create_flowchart.py 2>&1
python3 -c " from pypdf import PdfReader r = PdfReader('/tmp/workspace/imtp-flowchart/IMTP_Treatment_Flowchart.pdf') print(f'Pages: {len(r.pages)}') print(f'Size: {r.pages[0].mediabox}') import os print(f'File size: {os.path.getsize(\"/tmp/workspace/imtp-flowchart/IMTP_Treatment_Flowchart.pdf\")/1024:.1f} KB') "
IMTP Treatment Flowchart
PDF Document · PDF