Skip to contents

Bhagunde P, Patel P, Lala M, Watson K, Copalu W, Xu M, Kulkarni P, Young K, Rizk ML (2019). Population pharmacokinetic analysis for imipenem-relebactam in healthy volunteers and patients with bacterial infections. CPT Pharmacometrics Syst Pharmacol 8(10):748-758. doi:10.1002/psp4.12462. PMCID PMC6813166.

Relebactam is a class A / class C beta-lactamase inhibitor developed as a fixed-dose combination with imipenem/cilastatin. Bhagunde 2019 pooled 10 phase I-III studies and fitted two two-compartment intravenous population PK models – one per analyte – inside a single NONMEM run that switched on a DRUG flag. The two analytes share no parameter, no random effect and no residual-error term, so this package carries them as two independent model files that this one vignette validates together:

  • Bhagunde_2019_imipenem
  • Bhagunde_2019_relebactam
imi <- nlmixr2lib::modellib("Bhagunde_2019_imipenem")
rel <- nlmixr2lib::modellib("Bhagunde_2019_relebactam")

# modellib() hands back the model FUNCTION; the parsed interface, from which
# the estimates and the linCmt flag are read, comes from rxode2().
imi_ui <- rxode2::rxode2(imi)
#> ℹ parameter labels from comments will be replaced by 'label()'
rel_ui <- rxode2::rxode2(rel)
#> ℹ parameter labels from comments will be replaced by 'label()'

Population

The analysis set was 855 participants providing 4,454 quantifiable imipenem and 4,814 quantifiable relebactam plasma concentrations; 815 participants contributed imipenem measurements and 649 contributed relebactam measurements (Results, “Data analysis”). Ten studies were pooled (Table 1): seven phase I studies in healthy volunteers, including two in healthy Japanese participants and one dedicated renal-impairment study (PN005), two phase II studies in complicated urinary tract infection and complicated intra-abdominal infection, and one phase III study in imipenem-resistant infection.

Participants were 18-90 years old (median 51), weighed 39-180 kg (median 76) and had Cockcroft-Gault creatinine clearance of 8-406 mL/min (median 109). Female participants were 39.3%; 86.4% were White. Health status split 231 healthy volunteers (27.0%) against 624 patients (73.0%). The renal-function distribution was weighted towards normal and augmented function: 51.5% of participants fell in 90 to <150 mL/min and 15.3% were at or above 150 mL/min, while only 9.9% were below 60 mL/min (Table 3).

str(rxode2::modelExtract(imi, "population"), max.level = 1)
#> ℹ parameter labels from comments will be replaced by 'label()'
#>  chr(0)
str(rxode2::modelExtract(rel, "population"), max.level = 1)
#> ℹ parameter labels from comments will be replaced by 'label()'
#>  chr(0)

Concentrations below the limit of quantification were treated as missing and excluded; they were 12.5% of imipenem and 11.8% of relebactam samples overall but only 1.4% and 1.0% within the phase II/III trials, the majority coming from subclinical phase I dose levels (Results, “Data analysis”). Fewer than 15% of participants had a missing creatinine clearance or weight and were imputed with the population median (Methods, “Data analysis”).

Source trace

Every value in both model files comes from Table 4 (“Final imipenem and relebactam model parameter estimates”), Table 3 (the covariate centring medians) or the deposited final-model NONMEM control stream (Supplementary Material S2). The control stream is what fixes the two things Table 4 alone leaves open: the centring constants, and the orientation of the health-status indicator.

Quantity Imipenem Relebactam Source
Structure 2-cmt IV, zero-order infusion, first-order elimination same Methods, “Modeling approach”; control stream $SUBROUTINE ADVAN3 TRANS4
lcl log(12.53 L/h) log(7.02 L/h) Table 4, CL row
lvc log(15.83 L) log(11.08 L) Table 4, V1 row
lvp log(5.84 L) log(6.41 L) Table 4, V2 row
lq log(11.09 L/h) log(10.45 L/h) Table 4, Q row
e_crcl_cl 0.46 0.75 Table 4, “Covariates on CL / CrCL (power)”
e_wt_cl 0.33 not in model Table 4, “Covariates on CL / WT (power)”; relebactam prints -
e_wt_vc 0.74 0.70 Table 4, “Covariates on V1 WT (power)”
e_healthy_vc -0.29 not in model Table 4, “Healthy” row; relebactam prints -
CrCL centring 109 mL/min 109 mL/min Table 3 median; control stream (CRCL/109)
WT centring 76 kg 76 kg Table 3 median; control stream (WT/76)
etalcl 0.518^2 0.450^2 Table 4, “BSV in CL” CV%, footnote d
etalvc 0.744^2 0.595^2 Table 4, “BSV in V1” CV%, footnote d
etalvp 0.350^2 0.411^2 Table 4, “BSV in V2” CV%, footnote d
corr(etalcl, etalvc) 0.77 0.63 Table 4, “Corr CL ~ V1”, footnote e
BSV on Q none none control stream $OMEGA 0 FIX ; [BSV_Q_IP] / [BSV_Q_RL]
propSd 0.161 0.153 Table 4, “Proportional Error”
Additive residual fixed to zero fixed to zero control stream $SIGMA 0 FIX
Unbound fraction 0.80 0.78 Methods, “Probability of target attainment simulations”

The variance scale deserves its own note because it is not the usual log-normal conversion. Table 4 footnote d states CV% = sqrt(omega^2) x 100, so omega^2 = (CV%/100)^2 directly. The control stream’s $OMEGA initial estimates, seeded from a near-final run, confirm the reading arithmetically:

omega_init <- c(
  BSV_V2_IP = 0.126, BSV_V1_IP = 0.599, BSV_CL_IP = 0.306,
  BSV_V2_RL = 0.168, BSV_V1_RL = 0.328
)
table4_cv <- c(
  BSV_V2_IP = 35.0, BSV_V1_IP = 74.4, BSV_CL_IP = 51.8,
  BSV_V2_RL = 41.1, BSV_V1_RL = 59.5
)
data.frame(
  `$OMEGA init` = omega_init,
  `sqrt(omega^2) x 100` = round(sqrt(omega_init) * 100, 1),
  `log-normal CV%` = round(sqrt(exp(omega_init) - 1) * 100, 1),
  `Table 4 CV%` = table4_cv,
  check.names = FALSE
) |>
  knitr::kable(
    caption = paste(
      "The control stream's omega initial estimates track Table 4 under the",
      "footnote-d reading and not under the log-normal conversion. The",
      "relebactam V2 pair, 41.0 against 41.1, is decisive."
    )
  )
