SAS-Taper · how it works

How the dashed line is drawn

Not medical advice. The first graph on the calculator draws a dashed line next to the dose ladder. People read it as "where I actually am." At a film half-life it hugs the steps. At 900 hours it should stay high and only slowly fall. This page is the function that draws that line, one day at a time.

It is a shape, not a blood test. The number is a dose-equivalent milligram: the steady daily dose that would sit at the same level. Absolute plasma units would invite reading it as one person's concentration, which this page cannot stand behind.

Every diagram below is live. Move the half-life, pick a drop or a jump, and the whole thing runs again.

Half-life
32h
Hours
What the dose does
Day to inspect
6
Start here

The words this page uses

One compartment, one dose a day, one number on the same milligram axis as the ladder. Every name in the listing is in the table.

NameMeansOn the graph
dosesOne milligram figure per day: what you actually take. The solid step line.teal steps
half_life_hHours for the level to fall by half if you took nothing more. The slider.n/a
ln_twoNatural log of 2, about 0.693. Turns a half-life into a decay constant.n/a
kThe decay constant per hour, ln2 divided by the half-life.n/a
decayThe fraction still on board after one day, e to the minus k times 24. Close to 1 when the half-life is long.n/a
to_dose1 minus decay. Turns a compartment level back into a steady daily dose.n/a
start_mgThe steady dose you were on before day 1. Day 0 of the dashed line.left end of the dash
levelThe compartment amount, just after today's dose. Not plotted; it is an internal unit.n/a
doseToday's take, one entry of doses.one step
dayHow many doses have been taken since day 0.x axis
effThe steady daily dose that would produce this level. The dashed line. Not a plasma concentration.the dash
outThe list of (day, eff, dose) points the graph is drawn from, including day 0.every vertex
d_startThe closed form's name for start_mg, the dose you were steady on.day 0
new_dThe closed form's name for a new constant dose after a single step.the new step
nHow many days you have been at that new constant dose.a day tick
The whole algorithm

All of it, in one place

This is the recurrence the calculator runs, with the comments written for someone meeting it for the first time. Everything after it on this page is these same steps, one at a time, with a picture for each. If you would rather see the pictures first, skip past it. Nothing below depends on having read it. Nothing is dosed off this page.

Lines
# ── One-compartment, once a day ─────────────────────────────────────────────
# The dashed line on the first graph is not plasma. It is the daily dose that
# would produce the same level, so it can be read against the ladder. Nothing
# is dosed off this number. The calculator's copy lives in index.html as
# lagFromDoses; this page carries a third copy, for the diagrams.
ln_two = 0.693147                         # natural log of two


def lag_from_doses(doses, half_life_h, start_mg):
    # doses         one milligram figure per day, the ladder you actually take
    # half_life_h   hours for the level to fall by half, with no new dose
    # start_mg      the steady dose you were on before day 1 of the taper

    k       = ln_two / half_life_h        # per hour
    decay   = exp(-k * 24)                # still on board after one day
    to_dose = 1 - decay                   # turns a level back into a dose

    # Day 0 is already steady on start_mg. Seeding at zero drew a loading
    # ramp through cycle 1 that nobody starting a taper experiences.
    out   = [(0, start_mg, start_mg)]     # day, eff, dose
    level = start_mg / to_dose
    day   = 0

    for dose in doses:
        level = level * decay + dose      # remains, plus today's take
        day  += 1
        eff   = level * to_dose           # the matching steady dose
        out.append((day, eff, dose))

    return out


# ── A single step, in closed form ───────────────────────────────────────────
# After n days at a new constant dose, having started at d_start, the loop
# above is just an exponential moving average, and it has a closed form:
#
#     eff(n) = new_d + (d_start - new_d) * decay ** n
#
# A drop (new_d < d_start) leaves the curve ABOVE the new dose.
# A jump (new_d > d_start) leaves the curve BELOW the new dose.
# A long half-life (decay close to 1) stays near d_start instead of hugging.
d_start = start_mg                        # where you were steady
new_d = doses[0]                          # the new constant dose
n     = 6                                 # days at that dose
# eff(n) = new_d + (d_start - new_d) * decay ** n


