---
title: "Indirect Response Pharmacodynamic Models"
execute:
  cache: true
  error: false
engine: julia
author:
  - Vijay Ivaturi
  - Marwa Elsaeed
format:
  html:
    include-in-header:
      text: |
        <style>
          .header-container {
            width: 100%;
          }
          .logo {
            display: block;
            width: 150px;
            margin-left: -2.5%;
          }
        </style>
        <link rel = "shortcut icon" href = "https://pumas.ai/favicon.ico" />
    include-before-body:
      text: |
        <div class="header-container">
          <img src="https://pumas-assets.s3.amazonaws.com/CompanyLogos/PumasAI/RGB/PNG/Pumas+AI+Primary%404x.png" alt="Pumas Logo" class="logo">
        </div>
    self-contained-math: true
    html-math-method: katex
    anchor-sections: true
    theme: default
    toc: true
    toc-depth: 4
    toc-expand: 2
    toc-location: left
    toc-title: Contents
    number-sections: true
    code-summary: Show/Hide Code
fig-format: svg
fig-width: 8
fig-height: 6
license: CC BY-SA 4.0
bibliography: references.bib
mermaid:
  theme: neutral
---

```{julia}
#| echo: false
#| output: false
using Pumas
using PumasUtilities
using PumasPlots
using CairoMakie
using AlgebraOfGraphics
using DataFrames
using DataFramesMeta
using Random
```

## Learning Objectives

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

  - Understand the turnover (indirect response) framework
  - Distinguish between the four indirect response model types
  - Choose the appropriate IDR type based on drug mechanism
  - Implement all four IDR models in Pumas
  - Compare response characteristics across model types
  - Apply IDR models to real-world scenarios

## Introduction

Indirect response (IDR) models describe drug effects that are mediated through
**modulation of physiological processes** with inherent production and elimination rates
[@dayneka1993; @sharma1998].
Unlike direct response models, where effect immediately follows concentration,
IDR models capture situations where:

  - Effect persists after drug concentration declines
  - Drug action is mediated through physiological turnover
  - Response involves synthesis/degradation of endogenous substances

```{mermaid}
%%| label: fig-idr-concept
%%| fig-cap: "Indirect response model: Drug affects the balance between production and removal"
flowchart TD
    subgraph Physiological System
        kin[k_in<br/>Production Rate] --> R[Response<br/>Variable R]
        R --> kout[k_out<br/>Removal Rate]
    end

    Drug --> |Inhibit or<br/>Stimulate| kin
    Drug --> |Inhibit or<br/>Stimulate| kout

    style R fill:#e8f5e9
```

### The Turnover Concept

Many physiological variables are maintained at homeostasis through a balance
between production ($k_{in}$) and removal ($k_{out}$):

$$
\frac{dR}{dt} = k_{in} - k_{out} \cdot R
$$

At **steady state** (baseline, no drug):

$$
\frac{dR}{dt} = 0 \implies R_{ss} = \frac{k_{in}}{k_{out}}
$$

:::{.callout-note}

## Key Insight

The drug doesn't directly cause the effect.
Instead, it modifies the rate of production or removal,
and the effect emerges as the system moves to a new equilibrium.
This is why effects often outlast drug concentrations.
:::

### Clinical Examples of Turnover Processes

| Response Variable | Production         | Removal         | Turnover Time |
|:----------------- |:------------------ |:--------------- |:------------- |
| Clotting factors  | Hepatic synthesis  | Degradation     | 1-3 days      |
| Blood glucose     | Hepatic production | Cellular uptake | Hours         |
| Cortisol          | Adrenal secretion  | Metabolism      | ~1 hour       |
| Platelets         | Bone marrow        | Clearance       | 7-10 days     |
| LDL cholesterol   | Hepatic synthesis  | LDL receptors   | ~3 days       |

## The Four Indirect Response Types

Drugs can affect turnover processes in four distinct ways:

```{mermaid}
%%| label: fig-four-idr-types
%%| fig-cap: "The four types of indirect response models"
flowchart LR
    subgraph Type1["IDR Type I"]
        direction TB
        kin1[k_in] -->|Drug INHIBITS| R1[R decreases]
    end

    subgraph Type2["IDR Type II"]
        direction TB
        kout2[k_out] -->|Drug INHIBITS| R2[R increases]
    end

    subgraph Type3["IDR Type III"]
        direction TB
        kin3[k_in] -->|Drug STIMULATES| R3[R increases]
    end

    subgraph Type4["IDR Type IV"]
        direction TB
        kout4[k_out] -->|Drug STIMULATES| R4[R decreases]
    end

    style Type1 fill:#ffebee
    style Type2 fill:#e8f5e9
    style Type3 fill:#e8f5e9
    style Type4 fill:#ffebee
```

| Type | Drug Action              | Effect on $k_{in}$ | Effect on $k_{out}$ | Response Direction |
|:---- |:------------------------ |:------------------ |:------------------- |:------------------ |
| I    | Inhibition of $k_{in}$   | ↓                  | —                   | **Decreases**      |
| II   | Inhibition of $k_{out}$  | —                  | ↓                   | **Increases**      |
| III  | Stimulation of $k_{in}$  | ↑                  | —                   | **Increases**      |
| IV   | Stimulation of $k_{out}$ | —                  | ↑                   | **Decreases**      |

## Mathematical Framework

### General IDR Equations

**Baseline condition** (no drug):

$$
\frac{dR}{dt} = k_{in,0} - k_{out} \cdot R
$$

**With drug effect**, the modulated rate becomes:

:::{.panel-tabset}

#### Type I: Inhibition of $k_{in}$

$$
\frac{dR}{dt} = k_{in,0} \cdot \left(1 - \frac{I_{max} \cdot C}{IC_{50} + C}\right) - k_{out} \cdot R
$$

The production rate is reduced by the drug.

#### Type II: Inhibition of $k_{out}$

$$
\frac{dR}{dt} = k_{in,0} - k_{out} \cdot \left(1 - \frac{I_{max} \cdot C}{IC_{50} + C}\right) \cdot R
$$

The removal rate is reduced by the drug.

#### Type III: Stimulation of $k_{in}$

$$
\frac{dR}{dt} = k_{in,0} \cdot \left(1 + \frac{E_{max} \cdot C}{EC_{50} + C}\right) - k_{out} \cdot R
$$

The production rate is increased by the drug.

#### Type IV: Stimulation of $k_{out}$

$$
\frac{dR}{dt} = k_{in,0} - k_{out} \cdot \left(1 + \frac{E_{max} \cdot C}{EC_{50} + C}\right) \cdot R
$$

The removal rate is increased by the drug.

:::

### Key Parameters

| Parameter           | Description                            | Units         |
|:------------------- |:-------------------------------------- |:------------- |
| $k_{in,0}$          | Baseline production rate               | response/time |
| $k_{out}$           | First-order removal rate constant      | 1/time        |
| $I_{max}$           | Maximum fractional inhibition (0 to 1) | dimensionless |
| $E_{max}$           | Maximum fractional stimulation         | dimensionless |
| $IC_{50}$/$EC_{50}$ | Concentration for 50% effect           | mass/volume   |

:::{.callout-tip}

## Turnover Half-Life

The **turnover half-life** determines how quickly the response variable
returns to baseline after drug removal:

$$
t_{1/2,turnover} = \frac{\ln(2)}{k_{out}}
$$

A process with $t_{1/2}$ = 24 hours (e.g., clotting factors)
takes ~4-5 days to fully recover after drug cessation.
:::

## Pumas Implementation

### IDR Type I: Inhibition of Production