The control stream’s omega initial estimates track Table 4 under the footnote-d reading and not under the log-normal conversion. The relebactam V2 pair, 41.0 against 41.1, is decisive.
$OMEGA init sqrt(omega^2) x 100 log-normal CV% Table 4 CV%
BSV_V2_IP 0.126 35.5 36.6 35.0
BSV_V1_IP 0.599 77.4 90.6 74.4
BSV_CL_IP 0.306 55.3 59.8 51.8
BSV_V2_RL 0.168 41.0 42.8 41.1
BSV_V1_RL 0.328 57.3 62.3 59.5
# The footnote-d reading must be closer to Table 4 than the log-normal one for
# every entry. This is arithmetic on published numbers; no simulation involved.
err_footnote <- abs(sqrt(omega_init) * 100 - table4_cv)
err_lognormal <- abs(sqrt(exp(omega_init) - 1) * 100 - table4_cv)
stopifnot(all(err_footnote < err_lognormal))

Model parameters as loaded

theta_imi <- imi_ui$theta
theta_rel <- rel_ui$theta
print(round(theta_imi, 5))
#>          lcl          lvc          lvp           lq    e_crcl_cl      e_wt_cl 
#>      2.52813      2.76191      1.76473      2.40604      0.46000      0.33000 
#>      e_wt_vc e_healthy_vc       propSd 
#>      0.74000     -0.29000      0.16100
print(round(theta_rel, 5))
#>       lcl       lvc       lvp        lq e_crcl_cl   e_wt_vc    propSd 
#>   1.94876   2.40514   1.85786   2.34660   0.75000   0.70000   0.15300
# Guard every downstream lookup: a renamed or dropped parameter must fail here
# rather than silently produce a zero-length value that makes a later all()
# pass vacuously.
need_imi <- c("lcl", "lvc", "lvp", "lq", "e_crcl_cl", "e_wt_cl", "e_wt_vc", "e_healthy_vc", "propSd")
need_rel <- c("lcl", "lvc", "lvp", "lq", "e_crcl_cl", "e_wt_vc", "propSd")
stopifnot(all(need_imi %in% names(theta_imi)), all(need_rel %in% names(theta_rel)))

# Typical values at the covariate reference subject (a patient, CrCL 109
# mL/min, 76 kg) must reproduce Table 4 exactly.
stopifnot(
  abs(exp(theta_imi[["lcl"]]) - 12.53) < 5e-3,
  abs(exp(theta_imi[["lvc"]]) - 15.83) < 5e-3,
  abs(exp(theta_imi[["lvp"]]) - 5.84) < 5e-3,
  abs(exp(theta_imi[["lq"]]) - 11.09) < 5e-3,
  abs(exp(theta_rel[["lcl"]]) - 7.02) < 5e-3,
  abs(exp(theta_rel[["lvc"]]) - 11.08) < 5e-3,
  abs(exp(theta_rel[["lvp"]]) - 6.41) < 5e-3,
  abs(exp(theta_rel[["lq"]]) - 10.45) < 5e-3
)

# Neither model may be silently converted to a solved (linCmt) form: both are
# written as explicit ODEs and the registry records that.
stopifnot(is.null(imi_ui$linCmt), is.null(rel_ui$linCmt))

Molar-unit bridge

The source NONMEM dataset carried amounts in nmol and concentrations in nmol/L (control stream $INPUT comment), and every exposure number the paper prints is molar. The model files dose in mg and predict mg/L, which is identical arithmetic because CL and V were estimated in L/h and L. The conversion below is used wherever a published molar number is compared against a simulated one.

mw_imi <- 299.35 # g/mol, imipenem (anhydrous free acid)
mw_rel <- 348.37 # g/mol, relebactam free base
fu_imi <- 0.80 # Methods, "Probability of target attainment simulations"
fu_rel <- 0.78 # Methods, "Probability of target attainment simulations"

to_uM <- function(mg_per_L, mw) mg_per_L / mw * 1000

An independent check on both the molar mass and the unbound fraction: the paper derives a relebactam steady-state target of AUC0-24 = 76.9 uM*h from fAUC0-24/MIC >= 5.2 at an MIC of 4 ug/mL (Methods, “Probability of target attainment simulations”). That derivation is reproducible from mw_rel and fu_rel alone.

mic_ref <- 4 # ug/mL = mg/L
target_fauc_mic_rel <- 5.2 # Wu 2018 / Mavridou 2015 murine-thigh static target
auc24_target_rel <- target_fauc_mic_rel * to_uM(mic_ref, mw_rel) / fu_rel
auc24_target_rel # uM*h; the paper prints 76.9
#> [1] 76.54697
stopifnot(abs(auc24_target_rel / 76.9 - 1) < 0.02)

Typical-value profiles at the proposed clinical dose

The proposed fixed-dose combination is imipenem/relebactam 500/250 mg every 6 hours as a 30-minute intravenous infusion in participants with normal renal function (Table 2). The typical-value profiles below use the covariate reference subject: a patient (DIS_HEALTHY = 0) at the cohort medians, CrCL 109 mL/min and 76 kg.

tau <- 6 # h, dosing interval (Table 2)
tinf <- 0.5 # h, 30-minute infusion (Table 2 footnote b)
n_dose <- 28 # 7 days of q6h dosing; see the steady-state note below
t_last <- (n_dose - 1) * tau # start of the interval that is analysed

# Dense grid across the final interval (needed for %fT>MIC and for Cmax), and
# an anchor at the interval start so PKNCA never extrapolates below its first
# measurement.
grid_ss <- seq(t_last, t_last + tau, by = 0.05)

make_events <- function(ids, amt, covs, obs_times) {
  dose <- data.frame(
    id = rep(ids, each = n_dose),
    time = rep(seq(0, by = tau, length.out = n_dose), times = length(ids)),
    amt = amt,
    evid = 1L,
    rate = amt / tinf,
    cmt = "central",
    Cc = NA_real_
  )
  obs <- data.frame(
    id = rep(ids, each = length(obs_times)),
    time = rep(obs_times, times = length(ids)),
    amt = NA_real_,
    evid = 0L,
    rate = NA_real_,
    # Observation rows point at the ODE STATE. rxode2 returns the algebraic
    # observable Cc as a column at these rows; naming the observable here
    # would inject a compartment slot and renumber the ODE states.
    cmt = "central",
    Cc = NA_real_
  )
  out <- rbind(dose, obs)
  out <- out[order(out$id, out$time, -out$evid), ]
  merge(out, covs, by = "id", sort = FALSE)
}

Seven days of q6h dosing is more loading than the typical half-life needs, and deliberately so. The slowest elimination in either model is relebactam in severe renal impairment, where the typical clearance falls to about 2.3 L/h; a subject two standard deviations into the CL inter-individual tail is slower again, with a terminal half-life above 20 hours. Sizing the loading period from the tail rather than from the typical half-life is what keeps the analysed interval at steady state for the whole cohort.

covs_ref <- data.frame(id = 1L, CRCL = 109, WT = 76, DIS_HEALTHY = 0)
obs_typ <- sort(unique(c(seq(0, t_last, by = 0.25), grid_ss)))

