Skip to content

Tolerance Models

PD models for tolerance development through counter-regulation or receptor regulation mechanisms.


Counter-Regulation Tolerance

Function Signature

neopkpd.simulate_pkpd_tolerance_counter_regulation(
    cl: float,
    v: float,
    doses: list[dict],
    e0: float,
    emax: float,
    ec50: float,
    gamma: float,
    kin_mod: float,
    kout_mod: float,
    alpha_feedback: float,
    t0: float,
    t1: float,
    saveat: list[float],
    pk_kind: str = "OneCompIVBolus",
    ka: float | None = None,
    q: float | None = None,
    v2: float | None = None,
    ...
) -> dict

Parameters

Parameter Type Description
e0 float Baseline effect
emax float Maximum drug effect
ec50 float EC50 for drug effect
gamma float Hill coefficient
kin_mod float Moderator production rate constant
kout_mod float Moderator elimination rate constant
alpha_feedback float Feedback strength coefficient

Model Equations

Drug effect: $\(E_{drug} = \frac{E_{max} \cdot C^\gamma}{EC_{50}^\gamma + C^\gamma}\)$

Moderator dynamics (builds up with drug effect): $\(\frac{dM}{dt} = k_{in,mod} \cdot E_{drug} - k_{out,mod} \cdot M\)$

Net effect with tolerance: $\(E_{net} = E_0 + E_{drug} - \alpha \cdot M\)$


Basic Counter-Regulation Example

import neopkpd

# Chronic dosing with tolerance development
doses = [{"time": i * 8.0, "amount": 50.0} for i in range(21)]  # TID for 7 days

result = neopkpd.simulate_pkpd_tolerance_counter_regulation(
    cl=5.0,
    v=50.0,
    doses=doses,
    e0=0.0,
    emax=100.0,
    ec50=5.0,
    gamma=1.0,
    kin_mod=0.1,       # Moderator production
    kout_mod=0.05,     # Moderator elimination (t1/2 ~14h)
    alpha_feedback=1.0, # Full feedback
    t0=0.0,
    t1=168.0,          # 1 week
    saveat=[i * 0.5 for i in range(337)]
)

effect = result['observations']['effect']
t = result['t']

# Compare first dose vs last dose effect
first_dose_peak = max(effect[:16])  # First 8 hours
last_dose_peak = max(effect[-16:])  # Last 8 hours

print("Counter-Regulation Tolerance:")
print(f"  First dose peak effect: {first_dose_peak:.1f}")
print(f"  Last dose peak effect: {last_dose_peak:.1f}")
print(f"  Tolerance: {(1 - last_dose_peak/first_dose_peak) * 100:.1f}% reduction")

Clinical Example: Opioid Tolerance

import neopkpd

# Morphine-like tolerance
# Daily dosing for 2 weeks

doses = [{"time": i * 6.0, "amount": 10.0} for i in range(56)]  # Q6H for 2 weeks

result = neopkpd.simulate_pkpd_tolerance_counter_regulation(
    cl=60.0, v=200.0,    # Morphine-like PK
    doses=doses,
    e0=0.0,              # Baseline pain score
    emax=100.0,          # Max analgesia
    ec50=0.05,           # EC50 (mg/L)
    gamma=2.0,
    kin_mod=0.2,
    kout_mod=0.01,       # Slow moderator turnover (~3 day t1/2)
    alpha_feedback=0.8,
    t0=0.0, t1=336.0,
    saveat=[i * 1.0 for i in range(337)]
)

effect = result['observations']['effect']
t = result['t']

# Daily peak effect
print("Daily Peak Analgesia:")
for day in [1, 3, 7, 14]:
    start = (day - 1) * 24
    end = day * 24
    peak = max(effect[start:end])
    print(f"  Day {day:2d}: {peak:.1f}")

Effect of Feedback Strength

import neopkpd

alpha_values = [0.0, 0.25, 0.5, 1.0, 1.5]

doses = [{"time": i * 12.0, "amount": 50.0} for i in range(14)]

print("Alpha | Day 1 Peak | Day 7 Peak | Tolerance %")
print("-" * 50)

