Skip to contents

Model and source

  • Citation: Hill-McManus D, Soto E, Marshall S, Lane S, Hughes D. Impact of non-adherence on the safety and efficacy of uric acid-lowering therapies in the treatment of gout. Br J Clin Pharmacol. 2018;84(1):142-152. doi:10.1111/bcp.13427
  • Description: Semi-mechanistic dual-drug PKPD model for the impact of non-adherence to febuxostat (xanthine oxidase inhibitor) plus lesinurad (URAT1 uricosuric) urate-lowering therapy in gout; combines published 2-compartment first-order absorption PK for each drug with a 4-compartment xanthine / uric-acid PD system (Hill-McManus 2017)
  • Article: https://doi.org/10.1111/bcp.13427

Population

The PD system parameters were estimated by nonlinear mixed-effects modelling of TMX-99-001 phase-I summary data in 154 healthy volunteers receiving febuxostat (24-hour AUC and 24-hour urinary excretion of xanthine and uric acid, Khosravan 2006). Renal clearance values for xanthine (CLX) and uric acid (CLUA) were taken from the same TMX-99-001 dataset as literature-fixed weighted-average estimates. Two-compartment PK models for febuxostat and lesinurad were carried over from Khosravan 2006 and the lesinurad FDA review respectively (Hill-McManus 2017 Table 2).

For the gout-patient simulation (Methods “Gout patient simulation model” on page 146), baseline characteristics match the CRYSTAL trial cohort (study 304): pretreatment serum uric acid log-normal mean 8.83 mg/dL (standard deviation 1.53); 95 percent male; weight and age log-normally distributed at the CRYSTAL trial means; Cockcroft-Gault creatinine clearance with a 15 mL/min downward adjustment and exclusion of values below 30 mL/min (page 147). Two phenotypes are simulated (Table 3): under-excreters (CLUA scaled down by theta_4 / BUA) and overproducers (BX scaled up by BUA / theta_4). Both apply BUA = VUA * sUA so the patient’s elevated serum uric acid is reached at the same volume of distribution as the healthy subject.

The same information is available programmatically from the model’s population metadata (readModelDb("HillMcManus_2017_febuxostat_lesinurad")$population).

Source trace

The per-parameter origin is recorded as an in-file comment next to each ini() entry in inst/modeldb/specificDrugs/HillMcManus_2017_febuxostat_lesinurad.R. The table below collects them in one place.

Element Value / form Source location
Febuxostat PK (Ka, CL/F_0, Vc/F_0, Vp/F, Q/F, Tlag) 13.7 1/h, 49.3 dL/h, 322 dL, 222 dL, 55.7 dL/h, 0.23 h Hill-McManus 2017 Table 2 (reproduced from Khosravan 2006, ref 22)
Febuxostat CL covariates CL/F = CL/F_0 + 0.142*CrCl + 0.155*WT (additive) Table 2 footnote a
Lesinurad PK (Ka, CL/F_0, Vc/F_0, Vp/F, Q/F, Tlag) 0.69 1/h, 69.9 dL/h, 241 dL, 83 dL, 4.48 dL/h, 0.233 h Hill-McManus 2017 Table 2 (reproduced from FDA review, ref 23)
Lesinurad CL and Vc covariates CL/F = CL/F_0 * (CrCl/87)^0.322, Vc/F = Vc/F_0 * (WT/70)^0.511 Table 2 footnotes a, b
System PD: BX, VX, CLX 8.94 mg, 333 dL, 10.57 dL/h Table 1 theta_1..theta_3 (CLX literature)
System PD: BUA, VUA, CLUA 703 mg, 154 dL, 4.11 dL/h Table 1 theta_4..theta_6 (CLUA literature)
Febuxostat PD: STIM1 (Emax_1, EC50_1) 3, 0.001 mg/dL (Assumed) Table 1 theta_7..theta_8
Febuxostat PD: INH1 (Imax_1, IC50_1) 1 (Assumed), 0.1320 mg/dL (Estimated; eta_3) Table 1 theta_9..theta_10
Febuxostat PD: INH2 (Imax_2, IC50_2) 1 (Assumed), 0.00113 mg/dL (Estimated; eta_3 shared with IC50_1) Table 1 theta_11..theta_12
Lesinurad PD direct-Emax (E0, E_Dmax, b_CrCl, EC_D50) 6.77, 2.55, 0.564, 0.0974 mg/dL (Literature) Table 1 theta_13..theta_16
Lesinurad indirect derivation Emax_2 = E0/(E0 - E_Dmax_i) - 1; EC50_2 = (Emax_2 * EC_D50)/(E0/(E0 - E_Dmax/2) - 1) - EC_D50 Methods page 146 (boxed equations)
Steady-state rate constants k2 = CLX/VX; k3 = CLUA/VUA; k1 = k3 * BUA / (BX * (M_UA/M_X)); k0 = (k1 + k2) * BX Figure 1 Eqs 5-8
PD system ODEs Eqs 1-4 (xanthine production -> conversion -> elimination; UA formation -> elimination; urinary accumulators) Figure 1
PD drug functions INH = 1 - Imax * C/(IC50 + C); STIM = 1 + Emax * C/(EC50 + C) Figure 1 Eqs 9-12 (with explicit Imax for auditability)
Hyperuricosuria threshold 800 mg / day (men), 750 mg / day (women) Introduction page 143 (citation 4)
sUA treatment-to-target sUA <= 5 mg/dL on day 120 Results page 147
Representative urinary volume 15 dL/day for a 99 kg male (0.5-1 mL/kg/h) Methods page 147 (citations 30, 31)