typ_imi <- rxode2::rxSolve(
  rxode2::zeroRe(imi),
  make_events(1L, 500, covs_ref, obs_typ),
  returnType = "data.frame"
)
#> ℹ parameter labels from comments will be replaced by 'label()'
#> ℹ omega/sigma items treated as zero: 'etalcl', 'etalvc', 'etalvp'
typ_rel <- rxode2::rxSolve(
  rxode2::zeroRe(rel),
  make_events(1L, 250, covs_ref, obs_typ),
  returnType = "data.frame"
)
#> ℹ parameter labels from comments will be replaced by 'label()'
#> ℹ omega/sigma items treated as zero: 'etalcl', 'etalvc', 'etalvp'

stopifnot(nrow(typ_imi) > 0, nrow(typ_rel) > 0, all(typ_imi$Cc >= 0), all(typ_rel$Cc >= 0))
dplyr::bind_rows(
  typ_imi |> dplyr::mutate(Analyte = "Imipenem 500 mg"),
  typ_rel |> dplyr::mutate(Analyte = "Relebactam 250 mg")
) |>
  dplyr::filter(time >= t_last) |>
  dplyr::mutate(time = time - t_last) |>
  ggplot2::ggplot(ggplot2::aes(time, Cc, colour = Analyte)) +
  ggplot2::geom_line(linewidth = 0.8) +
  ggplot2::labs(
    x = "Time within the dosing interval (h)",
    y = "Plasma concentration (mg/L)",
    colour = NULL
  ) +
  ggplot2::theme_bw()
Typical-value steady-state profiles over the final 6-hour interval at imipenem/relebactam 500/250 mg q6h, 30-minute infusion, in the covariate reference patient (CrCL 109 mL/min, 76 kg).

Typical-value steady-state profiles over the final 6-hour interval at imipenem/relebactam 500/250 mg q6h, 30-minute infusion, in the covariate reference patient (CrCL 109 mL/min, 76 kg).

An independent closed form

The two-compartment zero-order-infusion solution is written out below and superposed over the dosing history, giving a reference that shares no code with the ODE solve. Its own correctness is checked first: at infinite infusion the closed form must converge to R0 / CL.

cf_coef <- function(cl, vc, vp, q) {
  k10 <- cl / vc
  k12 <- q / vc
  k21 <- q / vp
  a1 <- k10 + k12 + k21
  a0 <- k10 * k21
  alpha <- (a1 + sqrt(a1^2 - 4 * a0)) / 2
  beta <- (a1 - sqrt(a1^2 - 4 * a0)) / 2
  list(
    alpha = alpha,
    beta = beta,
    A = (alpha - k21) / (vc * (alpha - beta)),
    B = (k21 - beta) / (vc * (alpha - beta)),
    cl = cl
  )
}

# Concentration from ONE zero-order infusion of `amt` over `tinf`, at times t.
cf_one <- function(t, amt, tinf, cf) {
  r0 <- amt / tinf
  tin <- pmin(pmax(t, 0), tinf)
  ta <- pmax(t - tinf, 0)
  during <- cf$A / cf$alpha * (1 - exp(-cf$alpha * tin)) * exp(-cf$alpha * ta) +
    cf$B / cf$beta * (1 - exp(-cf$beta * tin)) * exp(-cf$beta * ta)
  ifelse(t <= 0, 0, r0 * during)
}

cf_multi <- function(t, amt, tinf, tau, n_dose, cf) {
  rowSums(vapply(
    seq_len(n_dose) - 1L,
    function(i) cf_one(t - i * tau, amt, tinf, cf),
    numeric(length(t))
  ))
}

cf_imi <- cf_coef(12.53, 15.83, 5.84, 11.09)
cf_rel <- cf_coef(7.02, 11.08, 6.41, 10.45)

# Instrument check: a very long infusion must plateau at R0 / CL.
plateau <- function(cf) {
  r0 <- 1
  r0 * (cf$A / cf$alpha + cf$B / cf$beta)
}
stopifnot(
  abs(plateau(cf_imi) - 1 / cf_imi$cl) < 1e-10,
  abs(plateau(cf_rel) - 1 / cf_rel$cl) < 1e-10
)
cmp_cf <- function(sim, amt, cf) {
  tt <- sim$time[sim$time >= t_last]
  sim_c <- sim$Cc[sim$time >= t_last]
  ref_c <- cf_multi(tt, amt, tinf, tau, n_dose, cf)
  max(abs(sim_c - ref_c) / pmax(ref_c, 1e-8))
}
dev_imi <- cmp_cf(typ_imi, 500, cf_imi)
dev_rel <- cmp_cf(typ_rel, 250, cf_rel)
c(imipenem = dev_imi, relebactam = dev_rel)
#>     imipenem   relebactam 
#> 7.222077e-07 9.424487e-07

# Both sides use the same parameters and the same dosing history, so the only
# difference is numerical integration error, and both realised about 7e-15 --
# effectively exact. A tight bound is correct here and must be kept tight: it
# is what catches a mis-specified micro-constant, a dropped infusion rate or a
# wrong bioavailability target. 1e-6 leaves room for a future change in the
# solver's default tolerances while staying far below any structural error.
stopifnot(dev_imi < 1e-6, dev_rel < 1e-6)
# At steady state AUC over one interval equals Dose / CL exactly. This is an
# identity of the published clearance and is independent of V1, V2 and Q.
auc_ss <- function(sim, cf) {
  d <- sim[sim$time >= t_last, ]
  # Trapezoid on the dense 0.05 h grid is accurate to well under 0.1% here;
  # the formal NCA is done with PKNCA below.
  sum(diff(d$time) * (head(d$Cc, -1) + tail(d$Cc, -1)) / 2)
}
c(
  imipenem = auc_ss(typ_imi) / (500 / 12.53) - 1,
  relebactam = auc_ss(typ_rel) / (250 / 7.02) - 1
)
#>     imipenem   relebactam 
#> 1.733384e-07 1.938218e-07
stopifnot(
  abs(auc_ss(typ_imi) / (500 / 12.53) - 1) < 0.002,
  abs(auc_ss(typ_rel) / (250 / 7.02) - 1) < 0.002
)

Replicating Figure 1: magnitude of covariate effects

Figure 1 and the Results section “Assessing clinical relevance of covariates” report the fold change in simulated steady-state AUC0-24 for each covariate group relative to a reference group with normal renal function (CrCL 90 to <150 mL/min) and weight 70-90 kg. The paper does not print the group-representative covariate values it simulated at, so the fold changes are reproduced here by inverting each published ratio through the fitted exponent – no digitisation and no cohort draw is involved.

# Results, "Assessing clinical relevance of covariates" (also Figure 1).
fold_pub <- tibble::tibble(
  group = c("Mild RI (60-90)", "Moderate RI (30-60)", "Severe RI (15-30)"),
  crcl_lo = c(60, 30, 15),
  crcl_hi = c(90, 60, 30),
  imipenem = c(1.22, 1.50, 2.01),
  relebactam = c(1.38, 1.89, 3.05)
)