for alpha in alpha_values:
    result = neopkpd.simulate_pkpd_tolerance_counter_regulation(
        cl=5.0, v=50.0, doses=doses,
        e0=0.0, emax=100.0, ec50=5.0, gamma=1.0,
        kin_mod=0.1, kout_mod=0.05, alpha_feedback=alpha,
        t0=0.0, t1=168.0,
        saveat=[i * 0.5 for i in range(337)]
    )

    effect = result['observations']['effect']
    day1_peak = max(effect[:24])
    day7_peak = max(effect[-24:])
    tolerance = (1 - day7_peak/day1_peak) * 100 if day1_peak > 0 else 0

    print(f"{alpha:5.2f} | {day1_peak:10.1f} | {day7_peak:10.1f} | {tolerance:10.1f}")

Receptor Regulation Model

Function Signature

neopkpd.simulate_pkpd_receptor_regulation(
    cl: float,
    v: float,
    doses: list[dict],
    e0: float,
    emax: float,
    ec50: float,
    gamma: float,
    r_baseline: float,
    kreg: float,
    rmax: float,
    kchange: float,
    direction: str,  # "down" or "up"
    t0: float,
    t1: float,
    saveat: list[float],
    ...
) -> dict

Parameters

Parameter Type Description
r_baseline float Baseline receptor density (normalized, typically 1.0)
kreg float Receptor return-to-baseline rate constant
rmax float Maximum receptor density (for up-regulation)
kchange float Rate of receptor change
direction str "down" or "up" regulation

Model Equations

Receptor dynamics: $\(\frac{dR}{dt} = k_{reg} \cdot (R_{baseline} - R) + regulation\_effect\)$

Down-regulation: $\(regulation\_effect = -k_{change} \cdot E_{drug} \cdot R\)$

Up-regulation: $\(regulation\_effect = +k_{change} \cdot E_{drug} \cdot (R_{max} - R)\)$

Net effect: $\(E_{net} = E_0 + R \cdot E_{drug}\)$


Receptor Down-Regulation Example

import neopkpd

# Beta-receptor down-regulation with chronic agonist
doses = [{"time": i * 8.0, "amount": 50.0} for i in range(21)]

result = neopkpd.simulate_pkpd_receptor_regulation(
    cl=5.0, v=50.0, doses=doses,
    e0=0.0, emax=100.0, ec50=5.0, gamma=1.0,
    r_baseline=1.0,    # Normalized baseline
    kreg=0.05,         # Receptor recovery rate
    rmax=2.0,          # Not used for down-regulation
    kchange=0.02,      # Down-regulation rate
    direction="down",
    t0=0.0, t1=168.0,
    saveat=[i * 0.5 for i in range(337)]
)

effect = result['observations']['effect']
receptor = result['states']['R']
t = result['t']

print("Beta-Receptor Down-Regulation:")
print(f"  Initial receptor: {receptor[0]:.2f}")
print(f"  Day 7 receptor: {receptor[-1]:.2f}")
print(f"  First dose peak: {max(effect[:16]):.1f}")
print(f"  Day 7 dose peak: {max(effect[-16:]):.1f}")

Receptor Up-Regulation Example

import neopkpd

# Receptor up-regulation (e.g., chronic antagonist exposure)
doses = [{"time": i * 12.0, "amount": 30.0} for i in range(14)]

result = neopkpd.simulate_pkpd_receptor_regulation(
    cl=5.0, v=50.0, doses=doses,
    e0=0.0, emax=100.0, ec50=5.0, gamma=1.0,
    r_baseline=1.0,
    kreg=0.03,
    rmax=3.0,          # Max 3x receptor density
    kchange=0.01,
    direction="up",
    t0=0.0, t1=168.0,
    saveat=[i * 0.5 for i in range(337)]
)

effect = result['observations']['effect']
receptor = result['states']['R']
t = result['t']

print("Receptor Up-Regulation:")
print(f"  Initial receptor: {receptor[0]:.2f}")
print(f"  Day 7 receptor: {receptor[-1]:.2f}")
print(f"  Receptor increase: {(receptor[-1]/receptor[0] - 1) * 100:.1f}%")

Recovery After Drug Discontinuation

import neopkpd

# 1 week dosing, then 2 weeks recovery
doses = [{"time": i * 8.0, "amount": 50.0} for i in range(21)]  # 7 days only