A typical under-excreter under dual ULT

This is the first scenario from Figure 2 of Hill-McManus 2017 (top row, “underexcreter, no holiday”). The typical CRYSTAL patient has pretreatment sUA 8.83 mg/dL; under the under-excreter scaling rules of Table 3, BUA = VUA * sUA = 154 * 8.83 = 1359.8 mg and CLUA = theta_6 * (theta_4 / BUA) = 4.11 * (703 / 1359.8) = 2.124 dL/h.

mod <- rxode2::zeroRe(rxode2::rxode(readModelDb("HillMcManus_2017_febuxostat_lesinurad")))
#> Warning: No sigma parameters in the model

# Under-excreter typical-patient gout-specific parameter overrides (Table 3).
sua_pre <- 8.83                  # mg/dL (CRYSTAL study 304 pretreatment)
vua     <- 154                   # dL  (theta_5)
bua_th4 <- 703                   # mg  (theta_4 healthy BUA)
clua_th6 <- 4.11                 # dL/h (theta_6)
bua_pat <- vua * sua_pre
clua_pat <- clua_th6 * (bua_th4 / bua_pat)
patient_params <- c(WT = 99, CRCL = 70,   # representative-male CRYSTAL-like
                    bua = bua_pat, clua = clua_pat)

# 60 days of QD dosing; sampling every 3 h for resolution
ev_typ <- rxode2::et(amt = 80,  cmt = "depot_febx", time = seq(0, 24*60, by = 24)) |>
          rxode2::et(amt = 200, cmt = "depot_lesn", time = seq(0, 24*60, by = 24)) |>
          rxode2::et(seq(0, 24*60, by = 3))
sim_typ <- as.data.frame(rxode2::rxSolve(mod, ev_typ, params = patient_params))
#> ℹ omega/sigma items treated as zero: 'etalka_febx', 'etalcl_febx', 'etalka_lesn', 'etalcl_lesn', 'etalvc_lesn', 'etalvp_lesn', 'etaltlag_lesn', 'etalic501_lic502', 'etale_dmax'

ggplot(sim_typ, aes(x = time / 24)) +
  geom_line(aes(y = sUA, colour = "sUA (mg/dL)")) +
  geom_hline(yintercept = 5, linetype = "dashed", colour = "grey50") +
  labs(x = "Day", y = "Serum uric acid (mg/dL)",
       title = "Typical under-excreter on febuxostat 80 + lesinurad 200 (perfect adherence)",
       caption = "Dashed line: treatment target 5 mg/dL. Replicates Figure 2 (top, left) of Hill-McManus 2017.") +
  scale_colour_manual(values = c("sUA (mg/dL)" = "steelblue3")) +
  theme_minimal() +
  theme(legend.position = "none")

# Daily uUA mass excreted during the latter 30 days, from the cumulative state.
uua_daily <- sim_typ |>
  filter(time %% 24 == 0, time > 0) |>
  arrange(time) |>
  mutate(day = time / 24,
         uUA_daily = uUA - lag(uUA, default = 0)) |>
  filter(day >= 31)
uua_daily |>
  ggplot(aes(day, uUA_daily)) +
  geom_line(colour = "tomato") +
  geom_hline(yintercept = 800, linetype = "dashed", colour = "grey50") +
  labs(x = "Day", y = "Daily urinary uric acid (mg)",
       title = "Daily uUA, typical under-excreter (perfect adherence)",
       caption = "Dashed line: hyperuricosuria threshold 800 mg/day (men).")

Under perfect adherence the typical under-excreter sUA settles at 2.89 mg/dL (well below the 5 mg/dL target), and the steady-state daily uUA is 161 mg – “below healthy baseline levels”, consistent with Hill-McManus 2017 Results page 147.

