Skip to contents

Model and source

  • Citation: Hodiamont CJ, Janssen JM, de Jong MD, Mathot RA, Juffermans NP, van Hest RM. (2017). Therapeutic Drug Monitoring of Gentamicin Peak Concentrations in Critically Ill Patients. Ther Drug Monit 39(5):522-530.
  • Article: https://doi.org/10.1097/FTD.0000000000000432
mod_meta <- rxode2::rxode(readModelDb("Hodiamont_2017_gentamicin"))
#> ℹ parameter labels from comments will be replaced by 'label()'
mod_meta$description
#> [1] "Two-compartment population PK model of intravenous gentamicin in critically ill adult ICU patients (Hodiamont 2017) estimated without retained covariates, with correlated between-subject variability on CL and central volume V1, combined additive plus proportional residual error, and substantial inter-occasion variability on CL and V1 reported in the source (documented in the vignette assumptions, not encoded structurally)."
mod_meta$reference
#> [1] "Hodiamont CJ, Janssen JM, de Jong MD, Mathot RA, Juffermans NP, van Hest RM. Therapeutic Drug Monitoring of Gentamicin Peak Concentrations in Critically Ill Patients. Ther Drug Monit 2017;39(5):522-530. doi:10.1097/FTD.0000000000000432."
mod_meta$units
#> $time
#> [1] "hour"
#> 
#> $dosing
#> [1] "mg"
#> 
#> $concentration
#> [1] "mg/L"

Population

Hodiamont 2017 developed a population PK model from 59 critically ill adults admitted to the mixed medical-surgical ICU of the Academic Medical Center in Amsterdam between May-June 2013 and April-June 2014 (Hodiamont 2017 Table 1). Demographics: 30 male and 29 female, mean age 60.9 +/- 17.2 years, mean total body weight 79.2 +/- 22.0 kg (IBW 71.4 +/- 11.6, ABW 74.6 +/- 13.0). Cockcroft-Gault creatinine clearance averaged 87.0 +/- 64.7 mL/min before the first dose and rose to 99.7 +/- 59.3 and 133.0 +/- 85.6 before the second and third doses respectively, indicating substantial within-patient variation in renal function. Patients received 130 gentamicin administrations over 62 treatment episodes (mean 2.1 +/- 1.9 administrations per episode); the protocol fixed the first dose at approximately 5 mg/kg total body weight (mean 5.1 +/- 1.1 mg/kg) delivered as a 30 min IV infusion. Four endocarditis episodes (3 mg/kg combined with a beta-lactam for synergy) were included in the PK fit but excluded from the paper’s primary target-attainment analysis. A total of 416 blood samples were collected across all episodes (44% routine TDM, 56% residual blood-gas waste material).

The same information is available programmatically via readModelDb("Hodiamont_2017_gentamicin")$population.

Source trace

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

Equation / parameter Value Source location
lcl (log CL) log(2.3) Hodiamont 2017 Table 2, Final Model column
lvc (log V1) log(21.6) Hodiamont 2017 Table 2, Final Model column
lq (log Q) log(1.3) Hodiamont 2017 Table 2, Final Model column
lvp (log V2) log(10.2) Hodiamont 2017 Table 2, Final Model column
IIV CL 75.0% CV -> omega^2 = log(1 + 0.75^2) = 0.446287 Hodiamont 2017 Table 2, IIV CL
IIV V1 27.0% CV -> omega^2 = log(1 + 0.27^2) = 0.070365 Hodiamont 2017 Table 2, IIV V1
Cor(IIV CL, IIV V1) -> covariance r = 0.21 -> 0.21 * sqrt(0.446287 * 0.070365) = 0.037214 Hodiamont 2017 Table 2, “Correlation, r, between IIV CL and IIV V1”
propSd (proportional residual SD) 0.194 Hodiamont 2017 Table 2, Residual variability (19.4%)
addSd (additive residual SD) 0.13 Hodiamont 2017 Table 2, Residual variability (additive 0.13 mg/L)
Two-compartment IV PK ODE structure n/a Hodiamont 2017 Methods “PK Analysis”; Results “Model” (2-cmt superior to 1- and 3-cmt)
Combined additive + proportional residual error n/a Hodiamont 2017 Results “Model”
Body-weight covariates absent in final model n/a Hodiamont 2017 Results “Model” – TBW/IBW/ABW tested, no significant improvement

