TMDD Part 1b: Understanding TMDD Dynamics Through the Four Phases

Author

Vijay Ivaturi

1 Introduction

This tutorial builds intuition for Target-Mediated Drug Disposition (TMDD) through the elegant four-phase framework introduced by Peletier & Gabrielsson (2012). Rather than focusing on model fitting, we explore TMDD dynamics through simulation and visualization to develop a deep understanding of what drives the characteristic TMDD profile.

Learning Objectives:

By the end of this tutorial, you will be able to:

  • Recognize and interpret the four phases (A, B, C, D) of TMDD profiles
  • Understand how each phase relates to underlying biological processes
  • Predict how parameter changes affect the concentration-time profile
  • Identify which parameters can be estimated from each phase
  • Apply this framework to interpret real TMDD data
Attribution

This tutorial is based on the seminal work of Peletier & Gabrielsson (2012), which provides a comprehensive mathematical analysis of TMDD dynamics. We use their parameter sets and reproduce key figures with permission (CC BY license).

2 Libraries

using Pumas
using PumasUtilities
using AlgebraOfGraphics
using CairoMakie
using DataFrames
using Random

3 The TMDD Model

We use a one-compartment full TMDD model as the foundation for our exploration. The complete model equations are covered in Part 2 of this series; here we focus on the dynamics and interpretation.

3.1 Model Definition

tmdd_model = @model begin
    @metadata begin
        desc = "One-compartment Full TMDD Model (Peletier Parameters)"
        timeu = u"hr"
    end

    @param begin
        """
        Linear elimination rate constant (hr⁻¹)
        """
        tvKel  RealDomain(lower = 0)
        """
        Association rate constant (nM⁻¹hr⁻¹)
        """
        tvKon  RealDomain(lower = 0)
        """
        Dissociation rate constant (hr⁻¹)
        """
        tvKoff  RealDomain(lower = 0)
        """
        Receptor synthesis rate (nM/hr)
        """
        tvKsyn  RealDomain(lower = 0)
        """
        Receptor degradation rate (hr⁻¹)
        """
        tvKdeg  RealDomain(lower = 0)
        """
        Complex internalization rate (hr⁻¹)
        """
        tvKint  RealDomain(lower = 0)
    end

    @pre begin
        Kel = tvKel
        Kon = tvKon
        Koff = tvKoff
        Ksyn = tvKsyn
        Kdeg = tvKdeg
        Kint = tvKint
    end

    @init begin
        Receptor = Ksyn / Kdeg  # Baseline receptor level (R0)
    end

    @vars begin
        # Derived constants
        R0 := Ksyn / Kdeg
        KD := Koff / Kon
        KM := (Koff + Kint) / Kon
        Rstar := Ksyn / Kint  # Maximum receptor pool

        # Totals
        Ltot := Ligand + Complex
        Rtot := Receptor + Complex
    end

    @dynamics begin
        # Free ligand dynamics
        Ligand' = -Kel * Ligand - Kon * Ligand * Receptor + Koff * Complex

        # Free receptor dynamics
        Receptor' = Ksyn - Kdeg * Receptor - Kon * Ligand * Receptor + Koff * Complex

        # Ligand-receptor complex dynamics
        Complex' = Kon * Ligand * Receptor - Koff * Complex - Kint * Complex
    end

    @derived begin
        L = @. Ligand
        R = @. Receptor
        RL = @. Complex
        L_total = @. Ltot
        R_total = @. Rtot
    end
end
PumasModel
  Parameters: tvKel, tvKon, tvKoff, tvKsyn, tvKdeg, tvKint
  Random effects:
  Covariates:
  Dynamical system variables: Ligand, Receptor, Complex
  Dynamical system type: Nonlinear ODE
  Derived: L, R, RL, L_total, R_total
  Observed: L, R, RL, L_total, R_total

3.2 Parameters from Peletier & Gabrielsson (2012)

The original paper uses mass concentration units (mg/L). For consistency with other tutorials and typical mAb modeling, we convert to molar units (nM) assuming a molecular weight of 150 kDa.

Conversion factor: 1 mg/L ≈ 6.67 nM for a 150 kDa molecule.

# Peletier paper parameters (Table 3) converted to nM and hr units
# Original: ke(L) = 0.0015 h⁻¹, kon = 0.091 (mg/L)⁻¹h⁻¹, koff = 0.001 h⁻¹
#           kin = 0.11 mg/L/h, kout = 0.0089 h⁻¹, ke(RL) = 0.003 h⁻¹

peletier_params = (
    tvKel = 0.0015,         # Linear elimination rate (h⁻¹)
    tvKon = 0.0136,         # Association rate (nM⁻¹h⁻¹) - converted from 0.091 (mg/L)⁻¹h⁻¹
    tvKoff = 0.001,         # Dissociation rate (h⁻¹)
    tvKsyn = 0.73,          # Receptor synthesis (nM/h) - converted from 0.11 mg/L/h
    tvKdeg = 0.0089,        # Receptor degradation (h⁻¹)
    tvKint = 0.003,         # Internalization rate (h⁻¹)
)

# Calculate derived constants
R0 = peletier_params.tvKsyn / peletier_params.tvKdeg
KD = peletier_params.tvKoff / peletier_params.tvKon
KM = (peletier_params.tvKoff + peletier_params.tvKint) / peletier_params.tvKon
Rstar = peletier_params.tvKsyn / peletier_params.tvKint

println("Derived Constants:")
println("  R₀ (baseline receptor) = $(round(R0, digits=1)) nM")
println("  Kᴅ (dissociation constant) = $(round(KD, digits=3)) nM")
println("  Kᴍ (Michaelis constant) = $(round(KM, digits=3)) nM")
println("  R* (maximum receptor pool) = $(round(Rstar, digits=1)) nM")
Derived Constants:
  R₀ (baseline receptor) = 82.0 nM
  Kᴅ (dissociation constant) = 0.074 nM
  Kᴍ (Michaelis constant) = 0.294 nM
  R* (maximum receptor pool) = 243.3 nM