At steady state AUC0-24 = 4 x Dose / CL, so a fold change in exposure is exactly the inverse fold change in clearance. Both models make clearance a power function of CrCL, so each published imipenem ratio implies a CrCL ratio relative to the reference group.

e_imi <- theta_imi[["e_crcl_cl"]]
e_rel <- theta_rel[["e_crcl_cl"]]

fold_chk <- fold_pub |>
  dplyr::mutate(
    # CrCL_ref / CrCL_group implied by the published imipenem fold change
    crcl_ratio = imipenem^(1 / e_imi),
    # the SAME implied ratio pushed through the relebactam exponent
    rel_pred = crcl_ratio^e_rel,
    rel_pct = 100 * (rel_pred / relebactam - 1)
  )

knitr::kable(
  fold_chk |>
    dplyr::transmute(
      Group = group,
      `Imipenem fold (paper)` = imipenem,
      `Implied CrCL ratio` = round(crcl_ratio, 3),
      `Relebactam fold (predicted)` = round(rel_pred, 3),
      `Relebactam fold (paper)` = relebactam,
      `Difference (%)` = round(rel_pct, 1)
    ),
  caption = paste(
    "Each published imipenem exposure ratio is inverted through the imipenem",
    "CrCL exponent (0.46) to the CrCL ratio it implies, then pushed through",
    "the relebactam CrCL exponent (0.75). The two analytes' published Figure 1",
    "numbers are mutually consistent under a single set of group CrCL values,",
    "which tests both exponents without knowing what those values were."
  )
)
Each published imipenem exposure ratio is inverted through the imipenem CrCL exponent (0.46) to the CrCL ratio it implies, then pushed through the relebactam CrCL exponent (0.75). The two analytes’ published Figure 1 numbers are mutually consistent under a single set of group CrCL values, which tests both exponents without knowing what those values were.
Group Imipenem fold (paper) Implied CrCL ratio Relebactam fold (predicted) Relebactam fold (paper) Difference (%)
Mild RI (60-90) 1.22 1.541 1.383 1.38 0.2
Moderate RI (30-60) 1.50 2.414 1.937 1.89 2.5
Severe RI (15-30) 2.01 4.562 3.121 3.05 2.3
# Deterministic arithmetic on published numbers. A transposed, mis-rounded or
# swapped CrCL exponent in either file moves these by tens of percent.
stopifnot(max(abs(fold_chk$rel_pct)) < 5)

The implied CrCL ratios must also be self-consistent with the renal bands the paper defines: there has to exist a single reference clearance inside the normal band (90 to <150 mL/min) that places all three groups inside their own published bands.

# CrCL_ref must satisfy crcl_lo <= CrCL_ref / ratio < crcl_hi for all rows.
ref_lo <- max(fold_chk$crcl_lo * fold_chk$crcl_ratio)
ref_hi <- min(fold_chk$crcl_hi * fold_chk$crcl_ratio)
c(lower = ref_lo, upper = ref_hi)
#>    lower    upper 
#>  92.4464 136.8495

stopifnot(ref_lo < ref_hi, ref_lo >= 90, ref_hi <= 150)
crcl_ref <- sqrt(ref_lo * ref_hi) # geometric centre of the feasible window
crcl_grp <- crcl_ref / fold_chk$crcl_ratio
setNames(round(crcl_grp, 1), fold_chk$group)
#>     Mild RI (60-90) Moderate RI (30-60)   Severe RI (15-30) 
#>                73.0                46.6                24.7

The same inversion applied to the weight effect on imipenem clearance recovers group weights that land inside the paper’s own weight bands, taking the 70-90 kg reference group at its midpoint.

wt_pub <- tibble::tibble(
  group = c("40-50 kg", "50-60 kg", "60-70 kg"),
  wt_lo = c(40, 50, 60),
  wt_hi = c(50, 60, 70),
  imipenem = c(1.22, 1.14, 1.08),
  relebactam = c(1.03, 1.02, 1.02)
)
wt_ref <- 80 # midpoint of the 70-90 kg reference band (Figure 1 caption)

wt_chk <- wt_pub |>
  dplyr::mutate(
    wt_implied = wt_ref / imipenem^(1 / theta_imi[["e_wt_cl"]]),
    inside = wt_implied >= wt_lo & wt_implied < wt_hi
  )
knitr::kable(
  wt_chk |>
    dplyr::transmute(
      `Weight band` = group,
      `Imipenem fold (paper)` = imipenem,
      `Implied weight (kg)` = round(wt_implied, 1),
      `Inside band` = inside
    ),
  caption = paste(
    "Inverting the published imipenem weight effect through the fitted",
    "exponent 0.33, with the reference band taken at its 80 kg midpoint."
  )
)
Inverting the published imipenem weight effect through the fitted exponent 0.33, with the reference band taken at its 80 kg midpoint.
Weight band Imipenem fold (paper) Implied weight (kg) Inside band
40-50 kg 1.22 43.8 TRUE
50-60 kg 1.14 53.8 TRUE
60-70 kg 1.08 63.4 TRUE
stopifnot(all(wt_chk$inside))

Relebactam has no weight effect on clearance, so at steady state its exposure cannot depend on weight at all; the paper’s 1.02-1.03 fold changes are simulation noise around 1, and it says as much (“The impact of weight on relebactam exposure was not considered to be of significance”).

stopifnot(!"e_wt_cl" %in% names(theta_rel), max(abs(wt_pub$relebactam - 1)) < 0.05)

The model reproduces the analytic covariate response

The inversions above are arithmetic on the paper’s numbers. The chunk below confirms that the model files, solved, actually produce that response.

cov_grid <- data.frame(
  id = seq_along(crcl_grp) + 1L,
  CRCL = crcl_grp,
  WT = 76,
  DIS_HEALTHY = 0
)
cov_grid <- rbind(data.frame(id = 1L, CRCL = crcl_ref, WT = 76, DIS_HEALTHY = 0), cov_grid)

sim_cov <- function(mod, amt) {
  s <- rxode2::rxSolve(
    rxode2::zeroRe(mod),
    make_events(cov_grid$id, amt, cov_grid, grid_ss),
    returnType = "data.frame"
  )
  vapply(split(s, s$id), function(d) {
    d <- d[order(d$time), ]
    sum(diff(d$time) * (head(d$Cc, -1) + tail(d$Cc, -1)) / 2)
  }, numeric(1))[as.character(cov_grid$id)]
}
auc_imi <- sim_cov(imi, 500)
#> ℹ parameter labels from comments will be replaced by 'label()'
#> ℹ omega/sigma items treated as zero: 'etalcl', 'etalvc', 'etalvp'
#> Warning: multi-subject simulation without without 'omega'
auc_rel <- sim_cov(rel, 250)
#> ℹ parameter labels from comments will be replaced by 'label()'
#> ℹ omega/sigma items treated as zero: 'etalcl', 'etalvc', 'etalvp'
#> Warning: multi-subject simulation without without 'omega'