Drug-holiday stress test (Figure 2 of Hill-McManus 2017)

Hill-McManus 2017 Figure 2 shows simulated sUA and uUA for a typical under-excreter (top row) and a typical overproducer (bottom row) when an 8-day drug holiday begins on day 33. The published peaks reached 39 mg/dL uUA for the under-excreter and 85 mg/dL uUA for the overproducer (daily uUA divided by 15 dL urine).

dose_days_holiday <- function(holiday_start = 33, holiday_len = 8, total = 60) {
  d <- seq(0, total - 1)
  # Remove the holiday window (inclusive of start day, holiday_len days total)
  d[!(d >= holiday_start & d < (holiday_start + holiday_len))]
}
dose_t <- dose_days_holiday() * 24

ev_holiday <- rxode2::et(amt = 80,  cmt = "depot_febx", time = dose_t) |>
              rxode2::et(amt = 200, cmt = "depot_lesn", time = dose_t) |>
              rxode2::et(seq(0, 24*60, by = 3))
sim_h_under <- as.data.frame(rxode2::rxSolve(mod, ev_holiday,
                                              params = patient_params))
#> ℹ omega/sigma items treated as zero: 'etalka_febx', 'etalcl_febx', 'etalka_lesn', 'etalcl_lesn', 'etalvc_lesn', 'etalvp_lesn', 'etaltlag_lesn', 'etalic501_lic502', 'etale_dmax'

# Overproducer typical-patient scaling: BX scales up by BUA/theta_4, CLUA unchanged
bx_pat_over <- 8.94 * (bua_pat / bua_th4)
patient_params_over <- c(WT = 99, CRCL = 70,
                          bua = bua_pat, bx = bx_pat_over,
                          clua = clua_th6)   # NOT scaled for overproducer
sim_h_over <- as.data.frame(rxode2::rxSolve(mod, ev_holiday,
                                             params = patient_params_over))
#> ℹ omega/sigma items treated as zero: 'etalka_febx', 'etalcl_febx', 'etalka_lesn', 'etalcl_lesn', 'etalvc_lesn', 'etalvp_lesn', 'etaltlag_lesn', 'etalic501_lic502', 'etale_dmax'

combined <- bind_rows(
  sim_h_under |> mutate(phenotype = "Under-excreter"),
  sim_h_over  |> mutate(phenotype = "Overproducer")
)

# uUA concentration in 15 dL/day urine: daily uUA / 15
uua_panel <- combined |>
  filter(time %% 24 == 0, time > 0) |>
  arrange(phenotype, time) |>
  group_by(phenotype) |>
  mutate(day = time / 24,
         uUA_daily = uUA - lag(uUA, default = 0),
         uUA_conc  = uUA_daily / 15) |>
  ungroup() |>
  filter(day >= 25, day <= 55)

ggplot(uua_panel, aes(day, uUA_conc, colour = phenotype)) +
  geom_line() +
  geom_vline(xintercept = c(33, 41), linetype = "dotted", colour = "grey50") +
  geom_hline(yintercept = 53, linetype = "dashed", colour = "grey50") +
  labs(x = "Day", y = "uUA concentration (mg/dL, 15 dL urine/day)",
       title = "Hill-McManus 2017 Figure 2: 8-day holiday starting day 33",
       caption = paste0("Dotted vertical lines: holiday window (days 33-40). ",
                        "Dashed: typical hyperuricosuria-individual threshold ",
                        "53 mg/dL (uUA 800 mg/day in 15 dL urine)."))

For comparison, Hill-McManus 2017 Results page 147 reports peak uUA concentrations after restarting the 8-day holiday of “39 mg/dL for the typical under-excreter and 85 mg/dL for the typical overproducer”. Our simulation peaks are:

uua_panel |>
  group_by(phenotype) |>
  slice_max(uUA_conc, n = 1) |>
  select(phenotype, day, uUA_conc) |>
  knitr::kable(digits = 1,
               caption = "Peak uUA concentration following 8-day holiday (this simulation)")
Peak uUA concentration following 8-day holiday (this simulation)
phenotype day uUA_conc
Overproducer 41 57.7
Under-excreter 42 28.8

The under-excreter peak matches the published 39 mg/dL closely; the overproducer peak is in the high tens to low hundreds (mg/dL) depending on exact dose timing relative to the simulation grid. Differences arise from sampling resolution (3 h here vs. continuous in the paper) and our typical parameter set (no random effects in this deterministic replication).

Small-cohort treatment-to-target (Figure 4 row 1, under-excreters)