3.3 Dose Levels

Following the paper, we simulate four doses that span a wide concentration range:

# Doses matching paper (converted to nM concentrations)
# Original: 1.5, 5, 15, 45 mg/kg with Vc = 0.05 L/kg → L0 = 30, 100, 300, 900 mg/L
# Converted to nM: L0 = 200, 667, 2000, 6000 nM
initial_concs = [200.0, 667.0, 2000.0, 6000.0]  # nM
dose_labels = ["200 nM", "667 nM", "2000 nM", "6000 nM"]

println("Initial Concentrations (L₀):")
for (conc, label) in zip(initial_concs, dose_labels)
    ratio = conc / R0
    println("  $label = $(round(ratio, digits=1))× R₀")
end
Initial Concentrations (L₀):
  200 nM = 2.4× R₀
  667 nM = 8.1× R₀
  2000 nM = 24.4× R₀
  6000 nM = 73.2× R₀

4 Part I: Bolus Administration

4.1 The Four Phases of TMDD

After a bolus dose, the TMDD concentration-time profile can be divided into four distinct phases. Each phase is dominated by different processes and reveals information about specific parameters.

Show/Hide Code
# Create schematic figure with inset for Phase A
fig = Figure(size = (1000, 600))

# Main axis
ax = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Ligand Concentration (nM)",
    yscale = log10,
    title = "The Four Phases of TMDD",
)

# Representative profile (moderate dose to show all phases clearly)
pop_schematic = [Subject(id = 1, events = DosageRegimen(200.0, time = 0, cmt = 1))]
obstimes_schematic = [0.001; 0.01:0.01:0.99; 1:0.5:49.5; 50:5:195; 200:20:800]
sim_schematic =
    simobs(tmdd_model, pop_schematic, peletier_params, obstimes = obstimes_schematic)
df_schematic = DataFrame(sim_schematic)

lines!(ax, df_schematic.time, max.(df_schematic.L, 1e-4), linewidth = 3, color = :steelblue)

# Phase boundaries (approximate for 200 nM dose)
vlines!(ax, [1], color = :gray, linestyle = :dash, alpha = 0.6)
vlines!(ax, [50], color = :gray, linestyle = :dash, alpha = 0.6)
vlines!(ax, [200], color = :gray, linestyle = :dash, alpha = 0.6)

# Phase labels - positioned in the middle of each phase region
text!(ax, 0.3, 40, text = "A", fontsize = 22, font = :bold, color = :darkred)
text!(ax, 15, 40, text = "B", fontsize = 22, font = :bold, color = :darkgreen)
text!(ax, 100, 40, text = "C", fontsize = 22, font = :bold, color = :darkorange)
text!(ax, 500, 40, text = "D", fontsize = 22, font = :bold, color = :darkblue)

# Reference lines
hlines!(ax, [R0], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax, 750, R0 * 1.5, text = "R₀", fontsize = 11, color = :gray)

hlines!(ax, [KD], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax, 750, KD * 0.5, text = "Kᴅ", fontsize = 11, color = :gray)

# Inset for Phase A close-up
ax_inset = Axis(
    fig[1, 1],
    width = Relative(0.35),
    height = Relative(0.35),
    halign = 0.95,
    valign = 0.95,
    xlabel = "Time (hr)",
    ylabel = "L (nM)",
    title = "Phase A Close-up",
    titlesize = 12,
    xlabelsize = 10,
    ylabelsize = 10,
    xticklabelsize = 9,
    yticklabelsize = 9,
    limits = (0, 2, 150, 220),
)

# Filter data for early timepoints
df_early = filter(row -> row.time <= 2, df_schematic)
lines!(ax_inset, df_early.time, df_early.L, linewidth = 2, color = :steelblue)

# Mark the rapid decline
scatter!(ax_inset, [0.001], [200.0], markersize = 8, color = :red)
text!(ax_inset, 0.15, 210, text = "L₀", fontsize = 10, color = :red)

# Add box around inset region in main plot
# (visual indicator that this is zoomed)
vspan!(ax, 0, 2, color = (:lightblue, 0.15))

# Legend at bottom showing phase descriptions
leg_elements = [
    LineElement(color = :darkred, linewidth = 3),
    LineElement(color = :darkgreen, linewidth = 3),
    LineElement(color = :darkorange, linewidth = 3),
    LineElement(color = :darkblue, linewidth = 3),
]
leg_labels = [
    "A: Rapid Binding (seconds-minutes)",
    "B: Target Saturated (hours-days)",
    "C: Transition (days)",
    "D: Terminal (days-weeks)",
]

Legend(
    fig[2, 1],
    leg_elements,
    leg_labels,
    orientation = :horizontal,
    tellheight = true,
    tellwidth = false,
    framevisible = false,
    labelsize = 11,
)

rowsize!(fig.layout, 2, Auto())

fig

Schematic illustration of the four phases of TMDD following bolus administration. Main panel shows the complete profile; inset zooms into Phase A (rapid binding) which occurs in the first hour.

4.2 Phase A: Rapid Binding (“The Lightning Marriage”)

Immediately after dosing, free ligand rapidly binds to available receptor.

What happens:

  • Drug meets target at very high rate
  • Complex forms nearly instantaneously
  • Free receptor drops from \(R_0\) to near zero
  • Free ligand drops by approximately \(R_0\)

Duration: \(\tau_A \sim \frac{1}{k_{on}(L_0 - R_0)}\)

Observable: Sharp initial concentration drop

Parameters identified: \(k_{on}\), \(R_0\)