# ── Draw it ─────────────────────────────────────────────────────────────────
# One vertex per day. The solid line is dose; the dashed line is eff. They
# share an axis because of to_dose. Clip nothing: a long half-life is
# supposed to sit high.
for day, eff, dose in out:
    line_to(day, eff)                     # the dash
    step_to(day, dose)                    # the ladder
01 Decay

A half-life becomes a fraction per day

The only number the slider changes is half_life_h. From it the page computes two fractions: how much of yesterday is still here after 24 hours (decay), and the rest (to_dose), which is also the weight on today's dose.

At 32 h, a day knocks the level down to about 60% and today's dose supplies the other 40%. At 900 h a day knocks it down to about 98%, so today's intake is a 2% nudge. That is why 900 h stays up.

Remaining fraction of yesterday, after 1 day, 6 days and 30 days, at the half-life on the slider.

02 Seed

Day 0 is already at the old dose

Someone starting a taper is not starting the drug. The dashed line begins at start_mg, not at zero. Seeding at zero drew a loading ramp through cycle 1 that nobody in this situation experiences.

The internal level is larger than the milligram dose, because it is the peak amount that a daily dose of start_mg would pile up to. Multiplying by to_dose puts it back on the milligram axis, so day 0 reads as the dose you were already on.

The seed. eff on day 0 is exactly start_mg, by construction.

03 One day

Yesterday's remains, plus today's take

Each morning the compartment keeps decay of what it had, then today's dose is added. That is the whole pharmacokinetic model: one compartment, instantaneous intake, first-order loss, sampled once a day just after the dose.

Move Day to inspect to walk the arithmetic. The highlighted row is that day. The closed form of a single step has to match this loop; if it does not, the listing is teaching the wrong function.

First days of the series. eff is what gets plotted. The identity line is the closed form against this loop, on every day of a constant step.

04 The axis

Same milligrams as the ladder

eff = level * to_dose is only a unit change. It answers "what steady daily dose would sit here?" so the dashed line and the solid steps share an axis. It is deliberately not a plasma concentration. A shape whose size you cannot see against the ladder would be worse than no shape.

Solid = the dose you take. Dashed = the dose-equivalent level. The inspected day is the dot.

05 A drop, a jump

The closed form of a single step

After n days at a new constant new_d, having been steady at d_start:

eff(n) = new_d + (d_start - new_d) * decay ** n

A drop leaves the curve above the new dose. A jump leaves it below. Pick those two modes on the driver and the inequality cannot flip. A washout is a drop to zero: the curve is then a pure exponential, the "stay up and fall" picture at 900 h.

The same half-life, three paths: drop 8 to 4, jump 4 to 8, washout 8 to 0. The inspected day is marked on each.

06 Long versus short

900 h does not hug the ladder

A 32 h film half-life, in the usual 24-42 hour range, is short next to a 6-day cycle, so the dashed line has almost landed by the next drop. That hugging is the point of the graph on the calculator: you may not feel a drop on the day you make it, but you have almost landed by day 6.

A 900 h half-life is 37.5 days. After one 6-day cycle about 90% of the first drop is still in front of you, so the line stays up. The calculator used to cap the input at 80 h, which silently redrew 900 as 80, and 80 still hugs. The cap is 2160 h now, 90 days, enough to sketch a 60-day injection tail.

Two half-lives on the same dose path: 32 h in teal, the slider's value dashed. On a default 8 mg taper the 900 h line is the one that stays high.

07 The taper

The real ladder, not one step

The calculator does not hold a constant dose. Each cycle drops, then holds. The function is the same: feed it the daily milligrams, one per day. The closed form no longer applies once the dose keeps moving, but the inequalities still do. After a drop, eff is above today's dose. After a jump, below. The page checks both, live, on whatever path you picked.

The path selected on the driver, drawn the way the calculator draws it.