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.
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.
| Name | Means | On the graph |
|---|---|---|
| doses | One milligram figure per day: what you actually take. The solid step line. | teal steps |
| half_life_h | Hours for the level to fall by half if you took nothing more. The slider. | n/a |
| ln_two | Natural log of 2, about 0.693. Turns a half-life into a decay constant. | n/a |
| k | The decay constant per hour, ln2 divided by the half-life. | n/a |
| decay | The 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_dose | 1 minus decay. Turns a compartment level back into a steady daily dose. | n/a |
| start_mg | The steady dose you were on before day 1. Day 0 of the dashed line. | left end of the dash |
| level | The compartment amount, just after today's dose. Not plotted; it is an internal unit. | n/a |
| dose | Today's take, one entry of doses. | one step |
| day | How many doses have been taken since day 0. | x axis |
| eff | The steady daily dose that would produce this level. The dashed line. Not a plasma concentration. | the dash |
| out | The list of (day, eff, dose) points the graph is drawn from, including day 0. | every vertex |
| d_start | The closed form's name for start_mg, the dose you were steady on. | day 0 |
| new_d | The closed form's name for a new constant dose after a single step. | the new step |
| n | How many days you have been at that new constant dose. | a day tick |
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.
# ── 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
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.
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.
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.
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.
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.
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.
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.