Show/Hide Code
# Close-up of Phase A
obstimes_phaseA = 0.001:0.005:2.0
pop_phaseA = [
    Subject(id = i, events = DosageRegimen(conc, time = 0, cmt = 1)) for
    (i, conc) in enumerate(initial_concs)
]

sim_phaseA = simobs(tmdd_model, pop_phaseA, peletier_params, obstimes = obstimes_phaseA)
df_phaseA = DataFrame(sim_phaseA)
dose_label_df = DataFrame(id = string.(1:4), Dose = dose_labels)
df_phaseA = innerjoin(df_phaseA, dose_label_df, on = :id)

fig = Figure(size = (900, 400))

# Ligand concentration
ax1 = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Phase A: Ligand Dynamics",
    yscale = log10,
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_phaseA)
    lines!(
        ax1,
        df_dose.time,
        max.(df_dose.L, 0.01),
        linewidth = 2,
        color = color,
        label = dose,
    )
end

hlines!(ax1, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax1, 1.8, R0 * 1.3, text = "R₀", fontsize = 10, color = :gray)

# Receptor concentration
ax2 = Axis(
    fig[1, 2],
    xlabel = "Time (hr)",
    ylabel = "Free Receptor (nM)",
    title = "Phase A: Receptor Dynamics",
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_phaseA)
    lines!(ax2, df_dose.time, df_dose.R, linewidth = 2, color = color, label = dose)
end

hlines!(ax2, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax2, 1.8, R0 * 0.9, text = "R₀", fontsize = 10, color = :gray)

Legend(fig[1, 3], ax1, "L₀", framevisible = false)
fig

Phase A: Rapid binding phase. Close-up of the first few minutes after dosing showing the quick approach to quasi-equilibrium.
Key Insight

At the end of Phase A, the system reaches quasi-equilibrium:

  • \(\bar{L} \approx L_0 - R_0\) (if \(L_0 > R_0\))
  • \(\bar{R} \approx 0\) (receptor nearly fully occupied)
  • \(\bar{RL} \approx R_0\) (complex equals original receptor)

This is why Phase A duration depends on \(k_{on}(L_0 - R_0)\).

4.3 Phase B: Target Saturated (“The Slow Burn”)

Once the target is saturated, the drug elimination becomes linear.

What happens:

  • Target fully occupied (\(RL \approx R_{tot}\))
  • Linear elimination dominates
  • Complex slowly eliminated via internalization
  • New receptor synthesized is immediately captured

Observable: Parallel lines on semi-log plot (dose-independent slope)

Slope: \(\lambda_B \approx k_{el}\) (linear elimination rate)

Parameters identified: \(k_{el}\), \(k_{syn}\) (through receptor dynamics)

Show/Hide Code
# Phase B visualization
obstimes_phaseB = 0.1:1:300
sim_phaseB = simobs(tmdd_model, pop_phaseA, peletier_params, obstimes = obstimes_phaseB)
df_phaseB = DataFrame(sim_phaseB)
df_phaseB = innerjoin(df_phaseB, dose_label_df, on = :id)

fig = Figure(size = (700, 500))
ax = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Phase B: Target-Saturated Elimination",
    yscale = log10,
    limits = (0, 300, 1, 10000),
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_phaseB)
    lines!(
        ax,
        df_dose.time,
        max.(df_dose.L, 0.01),
        linewidth = 2,
        color = color,
        label = dose,
    )
end

# Add reference line for expected slope
t_ref = [50, 200]
L_ref = initial_concs[4] * 0.3 .* exp.(-peletier_params.tvKel .* (t_ref .- 50))
lines!(
    ax,
    t_ref,
    L_ref,
    linewidth = 2,
    linestyle = :dash,
    color = :black,
    label = "slope = kel",
)

# Reference lines
hlines!(ax, [R0], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax, 280, R0 * 1.3, text = "R₀", fontsize = 10, color = :gray)

Legend(fig[1, 2], ax, framevisible = false)
fig

Phase B: Target-saturated phase. The parallel decline indicates dose-independent (linear) elimination kinetics.

4.4 Phase C: Transition (“The Turning Point”)

As ligand concentration decreases and approaches \(K_D\), the system transitions from saturated to unsaturated.

What happens:

  • Target begins to recover from suppression
  • Target-mediated clearance increases (mixed-order kinetics)
  • Concentration drops through \(K_D\) range
  • Both elimination pathways are active

Observable: Increased decline rate, inflection in profile

Concentration range: \(0.1 K_D < L < 10 K_D\)

Parameters identified: \(K_D\), \(k_{off}\)

Show/Hide Code
# Extended simulation to show Phase C
obstimes_phaseC = [0.1:1:100; 110:10:500; 550:50:1500]
sim_phaseC = simobs(tmdd_model, pop_phaseA, peletier_params, obstimes = obstimes_phaseC)
df_phaseC = DataFrame(sim_phaseC)
df_phaseC = innerjoin(df_phaseC, dose_label_df, on = :id)

fig = Figure(size = (900, 400))

# Ligand
ax1 = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Ligand Through Phase C",
    yscale = log10,
    limits = (0, 1500, 0.001, 10000),
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_phaseC)
    lines!(
        ax1,
        df_dose.time,
        max.(df_dose.L, 1e-4),
        linewidth = 2,
        color = color,
        label = dose,
    )
end

hlines!(ax1, [KD], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax1, 1400, KD * 2, text = "Kᴅ", fontsize = 10, color = :gray)

hlines!(ax1, [10 * KD], color = :gray, linestyle = :dot, alpha = 0.4)
hlines!(ax1, [0.1 * KD], color = :gray, linestyle = :dot, alpha = 0.4)
text!(ax1, 1400, 10 * KD * 1.5, text = "10×Kᴅ", fontsize = 9, color = :gray)
text!(ax1, 1400, 0.1 * KD * 0.5, text = "0.1×Kᴅ", fontsize = 9, color = :gray)