Virtual cohort

The original observed concentrations are not publicly available. To mirror the simulation scenarios reported by Hodiamont 2017 (Results “Simulation of Cmax at Different Starting Doses”; Figure 5), the vignette draws virtual cohorts of identical 70 kg patients and gives each subject either a 5 mg/kg (350 mg) or a 6 mg/kg (420 mg) first dose infused over 30 minutes. The paper used 1000 subjects per arm; the vignette uses 300 per arm to stay inside the pkgdown build time budget while keeping Monte Carlo noise below ~3 percentage points on each target-attainment statistic.

set.seed(20260524)

n_subjects <- 300L
infusion_h <- 0.5   # 30 min infusion (Hodiamont 2017 Methods, "Patients")

# Hodiamont 2017 simulated identical 70 kg patients (Methods,
# "Simulation of Cmax at Different Starting Doses"). The library model
# carries no body-weight covariate, so WT is only used here to express
# the per-kg dose; it does not enter the model() equations.
regimens <- tibble::tribble(
  ~regimen,   ~dose_mg_per_kg,
  "5 mg/kg",  5,
  "6 mg/kg",  6
)

make_cohort <- function(n, regimen, dose_mg_per_kg, id_offset = 0L) {
  ids <- id_offset + seq_len(n)
  wt  <- rep(70, n)
  amt <- wt * dose_mg_per_kg

  dose_rows <- tibble::tibble(
    id      = ids,
    time    = 0,
    evid    = 1L,
    cmt     = "central",
    amt     = amt,
    rate    = amt / infusion_h,
    regimen = regimen
  )

  obs_grid <- c(seq(0, 2, by = 0.1), 2.5, 3, 4, 6, 8, 12, 18, 24)
  obs_rows <- tidyr::expand_grid(id = ids, time = obs_grid) |>
    dplyr::mutate(
      evid    = 0L,
      cmt     = "central",
      amt     = 0,
      rate    = 0,
      regimen = regimen
    )

  dplyr::bind_rows(dose_rows, obs_rows) |>
    dplyr::arrange(id, time, dplyr::desc(evid))
}

events <- dplyr::bind_rows(
  make_cohort(n_subjects, "5 mg/kg", 5, id_offset =    0L),
  make_cohort(n_subjects, "6 mg/kg", 6, id_offset = 1000L)
)

stopifnot(!anyDuplicated(unique(events[, c("id", "time", "evid")])))

cat(
  "Dose rows:", sum(events$evid == 1L),
  " | Obs rows:", sum(events$evid == 0L), "\n"
)
#> Dose rows: 600  | Obs rows: 17400

Simulation

mod <- readModelDb("Hodiamont_2017_gentamicin")
sim <- rxode2::rxSolve(
  mod,
  events = events,
  keep   = c("regimen")
) |>
  as.data.frame()
#> ℹ parameter labels from comments will be replaced by 'label()'

Replicate published figures

Figure 5 – simulated first-dose Cmax distributions

Hodiamont 2017 Figure 5A and 5C show boxplots of simulated first-dose gentamicin Cmax at 5 mg/kg and 6 mg/kg respectively (1000 patients per arm, body weight 70 kg). The published median Cmax was 14.0 mg/L at 5 mg/kg and 16.8 mg/L at 6 mg/kg. Cmax in the paper is defined as the serum concentration 30 minutes after the end of a 30 min infusion, i.e. at 1 hour after the start of the infusion (Methods, “Analysis of Gentamicin Cmax”).

cmax_at_1h <- sim |>
  dplyr::filter(abs(time - 1) < 1e-6) |>
  dplyr::select(id, regimen, Cmax = Cc)