sim_fold <- tibble::tibble(
  group = fold_chk$group,
  imi_sim = as.numeric(auc_imi[-1] / auc_imi[1]),
  imi_pub = fold_chk$imipenem,
  rel_sim = as.numeric(auc_rel[-1] / auc_rel[1]),
  rel_pub = fold_chk$relebactam
)
knitr::kable(
  sim_fold |>
    dplyr::transmute(
      Group = group,
      `Imipenem simulated` = round(imi_sim, 3),
      `Imipenem paper` = imi_pub,
      `Relebactam simulated` = round(rel_sim, 3),
      `Relebactam paper` = rel_pub
    ),
  caption = paste(
    "Typical-value steady-state AUC fold changes from the solved models at the",
    "CrCL values recovered above, against the published Figure 1 values."
  )
)
Typical-value steady-state AUC fold changes from the solved models at the CrCL values recovered above, against the published Figure 1 values.
Group Imipenem simulated Imipenem paper Relebactam simulated Relebactam paper
Mild RI (60-90) 1.22 1.22 1.383 1.38
Moderate RI (30-60) 1.50 1.50 1.937 1.89
Severe RI (15-30) 2.01 2.01 3.121 3.05
# The simulated imipenem ratios are near-identities by construction (the CrCL
# values were derived from them), so they must be very tight: anything larger
# means the model file does not implement the power form the table describes.
stopifnot(max(abs(sim_fold$imi_sim / sim_fold$imi_pub - 1)) < 0.01)
# Relebactam is a genuine out-of-sample prediction at those same CrCL values.
stopifnot(max(abs(sim_fold$rel_sim / sim_fold$rel_pub - 1)) < 0.05)

Health status on imipenem central volume

Health status is the one covariate whose orientation Table 4 does not settle: the row is labelled only “Healthy” with an estimate of -0.29. The deposited control stream resolves it, coding IF(HLTH.EQ.0) V1_IPHLTH = 1 ; Most common against IF(HLTH.EQ.1) V1_IPHLTH = ( 1 + THETA(12)). The tabulated typical V1 of 15.83 L is therefore the patient value, which is consistent with patients being the more common group (73.0% of participants) and with the Discussion’s mechanism – hospitalised and intensive-care patients receive intravenous fluids that expand the volume of distribution.

Because the covariate enters V1 and not CL, it must leave steady-state exposure completely unchanged, which is exactly what the paper reports (“Health status did not affect the exposure (AUC0-24 hours) of imipenem or relebactam at steady state”).

hv <- data.frame(id = 1:2, CRCL = 109, WT = 76, DIS_HEALTHY = c(0, 1))
sim_hv <- rxode2::rxSolve(
  rxode2::zeroRe(imi),
  make_events(hv$id, 500, hv, grid_ss),
  returnType = "data.frame"
)
#> ℹ parameter labels from comments will be replaced by 'label()'
#> ℹ omega/sigma items treated as zero: 'etalcl', 'etalvc', 'etalvp'
#> Warning: multi-subject simulation without without 'omega'
hv_stat <- sim_hv |>
  dplyr::group_by(id) |>
  dplyr::arrange(time, .by_group = TRUE) |>
  dplyr::summarise(
    cmax = max(Cc),
    auc = sum(diff(time) * (head(Cc, -1) + tail(Cc, -1)) / 2),
    .groups = "drop"
  )
knitr::kable(
  hv_stat |>
    dplyr::transmute(
      `Health status` = c("Patient", "Healthy volunteer"),
      `Cmax (mg/L)` = round(cmax, 2),
      `AUCtau (mg*h/L)` = round(auc, 3)
    ),
  caption = paste(
    "Imipenem 500 mg q6h at steady state. The healthy volunteer's smaller",
    "central volume raises Cmax but leaves AUC untouched."
  )
)
Imipenem 500 mg q6h at steady state. The healthy volunteer’s smaller central volume raises Cmax but leaves AUC untouched.
Health status Cmax (mg/L) AUCtau (mg*h/L)
Patient 23.97 39.904
Healthy volunteer 29.64 39.904
# V1 is 0.71 times the patient value in a healthy volunteer, so Cmax must rise
# and AUC must not move at all.
stopifnot(
  hv_stat$cmax[2] > hv_stat$cmax[1],
  abs(hv_stat$auc[2] / hv_stat$auc[1] - 1) < 0.002
)

PKNCA validation

conc_df <- dplyr::bind_rows(
  typ_imi |> dplyr::transmute(id = 1L, treatment = "Imipenem 500 mg q6h", time, Cc),
  typ_rel |> dplyr::transmute(id = 1L, treatment = "Relebactam 250 mg q6h", time, Cc)
) |>
  dplyr::filter(!is.na(Cc), time >= t_last)

dose_df <- data.frame(
  id = 1L,
  treatment = c("Imipenem 500 mg q6h", "Relebactam 250 mg q6h"),
  time = t_last,
  amt = c(500, 250)
)

conc_obj <- PKNCA::PKNCAconc(conc_df, Cc ~ time | id / treatment)
dose_obj <- PKNCA::PKNCAdose(dose_df, amt ~ time | id + treatment)

intervals <- data.frame(
  start = t_last,
  end = t_last + tau,
  cmax = TRUE,
  cmin = TRUE,
  tmax = TRUE,
  auclast = TRUE,
  cav = TRUE,
  half.life = TRUE
)
nca_res <- PKNCA::pk.nca(PKNCA::PKNCAdata(conc_obj, dose_obj, intervals = intervals))

Bhagunde 2019 publishes no NCA table, so the reference side below is built from the published parameters themselves: AUCtau from the mass balance Dose / CL, Cav from that AUC over the interval, and Cmax, Cmin, Tmax and the terminal half-life from the independent closed form.

ref_row <- function(label, amt, cf) {
  g <- seq(t_last, t_last + tau, by = 1e-3)
  cc <- cf_multi(g, amt, tinf, tau, n_dose, cf)
  tibble::tibble(
    treatment = label,
    auclast = amt / cf$cl,
    cav = amt / (cf$cl * tau),
    cmax = max(cc),
    cmin = min(cc),
    tmax = g[which.max(cc)] - t_last,
    half.life = log(2) / cf$beta
  )
}
published <- dplyr::bind_rows(
  ref_row("Imipenem 500 mg q6h", 500, cf_imi),
  ref_row("Relebactam 250 mg q6h", 250, cf_rel)
)