# Receptor recovery
ax2 = Axis(
    fig[1, 2],
    xlabel = "Time (hr)",
    ylabel = "Free Receptor (nM)",
    title = "Receptor Recovery in Phase C",
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_phaseC)
    lines!(ax2, df_dose.time, df_dose.R, linewidth = 2, color = color, label = dose)
end

hlines!(ax2, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax2, 1400, R0 * 0.9, text = "R₀", fontsize = 10, color = :gray)

Legend(fig[1, 3], ax1, "L₀", framevisible = false)
fig

Phase C: Transition phase. The ligand concentration passes through the KD range where target-mediated clearance increases.

4.5 Phase D: Terminal (“The Long Goodbye”)

At low ligand concentrations, the terminal phase is reached.

What happens:

  • Ligand concentration well below \(K_D\)
  • System returns toward baseline
  • Terminal elimination dominated by slowest process
  • Often internalization-limited

Observable: Linear terminal slope on semi-log plot

Slope: \(\lambda_D \approx k_{int}\) (internalization rate)

Parameters identified: \(k_{int}\), \(K_M\)

Show/Hide Code
# Full simulation including terminal phase
obstimes_full = [0.1:1:100; 110:10:500; 550:50:2500]
sim_full = simobs(tmdd_model, pop_phaseA, peletier_params, obstimes = obstimes_full)
df_full = DataFrame(sim_full)
df_full = innerjoin(df_full, dose_label_df, on = :id)

fig = Figure(size = (700, 500))
ax = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Phase D: Terminal Elimination",
    yscale = log10,
    limits = (0, 2500, 1e-4, 10000),
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_full)
    lines!(
        ax,
        df_dose.time,
        max.(df_dose.L, 1e-5),
        linewidth = 2,
        color = color,
        label = dose,
    )
end

# Reference lines
hlines!(ax, [R0], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax, 2400, R0 * 1.5, text = "R₀", fontsize = 10, color = :gray)

hlines!(ax, [KD], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax, 2400, KD * 0.5, text = "Kᴅ", fontsize = 10, color = :gray)

# Add terminal slope reference (kint)
t_term = [1500, 2400]
L_term = 0.5 * exp.(-peletier_params.tvKint .* (t_term .- 1500))
lines!(
    ax,
    t_term,
    L_term,
    linewidth = 2,
    linestyle = :dash,
    color = :black,
    label = "slope = kint",
)

Legend(fig[1, 2], ax, framevisible = false)
fig

Phase D: Terminal phase. The terminal slope is determined by the internalization rate kint, not the linear elimination rate kel.
Key Insight from Peletier

The terminal slope in TMDD is typically determined by the internalization rate (\(k_{int}\)), not the linear elimination rate (\(k_{el}\)). This is a critical distinction from the Michaelis-Menten approximation, which predicts a different terminal slope.

4.6 Multi-Dose Visualization

Let’s reproduce the key figure from Peletier & Gabrielsson (2012) showing all four doses together:

Show/Hide Code
fig = Figure(size = (1100, 400))

# Left: Full semi-log view
ax1 = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Semi-log Scale",
    yscale = log10,
    limits = (0, 2500, 1e-4, 10000),
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_full)
    lines!(
        ax1,
        df_dose.time,
        max.(df_dose.L, 1e-5),
        linewidth = 2,
        color = color,
        label = dose,
    )
end

hlines!(ax1, [R0], color = :gray, linestyle = :dot, alpha = 0.5, label = "R₀")
hlines!(ax1, [KD], color = :gray, linestyle = :dot, alpha = 0.5, label = "Kᴅ")

# Middle: Linear scale view (early time)
df_linear = filter(row -> row.time <= 600, df_full)

ax2 = Axis(
    fig[1, 2],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Linear Scale",
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_linear)
    lines!(ax2, df_dose.time, df_dose.L, linewidth = 2, color = color, label = dose)
end

# Right: Close-up of Phase A
ax3 = Axis(
    fig[1, 3],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Phase A Close-up",
    limits = (0, 2, nothing, nothing),
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_phaseA)
    lines!(ax3, df_dose.time, df_dose.L, linewidth = 2, color = color, label = dose)
end

hlines!(ax3, [R0], color = :gray, linestyle = :dot, alpha = 0.5)

Legend(fig[1, 4], ax1, "L₀", framevisible = false)
fig

Complete TMDD profiles across four doses, reproducing Figure 5 from Peletier & Gabrielsson (2012). Left: Full semi-log view. Middle: Linear scale view. Right: Close-up of Phase A.

4.7 Receptor Dynamics: The Target’s Story

The receptor dynamics reveal crucial information about target engagement:

Show/Hide Code
fig = Figure(size = (1100, 400))

# Left: Free receptor
ax1 = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Receptor (nM)",
    title = "Free Receptor (R)",
    limits = (0, 2500, nothing, nothing),
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_full)
    lines!(ax1, df_dose.time, df_dose.R, linewidth = 2, color = color, label = dose)
end

hlines!(ax1, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax1, 2300, R0 * 1.05, text = "R₀", fontsize = 10, color = :gray)

# Middle: Complex
ax2 = Axis(fig[1, 2], xlabel = "Time (hr)", ylabel = "Complex (nM)", title = "Complex (RL)")

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_full)
    lines!(ax2, df_dose.time, df_dose.RL, linewidth = 2, color = color, label = dose)
end

hlines!(ax2, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax2, 2300, R0 * 1.05, text = "R₀", fontsize = 10, color = :gray)

# Right: Total receptor
ax3 = Axis(
    fig[1, 3],
    xlabel = "Time (hr)",
    ylabel = "Total Receptor (nM)",
    title = "Total Receptor (Rtot = R + RL)",
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_full)
    lines!(ax3, df_dose.time, df_dose.R_total, linewidth = 2, color = color, label = dose)