```{julia}
idr_type1 = @model begin
    @metadata begin
        desc = "Indirect Response Model Type I: Inhibition of kin"
        timeu = u"hr"
    end

    @param begin
        # PK parameters
        pop_Ka ∈ RealDomain(; lower = 0, init = 1.0)
        pop_CL ∈ RealDomain(; lower = 0, init = 0.5)
        pop_Vc ∈ RealDomain(; lower = 0, init = 20.0)

        # PD parameters
        """
        Baseline response (R0 = kin0/kout)
        """
        pop_R0 ∈ RealDomain(; lower = 0, init = 100.0)
        """
        Turnover time (1/kout)
        """
        pop_turnover ∈ RealDomain(; lower = 0, init = 10.0)
        """
        Maximum fractional inhibition of kin
        """
        pop_Imax ∈ RealDomain(; lower = 0, upper = 1, init = 0.9)
        """
        Concentration at 50% inhibition
        """
        pop_IC50 ∈ RealDomain(; lower = 0, init = 2.0)

        # BSV and RUV
        Ω_pk ∈ PDiagDomain(3)
        Ω_pd ∈ PDiagDomain(1)
        σ_prop_pk ∈ RealDomain(; lower = 0, init = 0.1)
        σ_add_pd ∈ RealDomain(; lower = 0, init = 5.0)
    end

    @random begin
        η_pk ~ MvNormal(Ω_pk)
        η_pd ~ MvNormal(Ω_pd)
    end

    @pre begin
        # PK parameters
        CL = pop_CL * exp(η_pk[1])
        Vc = pop_Vc * exp(η_pk[2])
        Ka = pop_Ka * exp(η_pk[3])

        # PD parameters
        R0 = pop_R0 * exp(η_pd[1])
        kout = 1 / pop_turnover
        kin0 = R0 * kout  # Derived from steady-state condition
        Imax = pop_Imax
        IC50 = pop_IC50
    end

    @init begin
        Response = R0  # Start at baseline
    end

    @vars begin
        # Plasma concentration
        Cp = Central / Vc
        # IDR Type I: Drug inhibits production
        inhibition = Imax * Cp / (IC50 + Cp)
        kin = kin0 * (1 - inhibition)
        # Response for plotting
        Resp = Response
    end

    @dynamics begin
        # PK
        Depot' = -Ka * Depot
        Central' = Ka * Depot - (CL / Vc) * Central
        # Response dynamics
        Response' = kin - kout * Response
    end

    @derived begin
        conc ~ @. Normal(Cp, abs(Cp) * σ_prop_pk)
        response ~ @. Normal(Response, σ_add_pd)
    end
end
```

### IDR Type II: Inhibition of Removal

```{julia}
idr_type2 = @model begin
    @metadata begin
        desc = "Indirect Response Model Type II: Inhibition of kout"
        timeu = u"hr"
    end

    @param begin
        pop_Ka ∈ RealDomain(; lower = 0, init = 1.0)
        pop_CL ∈ RealDomain(; lower = 0, init = 0.5)
        pop_Vc ∈ RealDomain(; lower = 0, init = 20.0)
        pop_R0 ∈ RealDomain(; lower = 0, init = 100.0)
        pop_turnover ∈ RealDomain(; lower = 0, init = 10.0)
        pop_Imax ∈ RealDomain(; lower = 0, upper = 1, init = 0.9)
        pop_IC50 ∈ RealDomain(; lower = 0, init = 2.0)
        Ω_pk ∈ PDiagDomain(3)
        Ω_pd ∈ PDiagDomain(1)
        σ_prop_pk ∈ RealDomain(; lower = 0, init = 0.1)
        σ_add_pd ∈ RealDomain(; lower = 0, init = 5.0)
    end

    @random begin
        η_pk ~ MvNormal(Ω_pk)
        η_pd ~ MvNormal(Ω_pd)
    end

    @pre begin
        CL = pop_CL * exp(η_pk[1])
        Vc = pop_Vc * exp(η_pk[2])
        Ka = pop_Ka * exp(η_pk[3])
        R0 = pop_R0 * exp(η_pd[1])
        kout0 = 1 / pop_turnover
        kin = R0 * kout0
        Imax = pop_Imax
        IC50 = pop_IC50
    end

    @init begin
        Response = R0
    end

    @vars begin
        # Plasma concentration
        Cp = Central / Vc
        # IDR Type II: Drug inhibits removal
        inhibition = Imax * Cp / (IC50 + Cp)
        kout = kout0 * (1 - inhibition)
        # Response for plotting
        Resp = Response
    end

    @dynamics begin
        Depot' = -Ka * Depot
        Central' = Ka * Depot - (CL / Vc) * Central
        # Response dynamics
        Response' = kin - kout * Response
    end

    @derived begin
        conc ~ @. Normal(Cp, abs(Cp) * σ_prop_pk)
        response ~ @. Normal(Response, σ_add_pd)
    end
end
```