ggplot(cmax_at_1h, aes(regimen, Cmax)) +
  geom_boxplot(width = 0.4, outlier.size = 0.6) +
  geom_hline(yintercept = c(15, 20), linetype = "dashed", colour = "grey50") +
  annotate("text", x = 0.6, y = 17.5, label = "Therapeutic\n15-20 mg/L",
           hjust = 0, size = 3, colour = "grey30") +
  labs(
    x       = "First-dose regimen",
    y       = "Cmax 30 min after end of infusion (mg/L)",
    title   = "Replicates Figure 5A/5C of Hodiamont 2017",
    caption = paste0(
      "Simulated first-dose Cmax for ", n_subjects,
      " 70 kg patients per regimen. Dashed lines mark the 15-20 mg/L therapeutic range."
    )
  )

PKNCA validation

Compute Cmax over the first dosing interval per subject with PKNCA. Grouping is by regimen. (Hodiamont 2017 reports first-dose Cmax only; there is no published AUC reference, but auclast is included for completeness.)

sim_nca <- sim |>
  dplyr::filter(!is.na(Cc)) |>
  dplyr::select(id, time, Cc, regimen)

dose_df <- events |>
  dplyr::filter(evid == 1L) |>
  dplyr::select(id, time, amt, regimen)

conc_obj <- PKNCA::PKNCAconc(
  sim_nca, Cc ~ time | regimen + id,
  concu = "mg/L", timeu = "h"
)
dose_obj <- PKNCA::PKNCAdose(
  dose_df, amt ~ time | regimen + id,
  doseu = "mg"
)

intervals <- data.frame(
  start    = 0,
  end      = 24,
  cmax     = TRUE,
  tmax     = TRUE,
  auclast  = TRUE
)

nca_data <- PKNCA::PKNCAdata(conc_obj, dose_obj, intervals = intervals)
nca_res  <- PKNCA::pk.nca(nca_data)

res_tbl <- as.data.frame(nca_res$result)

Comparison against Hodiamont 2017 simulation summaries

Hodiamont 2017 reports, for each starting-dose scenario, the median Cmax and the percentage of patients whose Cmax falls within (%Cther: 15-20 mg/L), below (%Csubther: < 15 mg/L), and above (%Csuprather: > 20 mg/L) the therapeutic range. The chunk below recomputes those statistics from the simulated Cmax-at-1-hour values (matching the paper’s Cmax definition) and renders them side-by-side with the published values.

simulated <- cmax_at_1h |>
  dplyr::group_by(regimen) |>
  dplyr::summarise(
    median_Cmax_sim    = median(Cmax),
    pct_in_target_sim  = mean(Cmax >= 15 & Cmax <= 20) * 100,
    pct_subther_sim    = mean(Cmax <  15)              * 100,
    pct_suprather_sim  = mean(Cmax >  20)              * 100,
    .groups = "drop"
  )

published <- tibble::tribble(
  ~regimen,   ~median_Cmax_pub, ~pct_in_target_pub, ~pct_subther_pub, ~pct_suprather_pub,
  "5 mg/kg",  14.0,             27.7,                58.6,             13.7,
  "6 mg/kg",  16.8,             33.5,                35.6,             30.9
)

comparison <- published |>
  dplyr::left_join(simulated, by = "regimen") |>
  dplyr::select(regimen,
                median_Cmax_pub,    median_Cmax_sim,
                pct_in_target_pub,  pct_in_target_sim,
                pct_subther_pub,    pct_subther_sim,
                pct_suprather_pub,  pct_suprather_sim)