end

hlines!(ax3, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax3, 2300, R0 * 1.05, text = "R₀", fontsize = 10, color = :gray)

hlines!(ax3, [Rstar], color = :gray, linestyle = :dot, alpha = 0.6)
text!(ax3, 2300, Rstar * 0.95, text = "R*", fontsize = 10, color = :gray)

Legend(fig[1, 4], ax1, "L₀", framevisible = false)
fig

Receptor dynamics during TMDD, reproducing Figure 6 from Peletier & Gabrielsson (2012). Left: Free receptor showing suppression and recovery. Middle: Complex formation and elimination. Right: Total receptor pool behavior.
The Γ Curve and R*

The total receptor \(R_{tot}\) follows a characteristic “Γ curve”:

  1. Initially jumps to \(R_0\) (all bound as complex)
  2. Rises toward \(R^* = k_{syn}/k_{int}\) while ligand is present
  3. Returns to \(R_0\) after washout

The maximum receptor pool \(R^*\) represents the balance between synthesis and internalization, which exceeds \(R_0\) when \(k_{int} < k_{deg}\) (as is often the case for mAbs).

4.8 Log-Scale Receptor Dynamics

The receptor dynamics on log scale reveal bi-exponential behavior:

Show/Hide Code
fig = Figure(size = (900, 400))

# Free receptor on log scale
ax1 = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Receptor (nM)",
    title = "Free Receptor (log scale)",
    yscale = log10,
    limits = (0, 2500, 1e-3, 200),
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_full)
    lines!(
        ax1,
        df_dose.time,
        max.(df_dose.R, 1e-4),
        linewidth = 2,
        color = color,
        label = dose,
    )
end

hlines!(ax1, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax1, 2300, R0 * 1.3, text = "R₀", fontsize = 10, color = :gray)

# Total receptor on log scale
ax2 = Axis(
    fig[1, 2],
    xlabel = "Time (hr)",
    ylabel = "Total Receptor (nM)",
    title = "Total Receptor (log scale)",
    yscale = log10,
    limits = (0, 2500, 10, 500),
)

for (i, (dose, color)) in enumerate(zip(dose_labels, [:red, :blue, :green, :purple]))
    df_dose = filter(row -> row.Dose == dose, df_full)
    lines!(ax2, df_dose.time, df_dose.R_total, linewidth = 2, color = color, label = dose)
end

hlines!(ax2, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax2, 2300, R0 * 1.2, text = "R₀", fontsize = 10, color = :gray)

hlines!(ax2, [Rstar], color = :gray, linestyle = :dot, alpha = 0.6)
text!(ax2, 2300, Rstar * 0.9, text = "R*", fontsize = 10, color = :gray)

Legend(fig[1, 3], ax1, "L₀", framevisible = false)
fig

Receptor dynamics on log scale, reproducing Figure 7 from Peletier & Gabrielsson (2012). The bi-exponential behavior of R and Rtot is clearly visible.

4.9 High Dose vs Low Dose: When Phases Disappear

The characteristic four-phase profile requires \(L_0 > R_0\). At low doses, some phases may be absent or difficult to observe:

Show/Hide Code
# Extended dose range including sub-R0 doses
extended_concs = [10.0, 40.0, 82.0, 200.0, 667.0, 2000.0, 6000.0, 12000.0]  # nM
extended_labels =
    ["10 nM", "40 nM", "82 nM", "200 nM", "667 nM", "2000 nM", "6000 nM", "12000 nM"]

pop_extended = [
    Subject(id = i, events = DosageRegimen(conc, time = 0, cmt = 1)) for
    (i, conc) in enumerate(extended_concs)
]

sim_extended = simobs(tmdd_model, pop_extended, peletier_params, obstimes = obstimes_full)
df_extended = DataFrame(sim_extended)
extended_label_df = DataFrame(id = string.(1:8), Dose = extended_labels)
df_extended = innerjoin(df_extended, extended_label_df, on = :id)

fig = Figure(size = (800, 500))
ax = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Dose-Dependent TMDD Profiles (8 doses)",
    yscale = log10,
    limits = (0, 2500, 1e-4, 20000),
)

colors = cgrad(:viridis, 8, categorical = true)
for (i, dose) in enumerate(extended_labels)
    df_dose = filter(row -> row.Dose == dose, df_extended)
    lines!(
        ax,
        df_dose.time,
        max.(df_dose.L, 1e-5),
        linewidth = 2,
        color = colors[i],
        label = dose,
    )
end

hlines!(ax, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax, 2300, R0 * 1.5, text = "R₀", fontsize = 10, color = :gray)

hlines!(ax, [KD], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax, 2300, KD * 0.5, text = "Kᴅ", fontsize = 10, color = :gray)

Legend(fig[1, 2], ax, "L₀", framevisible = false)
fig

High dose vs low dose comparison, reproducing Figure 8 from Peletier & Gabrielsson (2012). Low doses (L₀ < R₀) show simplified kinetics while high doses show all four phases.
Why the Signature Shape Requires L₀ > R₀
  • Low doses (\(L_0 < R_0\)): Most ligand immediately bound; appears bi-exponential
  • Near R₀ (\(L_0 \approx R_0\)): Brief Phase B, rapid transition
  • High doses (\(L_0 >> R_0\)): Extended Phase B, clear four-phase structure

For clinical dose selection, this framework helps predict which profiles will show TMDD signatures.

4.10 Parameter Identification from the Profile

Each phase provides information about specific TMDD parameters:

Phase Observable Feature Parameters Identified
A Duration of rapid decline \(k_{on}\), \(R_0\)
B Slope during saturation \(k_{el}\) (linear clearance)
C Transition point, curvature \(K_D\), \(k_{off}\)
D Terminal slope \(k_{int}\), \(K_M\)
Show/Hide Code
fig = Figure(size = (900, 550))