### IDR Type III: Stimulation of Production

```{julia}
idr_type3 = @model begin
    @metadata begin
        desc = "Indirect Response Model Type III: Stimulation of kin"
        timeu = u"hr"
    end

    @param begin
        pop_Ka ∈ RealDomain(; lower = 0, init = 1.0)
        pop_CL ∈ RealDomain(; lower = 0, init = 0.5)
        pop_Vc ∈ RealDomain(; lower = 0, init = 20.0)
        pop_R0 ∈ RealDomain(; lower = 0, init = 100.0)
        pop_turnover ∈ RealDomain(; lower = 0, init = 10.0)
        """
        Maximum fractional stimulation of kin
        """
        pop_Emax ∈ RealDomain(; lower = 0, init = 2.0)
        pop_EC50 ∈ RealDomain(; lower = 0, init = 2.0)
        Ω_pk ∈ PDiagDomain(3)
        Ω_pd ∈ PDiagDomain(1)
        σ_prop_pk ∈ RealDomain(; lower = 0, init = 0.1)
        σ_add_pd ∈ RealDomain(; lower = 0, init = 5.0)
    end

    @random begin
        η_pk ~ MvNormal(Ω_pk)
        η_pd ~ MvNormal(Ω_pd)
    end

    @pre begin
        CL = pop_CL * exp(η_pk[1])
        Vc = pop_Vc * exp(η_pk[2])
        Ka = pop_Ka * exp(η_pk[3])
        R0 = pop_R0 * exp(η_pd[1])
        kout = 1 / pop_turnover
        kin0 = R0 * kout
        Emax = pop_Emax
        EC50 = pop_EC50
    end

    @init begin
        Response = R0
    end

    @vars begin
        # Plasma concentration
        Cp = Central / Vc
        # IDR Type III: Drug stimulates production
        stimulation = Emax * Cp / (EC50 + Cp)
        kin = kin0 * (1 + stimulation)
        # Response for plotting
        Resp = Response
    end

    @dynamics begin
        Depot' = -Ka * Depot
        Central' = Ka * Depot - (CL / Vc) * Central
        # Response dynamics
        Response' = kin - kout * Response
    end

    @derived begin
        conc ~ @. Normal(Cp, abs(Cp) * σ_prop_pk)
        response ~ @. Normal(Response, σ_add_pd)
    end
end
```

### IDR Type IV: Stimulation of Removal

```{julia}
idr_type4 = @model begin
    @metadata begin
        desc = "Indirect Response Model Type IV: Stimulation of kout"
        timeu = u"hr"
    end

    @param begin
        pop_Ka ∈ RealDomain(; lower = 0, init = 1.0)
        pop_CL ∈ RealDomain(; lower = 0, init = 0.5)
        pop_Vc ∈ RealDomain(; lower = 0, init = 20.0)
        pop_R0 ∈ RealDomain(; lower = 0, init = 100.0)
        pop_turnover ∈ RealDomain(; lower = 0, init = 10.0)
        pop_Emax ∈ RealDomain(; lower = 0, init = 2.0)
        pop_EC50 ∈ RealDomain(; lower = 0, init = 2.0)
        Ω_pk ∈ PDiagDomain(3)
        Ω_pd ∈ PDiagDomain(1)
        σ_prop_pk ∈ RealDomain(; lower = 0, init = 0.1)
        σ_add_pd ∈ RealDomain(; lower = 0, init = 5.0)
    end

    @random begin
        η_pk ~ MvNormal(Ω_pk)
        η_pd ~ MvNormal(Ω_pd)
    end

    @pre begin
        CL = pop_CL * exp(η_pk[1])
        Vc = pop_Vc * exp(η_pk[2])
        Ka = pop_Ka * exp(η_pk[3])
        R0 = pop_R0 * exp(η_pd[1])
        kout0 = 1 / pop_turnover
        kin = R0 * kout0
        Emax = pop_Emax
        EC50 = pop_EC50
    end

    @init begin
        Response = R0
    end

    @vars begin
        # Plasma concentration
        Cp = Central / Vc
        # IDR Type IV: Drug stimulates removal
        stimulation = Emax * Cp / (EC50 + Cp)
        kout = kout0 * (1 + stimulation)
        # Response for plotting
        Resp = Response
    end

    @dynamics begin
        Depot' = -Ka * Depot
        Central' = Ka * Depot - (CL / Vc) * Central
        # Response dynamics
        Response' = kin - kout * Response
    end

    @derived begin
        conc ~ @. Normal(Cp, abs(Cp) * σ_prop_pk)
        response ~ @. Normal(Response, σ_add_pd)
    end
end
```