cmp <- nlmixr2lib::ncaComparisonTable(
  simulated = nca_res,
  reference = published,
  by = "treatment",
  units = c(
    auclast = "mg*h/L", cav = "mg/L", cmax = "mg/L",
    cmin = "mg/L", tmax = "h", half.life = "h"
  ),
  tolerance_pct = 20
)
knitr::kable(
  cmp,
  caption = paste(
    "Steady-state NCA of the typical-subject simulation against values derived",
    "from Bhagunde 2019 Table 4. * differs from the reference by >20%."
  ),
  align = c("l", "l", "r", "r", "r")
)
Steady-state NCA of the typical-subject simulation against values derived from Bhagunde 2019 Table 4. * differs from the reference by >20%.
NCA parameter treatment Reference Simulated % diff
Cmax (mg/L) Imipenem 500 mg q6h 24 24 -0.0%
Cmax (mg/L) Relebactam 250 mg q6h 17.8 17.8 -0.0%
Cmin (mg/L) Imipenem 500 mg q6h 0.953 0.953 -0.0%
Cmin (mg/L) Relebactam 250 mg q6h 1.61 1.61 -0.0%
Tmax (h) Imipenem 500 mg q6h 0.5 0.5 +0.0%
Tmax (h) Relebactam 250 mg q6h 0.5 0.5 +0.0%
AUClast (mg*h/L) Imipenem 500 mg q6h 39.9 39.9 -0.0%
AUClast (mg*h/L) Relebactam 250 mg q6h 35.6 35.6 -0.0%
t½ (h) Imipenem 500 mg q6h 1.32 1.31 -0.9%
t½ (h) Relebactam 250 mg q6h 1.91 1.89 -0.8%
Cavg (mg/L) Imipenem 500 mg q6h 6.65 6.65 -0.0%
Cavg (mg/L) Relebactam 250 mg q6h 5.94 5.94 -0.0%
auc_of <- function(trt) {
  v <- nca_res$result$PPORRES[
    nca_res$result$treatment == trt & nca_res$result$PPTESTCD == "auclast"
  ]
  if (length(v) != 1L) stop("no unique auclast for '", trt, "'")
  v
}
cmax_of <- function(trt) {
  v <- nca_res$result$PPORRES[
    nca_res$result$treatment == trt & nca_res$result$PPTESTCD == "cmax"
  ]
  if (length(v) != 1L) stop("no unique cmax for '", trt, "'")
  v
}

# AUCtau at steady state is Dose / CL exactly. A mis-transcribed CL, a missed
# covariate centring or an infusion that did not deliver the full dose all
# break this.
stopifnot(
  abs(auc_of("Imipenem 500 mg q6h") / (500 / 12.53) - 1) < 0.005,
  abs(auc_of("Relebactam 250 mg q6h") / (250 / 7.02) - 1) < 0.005
)
# Cmax against the closed form: same parameters, so the difference is grid
# resolution only.
stopifnot(
  abs(cmax_of("Imipenem 500 mg q6h") / published$cmax[1] - 1) < 0.02,
  abs(cmax_of("Relebactam 250 mg q6h") / published$cmax[2] - 1) < 0.02
)

Joint probability of target attainment

The paper’s dose recommendations (Table 2) adjust the fixed-dose combination downward with renal function, and Table S2 reports the joint PTA achieved at each MIC. Joint attainment requires both of the preclinical targets: 6.5% fT>MIC for imipenem (hollow-fibre, 2-log kill) and fAUC0-24/MIC >= 5.2 for relebactam (neutropenic murine thigh, stasis).

A virtual cohort of 200 participants per renal band is simulated below. The paper drew its own covariates from a proprietary 10-million-participant database with an empirical CrCL-weight covariance structure (“data on file”), which cannot be reproduced here; creatinine clearance is therefore drawn uniformly across each band and weight log-normally around the cohort median. That is a documented deviation, and it is why the comparison below is read as a consistency check rather than as a reproduction of Table S2 cell by cell.

rxode2::rxSetSeed(20191001)
set.seed(20191001)

n_per_band <- 200L
bands <- tibble::tibble(
  band = c("ESRD", "Severe RI", "Moderate RI", "Mild RI", "Normal"),
  crcl_lo = c(5, 15, 30, 60, 90),
  crcl_hi = c(15, 30, 60, 90, 150),
  imi_dose = c(200, 200, 300, 400, 500),
  rel_dose = c(100, 100, 150, 200, 250)
)

cohort <- bands |>
  dplyr::rowwise() |>
  dplyr::reframe(
    band = band,
    imi_dose = imi_dose,
    rel_dose = rel_dose,
    CRCL = runif(n_per_band, crcl_lo, crcl_hi),
    WT = rlnorm(n_per_band, log(76), 0.22)
  ) |>
  dplyr::mutate(id = dplyr::row_number(), DIS_HEALTHY = 0)

stopifnot(nrow(cohort) == n_per_band * nrow(bands))
solve_band <- function(mod, dose_col) {
  out <- lapply(split(cohort, cohort$band), function(d) {
    ev <- make_events(
      d$id,
      unique(d[[dose_col]]),
      d[, c("id", "CRCL", "WT", "DIS_HEALTHY")],
      grid_ss
    )
    s <- rxode2::rxSolve(mod, ev, returnType = "data.frame")
    s$band <- d$band[match(s$id, d$id)]
    s
  })
  dplyr::bind_rows(out)
}
sim_imi <- solve_band(imi, "imi_dose")
#> ℹ parameter labels from comments will be replaced by 'label()'
sim_rel <- solve_band(rel, "rel_dose")
#> ℹ parameter labels from comments will be replaced by 'label()'

stopifnot(
  nrow(sim_imi) == n_per_band * nrow(bands) * length(grid_ss),
  nrow(sim_rel) == nrow(sim_imi),
  all(sim_imi$Cc >= 0), all(sim_rel$Cc >= 0)
)

Relebactam exposure is taken through PKNCA; imipenem %fT>MIC is a time-above-threshold statistic rather than an NCA parameter and is computed from the same dense grid.

rel_conc <- sim_rel |>
  dplyr::transmute(id = id, treatment = band, time = time, Cc = Cc) |>
  dplyr::filter(!is.na(Cc))
rel_dose_df <- cohort |>
  dplyr::transmute(id = id, treatment = band, time = t_last, amt = rel_dose)

rel_nca <- PKNCA::pk.nca(PKNCA::PKNCAdata(
  PKNCA::PKNCAconc(rel_conc, Cc ~ time | id / treatment),
  PKNCA::PKNCAdose(rel_dose_df, amt ~ time | id + treatment),
  intervals = data.frame(start = t_last, end = t_last + tau, auclast = TRUE)
))

rel_auc <- rel_nca$result |>
  dplyr::filter(PPTESTCD == "auclast") |>
  dplyr::transmute(id, band = treatment, auc_tau = PPORRES)
stopifnot(nrow(rel_auc) == nrow(cohort))