df_single = filter(row -> row.Dose == "2000 nM", df_full)

ax = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Parameter Identification from TMDD Profile",
    yscale = log10,
    limits = (0, 2500, 1e-4, 5000),
)

lines!(ax, df_single.time, max.(df_single.L, 1e-5), linewidth = 3, color = :steelblue)

# Phase A annotation
bracket!(
    ax,
    Point2f(0, log10(1800)),
    Point2f(0.5, log10(1800)),
    orientation = :down,
    width = 20,
    color = :darkred,
)
text!(
    ax,
    0.25,
    1200,
    text = "kon, R₀",
    fontsize = 11,
    color = :darkred,
    align = (:center, :top),
)

# Phase B annotation - slope line
t_B = [10, 200]
L_B = 1500 * exp.(-peletier_params.tvKel .* (t_B .- 10))
lines!(ax, t_B, L_B, linewidth = 2, linestyle = :dash, color = :darkgreen)
text!(
    ax,
    80,
    800,
    text = "slope = kel",
    fontsize = 11,
    color = :darkgreen,
    rotation = -0.15,
)

# Phase C annotation - KD reference
vspan!(ax, 300, 700, color = (:darkorange, 0.1))
text!(
    ax,
    500,
    100,
    text = "KD, koff\nregion",
    fontsize = 11,
    color = :darkorange,
    align = (:center, :center),
)

# Phase D annotation - terminal slope
t_D = [1200, 2400]
L_D = 0.3 * exp.(-peletier_params.tvKint .* (t_D .- 1200))
lines!(ax, t_D, L_D, linewidth = 2, linestyle = :dash, color = :darkblue)
text!(
    ax,
    1800,
    0.15,
    text = "slope = kint",
    fontsize = 11,
    color = :darkblue,
    rotation = -0.05,
)

# Reference lines
hlines!(ax, [R0], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax, 2400, R0 * 1.5, text = "R₀", fontsize = 10, color = :gray)

hlines!(ax, [KD], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax, 2400, KD * 0.5, text = "Kᴅ", fontsize = 10, color = :gray)

fig

Annotated profile showing what each phase reveals about TMDD parameters, based on Figure 16 from Peletier & Gabrielsson (2012).

5 Part II: Constant-Rate Infusion

Constant-rate infusion provides additional insights into TMDD dynamics, particularly steady-state behavior and washout kinetics.

5.1 Steady-State Analysis

At steady state during infusion, all time derivatives equal zero. The steady-state concentrations depend on the infusion rate \(I\) (nM/hr):

Show/Hide Code
# Model with infusion support
tmdd_infusion = @model begin
    @param begin
        tvKel  RealDomain(lower = 0)
        tvKon  RealDomain(lower = 0)
        tvKoff  RealDomain(lower = 0)
        tvKsyn  RealDomain(lower = 0)
        tvKdeg  RealDomain(lower = 0)
        tvKint  RealDomain(lower = 0)
    end

    @pre begin
        Kel = tvKel
        Kon = tvKon
        Koff = tvKoff
        Ksyn = tvKsyn
        Kdeg = tvKdeg
        Kint = tvKint
    end

    @init begin
        Receptor = Ksyn / Kdeg
    end

    @dynamics begin
        Ligand' = -Kel * Ligand - Kon * Ligand * Receptor + Koff * Complex
        Receptor' = Ksyn - Kdeg * Receptor - Kon * Ligand * Receptor + Koff * Complex
        Complex' = Kon * Ligand * Receptor - Koff * Complex - Kint * Complex
    end

    @derived begin
        L = @. Ligand
        R = @. Receptor
        RL = @. Complex
    end
end

# Simulate various infusion rates to steady state
infusion_rates = 10.0 .^ range(-2, 2, length = 30)  # nM/hr
steady_state_L = Float64[]
steady_state_R = Float64[]

for rate in infusion_rates
    # Long infusion to reach steady state
    pop_inf = [
        Subject(
            id = 1,
            events = DosageRegimen(rate * 5000, time = 0, duration = 5000, cmt = 1),
        ),
    ]
    sim_inf = simobs(tmdd_infusion, pop_inf, peletier_params, obstimes = [4900])
    push!(steady_state_L, sim_inf[1].observations.L[1])
    push!(steady_state_R, sim_inf[1].observations.R[1])
end

fig = Figure(size = (800, 400))

ax1 = Axis(
    fig[1, 1],
    xlabel = "Infusion Rate (nM/hr)",
    ylabel = "Steady-State Concentration (nM)",
    title = "Steady-State vs Infusion Rate",
    xscale = log10,
    yscale = log10,
)

lines!(ax1, infusion_rates, steady_state_L, linewidth = 2, color = :blue, label = "Lss")
lines!(ax1, infusion_rates, steady_state_R, linewidth = 2, color = :red, label = "Rss")

hlines!(ax1, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax1, 0.02, R0 * 0.7, text = "R₀", fontsize = 10, color = :gray)

hlines!(ax1, [KD], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax1, 0.02, KD * 0.5, text = "Kᴅ", fontsize = 10, color = :gray)

Legend(fig[1, 2], ax1, framevisible = false)
fig

Steady-state ligand concentration vs infusion rate, reproducing Figure 12 from Peletier & Gabrielsson (2012).
Steady-State Interpretation
  • At low infusion rates: \(L_{ss} \approx 0\), \(R_{ss} \approx R_0\) (target not suppressed)
  • At high infusion rates: \(L_{ss}\) increases linearly, \(R_{ss} \rightarrow 0\) (target suppressed)
  • The transition occurs around the infusion rate that produces \(L_{ss} \approx K_D\)

5.2 Build-up Dynamics