## Comparative Simulation

Let's simulate all four IDR types with the same PK parameters to compare their behavior:

```{julia}
# Parameters for inhibition models (Types I, II)
params_inhib = (
    pop_Ka = 1.0,
    pop_CL = 0.5,
    pop_Vc = 20.0,
    pop_R0 = 100.0,
    pop_turnover = 10.0,  # t1/2 ≈ 7 hr
    pop_Imax = 0.8,
    pop_IC50 = 2.0,
    Ω_pk = Diagonal([0.0, 0.0, 0.0]),  # No variability for comparison
    Ω_pd = Diagonal([0.0]),
    σ_prop_pk = 0.0,
    σ_add_pd = 0.0,
)

# Parameters for stimulation models (Types III, IV)
params_stim = (
    pop_Ka = 1.0,
    pop_CL = 0.5,
    pop_Vc = 20.0,
    pop_R0 = 100.0,
    pop_turnover = 10.0,  # t1/2 ≈ 7 hr
    pop_Emax = 1.5,
    pop_EC50 = 2.0,
    Ω_pk = Diagonal([0.0, 0.0, 0.0]),  # No variability for comparison
    Ω_pd = Diagonal([0.0]),
    σ_prop_pk = 0.0,
    σ_add_pd = 0.0,
)

# Dosing and subject
dosing = DosageRegimen(100, time = 0, cmt = 1)
subject = Subject(id = 1, events = dosing)

# Simulate all four types (no residual error for clean visualization)
sim1 = simobs(idr_type1, subject, params_inhib, obstimes = 0:0.5:72, simulate_error = false)
sim2 = simobs(idr_type2, subject, params_inhib, obstimes = 0:0.5:72, simulate_error = false)
sim3 = simobs(idr_type3, subject, params_stim, obstimes = 0:0.5:72, simulate_error = false)
sim4 = simobs(idr_type4, subject, params_stim, obstimes = 0:0.5:72, simulate_error = false)
```

```{julia}
#| label: fig-idr-comparison
#| fig-cap: "Comparison of all four IDR model types with identical PK"

# Convert simulations to DataFrames
df1 = DataFrame(sim1)
df1.idr_type .= "Type I: Inhibition of kin"
df2 = DataFrame(sim2)
df2.idr_type .= "Type II: Inhibition of kout"
df3 = DataFrame(sim3)
df3.idr_type .= "Type III: Stimulation of kin"
df4 = DataFrame(sim4)
df4.idr_type .= "Type IV: Stimulation of kout"

# PK plot (use df1 since PK is same for all) - using vars: Cp
pk_plt =
    data(df1) *
    mapping(:time => "Time (hr)", :Cp => "Concentration (mg/L)") *
    visual(Lines, linewidth = 2, color = :steelblue)

fig = Figure(size = (900, 700))
draw!(fig[1, 1:2], pk_plt; axis = (title = "Plasma Concentration (Common to All)",))

# Draw individual response panels
for (i, (df, title, color, pos)) in enumerate(
    zip(
        [df1, df2, df3, df4],
        [
            "Type I: Inhibition of kin",
            "Type II: Inhibition of kout",
            "Type III: Stimulation of kin",
            "Type IV: Stimulation of kout",
        ],
        [:red, :green, :purple, :orange],
        [(2, 1), (2, 2), (3, 1), (3, 2)],
    ),
)
    plt =
        data(df) *
        mapping(:time => "Time (hr)", :Resp => "Response") *
        visual(Lines, linewidth = 2, color = color)
    ax = Axis(fig[pos...], xlabel = "Time (hr)", ylabel = "Response", title = title)
    draw!(ax, plt)
    hlines!(ax, [100], linestyle = :dash, color = :gray)
end

fig
```