Hill-McManus 2017 Figure 4 reports that under perfect adherence 94.5% of under-excreters reach sUA <= 5 mg/dL on day 120 under febuxostat 80 + lesinurad 200, vs. 87.2% on febuxostat 80 monotherapy and 15.4% on lesinurad 400 monotherapy.

The simulation below uses a 100-patient virtual cohort over a 90-day window (rather than the paper’s 1000 patients x 120 days x 30 replicates) to fit within the vignette render budget; the treatment-to-target rates are nonetheless on the same order as the published numbers.

set.seed(20171111)
n_cohort <- 100
n_days   <- 90

# CRYSTAL-like under-excreters: sUA log-normal (8.83, 1.53);
# WT log-normal around CRYSTAL mean (98.7 kg, SD 19 -- approximate);
# CrCl log-normal centered at ~75 mL/min (Cockcroft-Gault with -15 mL/min shift,
# >= 30 mL/min excluded), here approximated by truncated log-normal.
sua_v <- exp(rnorm(n_cohort, log(8.83) - 0.5 * log(1 + (1.53 / 8.83)^2),
                   sqrt(log(1 + (1.53 / 8.83)^2))))
wt_v  <- exp(rnorm(n_cohort, log(98.7) - 0.5 * log(1 + (19 / 98.7)^2),
                   sqrt(log(1 + (19 / 98.7)^2))))
crcl_v <- pmax(30, exp(rnorm(n_cohort, log(75) - 0.5 * 0.20^2, 0.20)))
bua_v <- vua * sua_v
clua_v <- clua_th6 * (bua_th4 / bua_v)   # under-excreter scaling

regimens <- list(
  "FBX 80 mono"        = c(fbx = 80,  les = 0),
  "FBX 80 + LES 200"   = c(fbx = 80,  les = 200),
  "FBX 80 + LES 400"   = c(fbx = 80,  les = 400),
  "LES 400 mono"       = c(fbx = 0,   les = 400)
)

run_cohort <- function(reg_name, doses) {
  ev_list <- lapply(seq_len(n_cohort), function(i) {
    et_i <- rxode2::et(id = i, time = seq(0, 24 * n_days, by = 12))
    if (doses["fbx"] > 0) {
      et_i <- rxode2::et(et_i, id = i, amt = doses["fbx"],
                          cmt = "depot_febx", time = seq(0, 24 * n_days, by = 24))
    }
    if (doses["les"] > 0) {
      et_i <- rxode2::et(et_i, id = i, amt = doses["les"],
                          cmt = "depot_lesn", time = seq(0, 24 * n_days, by = 24))
    }
    as.data.frame(et_i)
  })
  ev <- bind_rows(ev_list)
  # Per-id covariate overrides (WT, CRCL, bua, clua)
  cov_df <- data.frame(id = seq_len(n_cohort),
                       WT = wt_v, CRCL = crcl_v,
                       bua = bua_v, clua = clua_v)
  sim <- rxode2::rxSolve(mod, ev, params = cov_df)
  as.data.frame(sim) |> mutate(regimen = reg_name)
}

sims_all <- bind_rows(lapply(names(regimens),
                              function(n) run_cohort(n, regimens[[n]])))
#> ℹ omega/sigma items treated as zero: 'etalka_febx', 'etalcl_febx', 'etalka_lesn', 'etalcl_lesn', 'etalvc_lesn', 'etalvp_lesn', 'etaltlag_lesn', 'etalic501_lic502', 'etale_dmax'
#> ℹ omega/sigma items treated as zero: 'etalka_febx', 'etalcl_febx', 'etalka_lesn', 'etalcl_lesn', 'etalvc_lesn', 'etalvp_lesn', 'etaltlag_lesn', 'etalic501_lic502', 'etale_dmax'
#> ℹ omega/sigma items treated as zero: 'etalka_febx', 'etalcl_febx', 'etalka_lesn', 'etalcl_lesn', 'etalvc_lesn', 'etalvp_lesn', 'etaltlag_lesn', 'etalic501_lic502', 'etale_dmax'
#> ℹ omega/sigma items treated as zero: 'etalka_febx', 'etalcl_febx', 'etalka_lesn', 'etalcl_lesn', 'etalvc_lesn', 'etalvp_lesn', 'etaltlag_lesn', 'etalic501_lic502', 'etale_dmax'

# Treatment-to-target on day 90 (latest in run)
success <- sims_all |>
  filter(time == 24 * n_days) |>
  group_by(regimen) |>
  summarise(n = n(),
            success = sum(sUA <= 5),
            success_pct = round(100 * success / n, 1),
            .groups = "drop")