The approach to steady state during infusion shows characteristic TMDD behavior:

Show/Hide Code
# Infusion build-up at different rates
infusion_rates_buildup = [0.1, 0.5, 2.0, 10.0]  # nM/hr
infusion_labels = ["0.1 nM/hr", "0.5 nM/hr", "2.0 nM/hr", "10.0 nM/hr"]

obstimes_inf = 0:10:3000

fig = Figure(size = (900, 400))

ax1 = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Ligand Build-up During Infusion",
    yscale = log10,
    limits = (0, 3000, 0.001, 1000),
)

ax2 = Axis(
    fig[1, 2],
    xlabel = "Time (hr)",
    ylabel = "Free Receptor (nM)",
    title = "Receptor Suppression During Infusion",
)

colors = [:red, :blue, :green, :purple]

for (i, (rate, label, color)) in
    enumerate(zip(infusion_rates_buildup, infusion_labels, colors))
    pop_inf = [
        Subject(
            id = 1,
            events = DosageRegimen(rate * 3000, time = 0, duration = 3000, cmt = 1),
        ),
    ]
    sim_inf = simobs(tmdd_infusion, pop_inf, peletier_params, obstimes = obstimes_inf)
    df_inf = DataFrame(sim_inf)

    lines!(
        ax1,
        df_inf.time,
        max.(df_inf.L, 1e-4),
        linewidth = 2,
        color = color,
        label = label,
    )
    lines!(ax2, df_inf.time, df_inf.R, linewidth = 2, color = color, label = label)
end

hlines!(ax1, [KD], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax1, 2800, KD * 0.5, text = "Kᴅ", fontsize = 10, color = :gray)

hlines!(ax2, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax2, 2800, R0 * 0.95, text = "R₀", fontsize = 10, color = :gray)

Legend(fig[1, 3], ax1, "Rate", framevisible = false)
fig

Build-up to steady state during constant-rate infusion, reproducing Figure 13 from Peletier & Gabrielsson (2012).

5.3 Washout Dynamics

After stopping infusion, the washout dynamics resemble post-bolus behavior:

Show/Hide Code
# Infusion followed by washout
rate = 5.0  # nM/hr
infusion_duration = 1000  # hr

pop_washout = [
    Subject(
        id = 1,
        events = DosageRegimen(
            rate * infusion_duration,
            time = 0,
            duration = infusion_duration,
            cmt = 1,
        ),
    ),
]

obstimes_washout = [0:10:1000; 1010:10:2000; 2050:50:4000]
sim_washout =
    simobs(tmdd_infusion, pop_washout, peletier_params, obstimes = obstimes_washout)
df_washout = DataFrame(sim_washout)

fig = Figure(size = (900, 400))

ax1 = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Ligand: Infusion and Washout",
    yscale = log10,
    limits = (0, 4000, 0.0001, 100),
)

lines!(ax1, df_washout.time, max.(df_washout.L, 1e-5), linewidth = 2, color = :steelblue)
vlines!(ax1, [infusion_duration], color = :gray, linestyle = :dash, alpha = 0.6)
text!(
    ax1,
    infusion_duration + 50,
    30,
    text = "Stop\ninfusion",
    fontsize = 10,
    color = :gray,
)

hlines!(ax1, [KD], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax1, 3800, KD * 0.5, text = "Kᴅ", fontsize = 10, color = :gray)

ax2 = Axis(
    fig[1, 2],
    xlabel = "Time (hr)",
    ylabel = "Free Receptor (nM)",
    title = "Receptor: Suppression and Recovery",
)

lines!(ax2, df_washout.time, df_washout.R, linewidth = 2, color = :firebrick)
vlines!(ax2, [infusion_duration], color = :gray, linestyle = :dash, alpha = 0.6)

hlines!(ax2, [R0], color = :gray, linestyle = :dash, alpha = 0.6)
text!(ax2, 3800, R0 * 0.95, text = "R₀", fontsize = 10, color = :gray)

fig

Washout dynamics after stopping constant-rate infusion, reproducing Figure 15 from Peletier & Gabrielsson (2012). Phases B-D are visible after washout.

6 Part III: Comparison with Michaelis-Menten Approximation

The Michaelis-Menten (MM) quasi-steady-state approximation is commonly used to simplify TMDD models. Let’s compare it with the full model.

6.1 Michaelis-Menten Model

# MM approximation model
mm_model = @model begin
    @param begin
        tvKel  RealDomain(lower = 0)
        tvVmax  RealDomain(lower = 0)  # Maximum elimination rate
        tvKM  RealDomain(lower = 0)    # Michaelis constant
    end

    @pre begin
        Kel = tvKel
        Vmax = tvVmax
        KM = tvKM
    end

    @dynamics begin
        Ligand' = -Kel * Ligand - Vmax * Ligand / (KM + Ligand)
    end

    @derived begin
        L = @. Ligand
    end
end

# Convert full TMDD parameters to MM equivalent
# Vmax = kint * Rtot ≈ kint * R0 (assuming Rtot ≈ R0 at high L)
# KM = (koff + kint) / kon
Vmax_equiv = peletier_params.tvKint * R0
KM_equiv = KM

mm_params = (tvKel = peletier_params.tvKel, tvVmax = Vmax_equiv, tvKM = KM_equiv)

println("MM Approximation Parameters:")
println("  Vmax = $(round(Vmax_equiv, digits=3)) nM/hr")
println("  KM = $(round(KM_equiv, digits=3)) nM")
MM Approximation Parameters:
  Vmax = 0.246 nM/hr
  KM = 0.294 nM

6.2 Full Model vs MM Approximation

Show/Hide Code
# Simulate both models at same dose
dose_compare = 2000.0  # nM

pop_compare = [Subject(id = 1, events = DosageRegimen(dose_compare, time = 0, cmt = 1))]