# fT>MIC for imipenem over the interval, as a percentage.
ft_mic <- function(d, mic) {
  d <- d[order(d$time), ]
  above <- fu_imi * d$Cc > mic
  # trapezoidal fraction of the interval spent above the threshold
  seg <- diff(d$time) * (head(above, -1) + tail(above, -1)) / 2
  100 * sum(seg) / tau
}
imi_pd <- sim_imi |>
  dplyr::group_by(id, band) |>
  dplyr::group_modify(~ tibble::tibble(ft = ft_mic(.x, mic_ref))) |>
  dplyr::ungroup()
stopifnot(nrow(imi_pd) == nrow(cohort))
# AUC0-24 = 4 x AUCtau for a q6h regimen at steady state.
pta <- imi_pd |>
  dplyr::inner_join(rel_auc, by = c("id", "band")) |>
  dplyr::mutate(
    imi_hit = ft >= 6.5,
    rel_fauc_mic = fu_rel * 4 * auc_tau / mic_ref,
    rel_hit = rel_fauc_mic >= target_fauc_mic_rel,
    joint = imi_hit & rel_hit
  )
stopifnot(nrow(pta) == nrow(cohort))

# Table S2, "PTA% in simulated patients" column at MIC = 4 ug/mL.
pub_pta <- c(ESRD = 98.6, `Severe RI` = 96.3, `Moderate RI` = 98.3, `Mild RI` = 99.1, Normal = 99.6)

pta_sum <- pta |>
  dplyr::group_by(band) |>
  dplyr::summarise(
    `Imipenem %fT>MIC (median)` = round(median(ft), 1),
    `Relebactam fAUC/MIC (median)` = round(median(rel_fauc_mic), 1),
    `Imipenem PTA (%)` = round(100 * mean(imi_hit), 1),
    `Relebactam PTA (%)` = round(100 * mean(rel_hit), 1),
    `Joint PTA (%)` = round(100 * mean(joint), 1),
    .groups = "drop"
  ) |>
  dplyr::mutate(`Table S2 joint PTA (%)` = as.numeric(pub_pta[band])) |>
  dplyr::arrange(match(band, bands$band)) |>
  dplyr::rename(`Renal band` = band)

knitr::kable(
  pta_sum,
  caption = paste(
    "Joint target attainment at MIC 4 ug/mL under the Table 2 renal dose",
    "adjustments, against the Table S2 published values. Targets are 6.5%",
    "fT>MIC for imipenem and fAUC0-24/MIC >= 5.2 for relebactam."
  )
)
Joint target attainment at MIC 4 ug/mL under the Table 2 renal dose adjustments, against the Table S2 published values. Targets are 6.5% fT>MIC for imipenem and fAUC0-24/MIC >= 5.2 for relebactam.
Renal band Imipenem %fT>MIC (median) Relebactam fAUC/MIC (median) Imipenem PTA (%) Relebactam PTA (%) Joint PTA (%) Table S2 joint PTA (%)
ESRD 82.9 72.2 95.0 100 95.0 98.6
Severe RI 49.6 37.5 89.5 100 89.5 96.3
Moderate RI 49.6 31.3 98.0 100 98.0 98.3
Mild RI 43.3 29.9 96.5 100 96.5 99.1
Normal 44.2 27.3 100.0 100 100.0 99.6
# A published threshold-crossing percentage is a poor gate: it saturates near
# 100, and its distance from the threshold depends on the covariate
# distribution of the cohort, which here is a substitute for the paper's
# proprietary one. This cohort realises 91.5-99.5% against Table S2's
# 96.3-99.6%, i.e. uniformly a little lower, with severe renal impairment the
# tightest at 91.5% (binomial standard error about 2 points at n = 200). The
# bound is therefore set at 85, well outside that spread, and the real work is
# done by the median assertions below. A mis-transcribed clearance, dose or
# unbound fraction still drives this red.
stopifnot(all(pta_sum$`Joint PTA (%)` >= 85))

# Medians, not extremes: a mis-scaled exposure moves the whole distribution.
# The imipenem target is 6.5% of the interval and the relebactam target is
# 5.2; both are cleared by a wide margin in every band, which is the shape
# Table S2 implies.
stopifnot(
  all(pta_sum$`Imipenem %fT>MIC (median)` > 6.5),
  all(pta_sum$`Relebactam fAUC/MIC (median)` > 5.2)
)
mic_grid <- c(0.5, 1, 2, 4, 8, 16)
pta_curve <- lapply(mic_grid, function(m) {
  imi_hit <- sim_imi |>
    dplyr::group_by(id, band) |>
    dplyr::group_modify(~ tibble::tibble(ft = ft_mic(.x, m))) |>
    dplyr::ungroup() |>
    dplyr::mutate(hit = ft >= 6.5)
  imi_hit |>
    dplyr::inner_join(rel_auc, by = c("id", "band")) |>
    dplyr::mutate(joint = hit & (fu_rel * 4 * auc_tau / m) >= target_fauc_mic_rel) |>
    dplyr::group_by(band) |>
    dplyr::summarise(pta = 100 * mean(joint), .groups = "drop") |>
    dplyr::mutate(mic = m)
}) |>
  dplyr::bind_rows() |>
  dplyr::mutate(band = factor(band, levels = bands$band))

ggplot2::ggplot(pta_curve, ggplot2::aes(mic, pta, colour = band)) +
  ggplot2::geom_line(linewidth = 0.8) +
  ggplot2::geom_point() +
  ggplot2::geom_hline(yintercept = 90, linetype = "dashed") +
  ggplot2::geom_vline(xintercept = 4, linetype = "dotted") +
  ggplot2::scale_x_log10(breaks = mic_grid) +
  ggplot2::labs(
    x = "MIC (ug/mL)",
    y = "Joint PTA (%)",
    colour = "Renal band"
  ) +
  ggplot2::theme_bw()
Joint probability of target attainment across MIC, by renal band, under the Table 2 dose adjustments. The horizontal line is the 90% criterion and the vertical line is the 4 ug/mL EUCAST breakpoint for Pseudomonas aeruginosa used throughout Bhagunde 2019.

Joint probability of target attainment across MIC, by renal band, under the Table 2 dose adjustments. The horizontal line is the 90% criterion and the vertical line is the 4 ug/mL EUCAST breakpoint for Pseudomonas aeruginosa used throughout Bhagunde 2019.

# Attainment must fall as MIC rises, within each band, as a trend rather than
# step by step (adjacent MICs can tie at 100%).
trend <- pta_curve |>
  dplyr::group_by(band) |>
  dplyr::summarise(
    drop = pta[mic == min(mic_grid)] - pta[mic == max(mic_grid)],
    .groups = "drop"
  )
stopifnot(nrow(trend) == nrow(bands), all(trend$drop > 0))

Upper clinical exposure bounds