knitr::kable(
  comparison,
  digits  = 1,
  caption = paste("Comparison of simulated first-dose Cmax statistics with",
                  "Hodiamont 2017 Results 'Simulation of Cmax at Different",
                  "Starting Doses'. The 'pub' columns are the published values",
                  "(1000 patients per arm); the 'sim' columns come from the",
                  paste0("packaged model with n = ", n_subjects,
                         " 70 kg patients per arm."))
)
Comparison of simulated first-dose Cmax statistics with Hodiamont 2017 Results ‘Simulation of Cmax at Different Starting Doses’. The ‘pub’ columns are the published values (1000 patients per arm); the ‘sim’ columns come from the packaged model with n = 300 70 kg patients per arm.
regimen median_Cmax_pub median_Cmax_sim pct_in_target_pub pct_in_target_sim pct_subther_pub pct_subther_sim pct_suprather_pub pct_suprather_sim
5 mg/kg 14.0 13.8 27.7 28.3 58.6 62.7 13.7 9.0
6 mg/kg 16.8 16.5 33.5 42.7 35.6 35.7 30.9 21.7

The simulated median Cmax and target-attainment percentages should track the published values within Monte Carlo noise (the paper used 1000 patients per arm versus 300 here). Sizeable IIV on V1 (27%) and on CL (75%) drives the wide spread; the simulated medians sitting near the centre of the published values is the primary check that the typical-value structural parameters and the IIV omegas were translated correctly. The PKNCA cmax value over the full 0-24 h dosing interval is also available in res_tbl for users who prefer the maximum-over- interval definition; that value will be similar but is not identical to the published “30 min after end of infusion” Cmax used in the Hodiamont paper.

Assumptions and deviations

  • Inter-occasion variability (IOV) not encoded. Hodiamont 2017 estimated IOV on both CL (24.0% CV) and V1 (25.1% CV); the IOV on V1 is in fact the paper’s central finding because it exceeded the arbitrary 15% cutoff below which the authors considered routine TDM effective. Following the precedent set by Sikma_2020_tacrolimus* and Ting_2014_tobramycin_inhaled, the packaged model omits the IOV terms because nlmixr2lib popPK extractions do not standardise IOV encoding (it requires an OCC variable in the dataset and a multiplexed per-occasion eta structure, cf. Wilkins_2008_rifampicin or Vet_2016_midazolam). Population-level statistics from simulations of a single dose (such as the first-dose Cmax distributions replicated above) are unaffected because IOV only acts across occasions within a subject. Users simulating multi-dose scenarios and interested in repeat-administration Cmax variability should add the IOV layer manually; in the source paper this was the main driver of why TDM after the first dose had limited utility.
  • Body-weight covariates absent. Hodiamont 2017 tested TBW, IBW, and ABW on CL, Q, V1, and V2 using both allometric (with fixed exponents 0.75 / 1) and univariate forms and reported no significant OFV improvement (Results, “Model”). The packaged model therefore carries no covariate effects and covariateData is empty. Users applying this model to populations whose body-size distribution differs substantially from the source cohort (mean TBW 79 kg, range reported but not tabulated subject-by-subject) should interpret predictions with that limitation in mind.
  • Renal function, fluid balance, inotrope use not tested. The paper states explicitly that these covariates were not evaluated; the goal was to quantify the total IOV that arises in routine TDM where only body weight is normally considered. The packaged model inherits this scope.
  • Endocarditis sub-cohort retained in fit. Four treatment episodes for endocarditis were dosed at 3 mg/kg in combination with a beta-lactam and were retained in the PK fit but excluded from the paper’s primary target-attainment analysis. The library model does not distinguish these episodes from the standard 5 mg/kg-protocol episodes.
  • Cmax definition. The paper’s Cmax is the concentration 30 minutes after the end of a 30 minute infusion (i.e. at 1 hour after the start of dosing). The comparison table uses that definition; the PKNCA cmax field over 0-24 h is similar but not identical.
  • Infusion duration set by the event table. The source paper modelled a 30 minute IV infusion. The library model does not hard-code dur(central), so users specify infusion duration per dose via the rate (or dur) column on the event-table dose rows; the vignette uses rate = amt / 0.5 to deliver each dose over 30 minutes.
  • Errata not searched. The skill’s pre-flight checklist asks for an errata search on the publisher landing page; for this 2017 article the search was not performed during extraction. If a subsequent erratum revises a Table 2 estimate, the packaged values should be refreshed accordingly.