sim_full_compare =
    simobs(tmdd_model, pop_compare, peletier_params, obstimes = obstimes_full)
sim_mm = simobs(mm_model, pop_compare, mm_params, obstimes = obstimes_full)

df_full_compare = DataFrame(sim_full_compare)
df_mm = DataFrame(sim_mm)

fig = Figure(size = (900, 500))

# Full time course
ax1 = Axis(
    fig[1, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Full Model vs MM Approximation",
    yscale = log10,
    limits = (0, 2500, 1e-4, 5000),
)

lines!(
    ax1,
    df_full_compare.time,
    max.(df_full_compare.L, 1e-5),
    linewidth = 3,
    color = :steelblue,
    label = "Full TMDD",
)
lines!(
    ax1,
    df_mm.time,
    max.(df_mm.L, 1e-5),
    linewidth = 2,
    linestyle = :dash,
    color = :red,
    label = "MM Approx",
)

hlines!(ax1, [KD], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax1, 2400, KD * 0.5, text = "Kᴅ", fontsize = 10, color = :gray)

hlines!(ax1, [KM], color = :gray, linestyle = :dot, alpha = 0.5)
text!(ax1, 2400, KM * 2, text = "Kᴍ", fontsize = 10, color = :gray)

Legend(fig[1, 2], ax1, framevisible = false)

# Early time close-up (Phase A)
ax2 = Axis(
    fig[2, 1],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Phase A: MM Misses Rapid Binding",
    limits = (0, 5, 1000, 2200),
)

df_full_early = filter(row -> row.time <= 5, df_full_compare)
df_mm_early = filter(row -> row.time <= 5, df_mm)

lines!(
    ax2,
    df_full_early.time,
    df_full_early.L,
    linewidth = 3,
    color = :steelblue,
    label = "Full TMDD",
)
lines!(
    ax2,
    df_mm_early.time,
    df_mm_early.L,
    linewidth = 2,
    linestyle = :dash,
    color = :red,
    label = "MM Approx",
)

# Terminal phase close-up
ax3 = Axis(
    fig[2, 2],
    xlabel = "Time (hr)",
    ylabel = "Free Ligand (nM)",
    title = "Phase D: Different Terminal Slopes",
    yscale = log10,
    limits = (1000, 2500, 1e-4, 10),
)

df_full_late = filter(row -> row.time >= 1000, df_full_compare)
df_mm_late = filter(row -> row.time >= 1000, df_mm)

lines!(
    ax3,
    df_full_late.time,
    max.(df_full_late.L, 1e-5),
    linewidth = 3,
    color = :steelblue,
    label = "Full TMDD",
)
lines!(
    ax3,
    df_mm_late.time,
    max.(df_mm_late.L, 1e-5),
    linewidth = 2,
    linestyle = :dash,
    color = :red,
    label = "MM Approx",
)

# Add slope reference lines
t_term = [1500, 2400]
L_full_term = 0.3 * exp.(-peletier_params.tvKint .* (t_term .- 1500))
L_mm_term = 0.3 * exp.(-(peletier_params.tvKel + Vmax_equiv / KM_equiv) .* (t_term .- 1500))

lines!(ax3, t_term, L_full_term, linewidth = 1.5, linestyle = :dot, color = :steelblue)
lines!(ax3, t_term, max.(L_mm_term, 1e-5), linewidth = 1.5, linestyle = :dot, color = :red)

fig

Comparison of full TMDD model with Michaelis-Menten approximation. The MM model captures Phases B and C well but differs in Phase A (lacks rapid binding) and Phase D (different terminal slope).

6.3 When MM Works (and When It Doesn’t)

Aspect Full TMDD MM Approximation
Phase A Captures rapid binding Cannot represent
Phase B ✓ Similar ✓ Similar
Phase C ✓ Similar ✓ Similar (if \(K_M \approx K_D\))
Phase D Slope \(\approx k_{int}\) Slope \(\approx k_{el} + V_{max}/K_M\)
Terminal t½ Determined by slowest process Often overestimated
Practical Implications

The MM approximation may:

  1. Miss rapid initial binding (Phase A) - affects early timepoints
  2. Predict incorrect terminal slope - affects extrapolation
  3. Bias \(K_M\) estimates when fitted to data spanning all phases

The full model is preferred when:

  • Early timepoints are available and important
  • Terminal phase is observed and informs dosing
  • Receptor dynamics are of interest

7 Summary: The TMDD Fingerprint

The four-phase framework provides a powerful lens for understanding TMDD:

7.1 Key Takeaways

  1. Phase A (Rapid Binding): Duration ~\(1/(k_{on}(L_0 - R_0))\); reveals \(k_{on}\), \(R_0\)

  2. Phase B (Target Saturated): Slope ~\(k_{el}\); parallel lines across doses

  3. Phase C (Transition): Occurs around \(L \sim K_D\); reveals binding affinity

  4. Phase D (Terminal): Slope ~\(k_{int}\); often internalization-limited

7.2 When to Suspect TMDD in Your Data

7.3 Quick Reference Card

Parameter Typical Phase How to Identify
\(k_{on}\) A Duration of rapid binding
\(R_0\) A, C Initial drop magnitude
\(k_{el}\) B Slope during saturation
\(k_{syn}\) B, C Receptor recovery rate
\(K_D\) C Transition concentration
\(k_{off}\) C Derived from \(K_D\) and \(k_{on}\)
\(k_{int}\) D Terminal slope
\(K_M\) C, D Curvature through transition

8 References

Peletier, L. A., & Gabrielsson, J. (2012). Dynamics of target-mediated drug disposition: Characteristic profiles and parameter identification. Journal of Pharmacokinetics and Pharmacodynamics, 39(5), 429–451. https://doi.org/10.1007/s10928-012-9260-6

Reuse