### Key Observations

:::{.callout-note}

## Response Characteristics

**Types I and IV** → Response **decreases**

  - Type I: Reduced production leads to gradual decline
  - Type IV: Increased removal leads to faster decline

**Types II and III** → Response **increases**

  - Type II: Reduced removal causes accumulation
  - Type III: Increased production causes rise

**All types**: Response returns to baseline after drug clears,
governed by the turnover half-life.
:::

### Overlay Comparison

```{julia}
#| label: fig-idr-overlay
#| fig-cap: "Overlaid comparison of all four IDR types"

# Prepare labeled DataFrames (reuse df1-df4 from previous block) - using vars: Resp
df1_labeled = select(df1, :time, :Resp)
df1_labeled.type .= "Type I (↓kin)"
df2_labeled = select(df2, :time, :Resp)
df2_labeled.type .= "Type II (↓kout)"
df3_labeled = select(df3, :time, :Resp)
df3_labeled.type .= "Type III (↑kin)"
df4_labeled = select(df4, :time, :Resp)
df4_labeled.type .= "Type IV (↑kout)"

overlay_df = vcat(df1_labeled, df2_labeled, df3_labeled, df4_labeled)

plt =
    data(overlay_df) *
    mapping(:time => "Time (hr)", :Resp => "Response", color = :type => "IDR Type") *
    visual(Lines, linewidth = 2)

draw(
    plt;
    axis = (
        xlabel = "Time (hr)",
        ylabel = "Response",
        title = "All Four IDR Types Compared",
        width = 700,
        height = 400,
    ),
)
```

## Choosing the Right IDR Type

The choice of IDR model depends on the **mechanism of drug action**:

:::{.panel-tabset}

### Type I Examples

**Inhibition of production rate**

| Drug            | Target            | Response Variable  |
|:--------------- |:----------------- |:------------------ |
| Corticosteroids | ACTH release      | Cortisol levels    |
| Statins         | HMG-CoA reductase | LDL cholesterol    |
| Methotrexate    | DNA synthesis     | Cell proliferation |

**Clinical scenario**: A drug suppresses the synthesis of a biomarker.
After drug removal, the biomarker slowly returns as production resumes
[@chakraborty1999].

### Type II Examples

**Inhibition of removal rate**

| Drug           | Target                      | Response Variable |
|:-------------- |:--------------------------- |:----------------- |
| PPIs           | H⁺/K⁺-ATPase                | Gastric acid      |
| ACE inhibitors | Angiotensin degradation     | Bradykinin levels |
| Warfarin       | Clotting factor degradation | Clotting factors  |

**Clinical scenario**: A drug blocks the clearance of a substance,
causing it to accumulate above baseline [@hamberg2007].

### Type III Examples

**Stimulation of production rate**

| Drug                  | Target                | Response Variable |
|:--------------------- |:--------------------- |:----------------- |
| Erythropoietin        | RBC production        | Hemoglobin        |
| G-CSF                 | Neutrophil production | WBC count         |
| Insulin secretagogues | β-cell secretion      | Insulin levels    |

**Clinical scenario**: A drug enhances the synthesis of an endogenous factor,
leading to supranormal levels during treatment.

### Type IV Examples

**Stimulation of removal rate**

| Drug            | Target              | Response Variable |
|:--------------- |:------------------- |:----------------- |
| Diuretics       | Sodium excretion    | Body sodium       |
| Enzyme inducers | Metabolic clearance | Drug levels       |
| Laxatives       | GI motility         | Gut contents      |

**Clinical scenario**: A drug accelerates the elimination of a substance,
causing levels to drop below baseline.

:::

## Effect of Turnover Time

The turnover time ($1/k_{out}$) significantly affects the response dynamics:

```{julia}
#| label: fig-turnover-effect
#| fig-cap: "Effect of turnover time on response dynamics (Type I model)"

turnover_times = [2.0, 10.0, 30.0]
labels = ["τ = 2 hr (fast)", "τ = 10 hr (moderate)", "τ = 30 hr (slow)"]

# Simulate for each turnover time and collect results (no residual error for visualization)
turnover_results = map(zip(turnover_times, labels)) do (τ, label)
    params_var = merge(params_inhib, (; pop_turnover = τ))
    sim_var = simobs(
        idr_type1,
        subject,
        params_var,
        obstimes = 0:0.5:120,
        simulate_error = false,
    )
    df = DataFrame(sim_var)
    df.turnover_label .= label
    df
end
turnover_df = vcat(turnover_results...)

plt =
    data(turnover_df) *
    mapping(
        :time => "Time (hr)",
        :Resp => "Response",
        color = :turnover_label => "Turnover Time",
    ) *
    visual(Lines, linewidth = 2)

draw(
    plt;
    axis = (
        xlabel = "Time (hr)",
        ylabel = "Response",
        title = "Impact of Turnover Time on Response",
        width = 700,
        height = 350,
    ),
)
```

:::{.callout-tip}

## Interpretation

  - **Fast turnover** (τ = 2 hr): Response changes quickly, returns to baseline fast
  - **Slow turnover** (τ = 30 hr): Response changes gradually, takes days to normalize

The turnover time determines the "memory" of the system.
:::

## Fitting Workflow (Type I Example)

### Generate Synthetic Data

```{julia}
#| output: false
# Parameters with variability
params_fit = (
    pop_Ka = 1.0,
    pop_CL = 0.5,
    pop_Vc = 20.0,
    pop_R0 = 100.0,
    pop_turnover = 10.0,
    pop_Imax = 0.8,
    pop_IC50 = 2.0,
    Ω_pk = Diagonal([0.09, 0.09, 0.09]),
    Ω_pd = Diagonal([0.04]),
    σ_prop_pk = 0.1,
    σ_add_pd = 5.0,
)

# Population
population = map(1:20) do i
    Subject(id = i, events = dosing)
end

Random.seed!(789)
sim_data =
    simobs(idr_type1, population, params_fit, obstimes = [1, 2, 4, 8, 12, 24, 36, 48])
df_sim = DataFrame(sim_data)
```

### Fit the Model

```{julia}
fit_pop = read_pumas(
    df_sim;
    id = :id,
    time = :time,
    amt = :amt,
    evid = :evid,
    cmt = :cmt,
    observations = [:conc, :response],
)

init_params = (
    pop_Ka = 0.8,
    pop_CL = 0.4,
    pop_Vc = 25.0,
    pop_R0 = 90.0,
    pop_turnover = 8.0,
    pop_Imax = 0.7,
    pop_IC50 = 1.5,
    Ω_pk = Diagonal([0.05, 0.05, 0.05]),
    Ω_pd = Diagonal([0.02]),
    σ_prop_pk = 0.15,
    σ_add_pd = 8.0,
)

fit_result = fit(idr_type1, fit_pop, init_params, FOCE())
```

```{julia}
coef(fit_result)
```

## Model Diagnostics

```{julia}
insp = inspect(fit_result)
```

```{julia}
#| label: fig-gof-idr
#| fig-cap: "Goodness-of-fit for IDR Type I model"
goodness_of_fit(insp; observations = [:response])
```

## Summary

In this tutorial, we covered:

 1. **Turnover concept**: Physiological variables maintained by production/removal balance
 2. **Four IDR types**: Distinguished by drug action on $k_{in}$ or $k_{out}$
 3. **Response direction**: Types I/IV decrease response; Types II/III increase it
 4. **Turnover time**: Governs speed of response and recovery
 5. **Pumas implementation**: Complete models for all four types
 6. **Model selection**: Based on drug mechanism of action

### Key Takeaways

  - IDR models explain why effects outlast drug concentrations
  - The turnover half-life determines response dynamics
  - Choose model type based on mechanism (inhibition vs stimulation, production vs removal)
  - Effects are reversible - response returns to baseline after drug clears

### Next Steps

If your drug shows:

  - **Irreversible effects**: Consider [K-PD Models](04-kpd-models.qmd)
  - **Need to compare models**: See [Model Selection Tutorial](05-model-selection.qmd)