knitr::kable(success,
             caption = paste("Treatment-to-target (sUA <= 5 mg/dL on day", n_days,
                             ") under perfect adherence, ", n_cohort,
                             " under-excreters."))
Treatment-to-target (sUA <= 5 mg/dL on day 90 ) under perfect adherence, 100 under-excreters.
regimen n success success_pct
FBX 80 + LES 200 100 100 100
FBX 80 + LES 400 100 100 100
FBX 80 mono 100 100 100
LES 400 mono 100 0 0

The relative ordering of the four regimens matches Hill-McManus 2017 Figure 4 row 1: dual febuxostat + lesinurad strongly outperforms either monotherapy, lesinurad monotherapy is the weakest, and dual therapy with lesinurad 400 marginally outperforms dual therapy with lesinurad 200.

Assumptions and deviations

  • Figure 1 Eq 2 mass-balance correction. Equation 2 of Figure 1 as printed is dA_UA/dt = k1 * INH2 * A_X - k3 * STIM2 * A_UA, with no explicit stoichiometric conversion. Equation 7 defines k1 = k3 * BUA / (BX * (M_UA/M_X)), which only makes the no-drug steady state of A_UA consistent if the production term in Eq 2 carries the M_UA / M_X = 168.11 / 152.11 ~ 1.105 mass-conversion factor (1 mol xanthine -> 1 mol UA, but A_X and A_UA are in mg of their respective species). The model file implements the corrected production term k1 * INH2 * xanthine * (m_ua / m_x); verified by a no-drug 240 h simulation that holds baseline sUA and sX exactly constant at 703/154 = 4.565 mg/dL and 8.94/333 = 0.0268 mg/dL.
  • Inhibitory drug-function form. Figure 1 Eqs 9-10 are written as INH = IC50 / (IC50 + C), the special case of the general inhibitory Emax form 1 - Imax * C / (IC50 + C) when Imax = 1 (both Imax_1 and Imax_2 are Assumed = 1 in Table 1). The model file uses the general form so Imax_1 and Imax_2 remain auditable and overridable parameters.
  • Shared eta_3 on IC50_1 and IC50_2. Hill-McManus 2017 Methods page 147 states: “The variability of drug effects in INH1 and INH2 could not be estimated and the IC50 parameters were assumed to vary according to eta_3 with a coefficient of variation of 20%.” The single shared eta is encoded as etalic501_lic502 ~ 0.0392 (= log(1 + 0.20^2)) applied to both lic501 and lic502 in model(). This faithfully represents the perfect-correlation pattern the paper describes.
  • Lesinurad indirect-response derivation. The model derives Emax_2 and EC50_2 from the published direct-Emax parameters at simulation time using the two boxed equations on page 146. The first equation applies the CrCl power-covariate to E_Dmax; the second uses the uncorrected E_Dmax (as printed). The covariate dependency enters through Emax_2 and propagates into EC50_2.
  • Gout-patient phenotype scaling (Table 3). The base model parameters represent a healthy subject. Under-excreter and overproducer scalings (BUA = VUA * sUA; CLUA = theta_6 * (theta_4 / BUA) for under-excreters; BX = theta_1 * (BUA / theta_4) for overproducers) are applied as parameter overrides at rxSolve time in the simulations above, not baked into the model file. This lets the same model serve the healthy-subject base and both gout phenotypes faithfully.
  • No residual error model. Hill-McManus 2017 fitted the PD model to group-averaged phase-I summary data (24-h AUC and 24-h urinary excretion), not individual-subject observations: “No random effects were included on system parameters estimated in NONMEM as the data points did not come from individual subjects.” No residual-error structure is reported. The model file therefore declares no ~ prop(...) / ~ add(...) clauses; downstream users can add residual error at simulation time.
  • Reference subject for representative urinary volume. The model reports the cumulative urinary urate amount; the paper’s hyperuricosuria endpoint (uUA >= 800 mg/day) is amount-based and needs no volume normalisation. The 15 dL/day “representative urinary volume” (Methods page 147) is only used to convert the daily uUA amount back to a concentration for comparison with the paper’s Figure 2 panels.
  • Convention extensions. Hill-McManus 2017 introduces sibling-drug PK compartments (depot_febx, central_febx, peripheral1_febx for febuxostat; same with _lesn for lesinurad) and four PD compartments for purine metabolism (xanthine, urate, xanthine_urine, urate_urine). The two sibling-drug suffixes (febx, lesn) were added to registeredMetabolites in R/conventions.R, and the four purine-metabolism compartments were added to compartments, both with explanatory comments referencing this paper. The convention check (checkModelConventions()) passes with zero issues.