The paper derives an upper exposure threshold for each compound from the highest clinically supported dose, simulated in 1,000 participants with normal renal function: imipenem 1 g q6h and relebactam 625 mg q6h, with the threshold taken as the 90th percentile of the resulting exposure distribution (Methods, “Probability of target attainment simulations”; Results, “PTA simulations”).

norm_cohort <- cohort |> dplyr::filter(band == "Normal")

bound_sim <- function(mod, amt, mw) {
  ev <- make_events(
    norm_cohort$id, amt,
    norm_cohort[, c("id", "CRCL", "WT", "DIS_HEALTHY")],
    grid_ss
  )
  s <- rxode2::rxSolve(mod, ev, returnType = "data.frame")
  per_id <- s |>
    dplyr::group_by(id) |>
    dplyr::arrange(time, .by_group = TRUE) |>
    dplyr::summarise(
      auc24 = 4 * sum(diff(time) * (head(Cc, -1) + tail(Cc, -1)) / 2),
      cmax = max(Cc),
      .groups = "drop"
    )
  c(
    auc24 = unname(quantile(to_uM(per_id$auc24, mw), 0.9)),
    cmax = unname(quantile(to_uM(per_id$cmax, mw), 0.9))
  )
}
bnd_imi <- bound_sim(imi, 1000, mw_imi)
bnd_rel <- bound_sim(rel, 625, mw_rel)

bound_tab <- tibble::tibble(
  Analyte = c("Imipenem 1 g q6h", "Relebactam 625 mg q6h"),
  `AUC0-24 P90 simulated (uM*h)` = round(c(bnd_imi[["auc24"]], bnd_rel[["auc24"]]), 1),
  `AUC0-24 P90 paper (uM*h)` = c(1959.5, 1655.2),
  `Cmax P90 simulated (uM)` = round(c(bnd_imi[["cmax"]], bnd_rel[["cmax"]]), 1),
  `Cmax P90 paper (uM)` = c(364.1, 250.8)
)
knitr::kable(
  bound_tab,
  caption = paste(
    "Upper clinical exposure bounds. The paper's covariate database is",
    "proprietary, so the simulated column uses this vignette's own",
    "normal-renal-function cohort."
  )
)
Upper clinical exposure bounds. The paper’s covariate database is proprietary, so the simulated column uses this vignette’s own normal-renal-function cohort.
Analyte AUC0-24 P90 simulated (uM*h) AUC0-24 P90 paper (uM*h) Cmax P90 simulated (uM) Cmax P90 paper (uM)
Imipenem 1 g q6h 1880.4 1959.5 322.2 364.1
Relebactam 625 mg q6h 1584.5 1655.2 217.2 250.8
# These are 90th percentiles of a cohort drawn from a DIFFERENT covariate
# distribution than the paper's, so only the magnitude is testable, not the
# exact value. This cohort realises 18.0 / 12.2 / 10.8 / 1.1% deviation, all
# on the high side for imipenem, which is what a uniform-within-band CrCL draw
# does to the low-clearance tail. A 30% band sits outside that spread and
# outside the thread-count-dependent draw, and still goes red on a dose error
# or a dropped covariate. It is deliberately NOT the gate on molar mass -- the
# 76.9 uM*h reproduction above does that job at 2%.
pct <- abs(c(
  bnd_imi[["auc24"]] / 1959.5, bnd_rel[["auc24"]] / 1655.2,
  bnd_imi[["cmax"]] / 364.1, bnd_rel[["cmax"]] / 250.8
) - 1)
round(100 * pct, 1)
#> [1]  4.0  4.3 11.5 13.4
stopifnot(all(pct < 0.30))

Assumptions and deviations

  • Molar mass and unbound fraction are external constants. The model files work entirely in mg and mg/L. The conversions to the paper’s uM exposure metrics use imipenem 299.35 g/mol and relebactam 348.37 g/mol, neither of which is printed in the paper. The relebactam value is confirmed internally: it reproduces the paper’s own AUC0-24 target of 76.9 uM*h from fAUC0-24/MIC = 5.2 at MIC 4 ug/mL with fu = 0.78 to within 0.5%. The unbound fractions 0.80 and 0.78 are from the paper.
  • The virtual cohort is not the paper’s. Bhagunde 2019 sampled its PTA populations from a pooled antibacterial-programme database of 10,000,000 virtual participants with an empirical CrCL-weight variance-covariance structure, described only as “data on file”. This vignette draws creatinine clearance uniformly inside each renal band and weight log-normally with median 76 kg and a 0.22 log-scale standard deviation. Every cohort-derived number below the Figure 1 section should be read against that substitution. The consequence is visible and consistent: joint PTA runs 0.1-4.8 points below Table S2 in every renal band, and the imipenem upper-bound exposures run 11-18% above the published ones, both of which are what a uniform-within-band creatinine clearance draw does relative to a distribution concentrated towards the middle of each band. The gates are therefore set on magnitude with explicit headroom, and the sharp reproductions in this vignette are the deterministic ones – the closed form, the mass balance, the Figure 1 inversions and the 76.9 uM*h target – not the cohort statistics.
  • Figure 1’s group covariate values are not published. The fold changes are validated by inverting each published ratio through the fitted exponent rather than by digitising the figure, which is both draw-free and stronger: the imipenem and relebactam panels have to be mutually consistent under a single set of group CrCL values, and they are, to within 2.5%.
  • The Table 4 health-status confidence interval has a lost minus sign. The row prints “-0.34 to 0.23”; an RSE of 9.5% on an estimate of -0.29 gives a Wald interval of -0.34 to -0.24, and an interval spanning zero would contradict the covariate’s retention through backward deletion at P < 0.001. The model file records the corrected interval in a comment. The point estimate is unaffected.
  • The Discussion’s “28.6%” is the unrounded estimate. The Discussion states that “patients were found to have a higher central volume of distribution (28.6%) than healthy volunteers” while Table 4 prints -0.29. The two are the same number at different rounding: an unrounded -0.286 rounds to -0.29 and is consistent with the 9.5% RSE. Read strictly as a patient-versus-healthy ratio the implied increase is 1/0.71 - 1 = 40.8%, not 28.6%; the model file uses the tabulated -0.29 and this vignette does not gate on the Discussion phrasing.
  • Steady state is forced by a 7-day loading period. Neither model has an analytic solution available to ss = 1, so steady state is reached by dosing. Seven days of q6h dosing is sized from the inter-individual tail of the slowest parameter – relebactam clearance in severe renal impairment – not from the typical half-life.
  • Between-occasion variability was not modelled by the authors (“Interoccasion variability: None”, control stream header), so none is encoded.
  • Race, sex and age were screened and not retained. They are recorded in each model file’s covariatesDataExcluded with the reason. Race was explicitly not evaluable: “Meaningful evaluation of race as a covariate was not possible because of an insufficient number of nonwhite participants”.
  • Cilastatin is not modelled. It is a renal dehydropeptidase inhibitor with no antibacterial activity, co-formulated with imipenem, and was not part of the population PK analysis.