result = neopkpd.simulate_pkpd_tolerance_counter_regulation(
    cl=5.0, v=50.0, doses=doses,
    e0=0.0, emax=100.0, ec50=5.0, gamma=1.0,
    kin_mod=0.1, kout_mod=0.02, alpha_feedback=1.0,
    t0=0.0, t1=504.0,  # 3 weeks total
    saveat=[i * 1.0 for i in range(505)]
)

effect = result['observations']['effect']
t = result['t']

print("Tolerance Recovery:")
print(f"  Day 7 (end of dosing): Moderator at maximum")
print(f"  Day 14: Partial recovery")
print(f"  Day 21: Near baseline")

# Simulate re-exposure after 2-week break
# (Would need new simulation with rechallenge dose)

Comparing Tolerance Mechanisms

import neopkpd

doses = [{"time": i * 8.0, "amount": 50.0} for i in range(21)]

# Counter-regulation
result_counter = neopkpd.simulate_pkpd_tolerance_counter_regulation(
    cl=5.0, v=50.0, doses=doses,
    e0=0.0, emax=100.0, ec50=5.0, gamma=1.0,
    kin_mod=0.1, kout_mod=0.05, alpha_feedback=1.0,
    t0=0.0, t1=168.0,
    saveat=[i * 0.5 for i in range(337)]
)

# Receptor down-regulation
result_receptor = neopkpd.simulate_pkpd_receptor_regulation(
    cl=5.0, v=50.0, doses=doses,
    e0=0.0, emax=100.0, ec50=5.0, gamma=1.0,
    r_baseline=1.0, kreg=0.05, rmax=2.0, kchange=0.02,
    direction="down",
    t0=0.0, t1=168.0,
    saveat=[i * 0.5 for i in range(337)]
)

counter_effect = result_counter['observations']['effect']
receptor_effect = result_receptor['observations']['effect']

print("Tolerance Mechanism Comparison:")
print("                  | Counter-Reg | Receptor")
print("-" * 50)
print(f"Day 1 peak effect | {max(counter_effect[:48]):11.1f} | {max(receptor_effect[:48]):.1f}")
print(f"Day 7 peak effect | {max(counter_effect[-48:]):11.1f} | {max(receptor_effect[-48:]):.1f}")

Dose Escalation to Overcome Tolerance

import neopkpd

# Escalating dose to maintain effect
base_dose = 50.0
escalation = 1.2  # 20% increase each day

doses = []
for day in range(7):
    daily_dose = base_dose * (escalation ** day)
    for dose_num in range(3):  # TID
        doses.append({"time": day * 24 + dose_num * 8.0, "amount": daily_dose})

result = neopkpd.simulate_pkpd_tolerance_counter_regulation(
    cl=5.0, v=50.0, doses=doses,
    e0=0.0, emax=100.0, ec50=5.0, gamma=1.0,
    kin_mod=0.1, kout_mod=0.05, alpha_feedback=1.0,
    t0=0.0, t1=168.0,
    saveat=[i * 0.5 for i in range(337)]
)

effect = result['observations']['effect']

print("Dose Escalation to Maintain Effect:")
for day in range(7):
    start = day * 48
    end = (day + 1) * 48
    peak = max(effect[start:end])
    dose = base_dose * (escalation ** day)
    print(f"  Day {day+1}: Dose = {dose:.0f} mg, Peak effect = {peak:.1f}")

Equations Summary

Counter-Regulation Model

Quantity Formula
Drug effect \(E_{max} \cdot C^\gamma / (EC_{50}^\gamma + C^\gamma)\)
Moderator rate \(k_{in,mod} \cdot E_{drug} - k_{out,mod} \cdot M\)
Net effect \(E_0 + E_{drug} - \alpha \cdot M\)
Moderator t1/2 \(\ln(2) / k_{out,mod}\)

Receptor Regulation Model

Quantity Formula
Down-regulation \(k_{reg}(R_0 - R) - k_{change} \cdot E_{drug} \cdot R\)
Up-regulation \(k_{reg}(R_0 - R) + k_{change} \cdot E_{drug} \cdot (R_{max} - R)\)
Net effect \(E_0 + R \cdot E_{drug}\)

See Also