Skip to contents

Model and source

  • Citation: Schutte LM, van Hest RM, Stoof SCM, Leebeek FWG, Cnossen MH, Kruip MJHA, Mathot RAA. Pharmacokinetic Modelling to Predict FVIII:C Response to Desmopressin and Its Reproducibility in Nonsevere Haemophilia A Patients. Thromb Haemost 2018;118(3):621-629.
  • Article: https://doi.org/10.1160/TH17-06-0390
  • Description: Two-compartment apparent population PK model of endogenous factor VIII coagulant activity (FVIII:C) following a desmopressin (DDAVP) administration in nonsevere haemophilia A patients. The administered intervention is desmopressin; the apparent PK parameters describe the resulting endogenous FVIII:C release as if it were a unit-dose drug input. The covariate FVIIIRECENT (most recently measured FVIII:C, IU/mL) acts on baseline FVIII, V1, and CL.

Population

Schutte 2018 is a single-centre retrospective cohort drawn from nonsevere haemophilia A patients at the Erasmus University Medical Centre, Rotterdam (Schutte 2018 Patients and Methods). The PK dataset comprises 623 FVIII:C measurements from 142 desmopressin administrations in 128 patients (14 of whom contributed two administrations on separate occasions). Median age was 28 years (range 7-75; 24% below 18 years), median body weight 75 kg (range 26-120). The cohort is essentially male because haemophilia A is X-linked recessive. Disease severity: 84% mild (n = 107) and 16% moderate (n = 21) HA. Desmopressin was administered intravenously over 30 minutes at 0.3 micrograms/kg in 92% of administrations and intranasally as a 300-microgram fixed dose in the remaining 8% (Schutte 2018 Desmopressin Administration; Table 1).

Demographic baselines relevant to the model: FVIII-lowest (the lowest ever recorded FVIII:C activity per patient) had median 0.10 IU/mL (interquartile range 0.04-0.18, n = 128). FVIII-recent (the most recent FVIII:C measurement obtained at most 1 day before desmopressin) had median 0.15 IU/mL (interquartile range 0.08-0.24, n = 120). FVIII-recent was the only covariate retained in the final model; the multivariate analysis preferred FVIII-recent over FVIII-lowest because nonsevere HA patients accumulate FVIII activity gradually over years (Schutte 2018 Discussion). The same information is available programmatically via the model’s population metadata (readModelDb("Schutte_2018_desmopressin")$population after the model is loaded).

Source trace

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

Equation / parameter Value Source location
lka (= log ka) log(3.8 1/h) Schutte 2018 Table 2, Final-model column
lcl (= log CL/F) log(0.26 L/h) Schutte 2018 Table 2, Final-model column
lvc (= log V1/F) log(1.7 L) Schutte 2018 Table 2, Final-model column
lq (= log Q/F) log(0.11 L/h) Schutte 2018 Table 2, Final-model column
lvp (= log V2/F) log(0.24 L) Schutte 2018 Table 2, Final-model column
lbase_fviii (= log typical baseline FVIII at FVIIIRECENT = 0.15) log(0.15 IU/mL) Schutte 2018 Table 2, Final-model column
e_fviiirecent_base +0.74 Schutte 2018 Table 2, FVIII recent on baseline (Eq. 1)
e_fviiirecent_vc -0.61 Schutte 2018 Table 2, FVIII recent on V1 (Eq. 3)
e_fviiirecent_cl -0.73 Schutte 2018 Table 2, FVIII recent on CL (Eq. 2)
IIV etalbase_fviii 37% CV (var = log(1 + 0.37^2) = 0.1283) Schutte 2018 Table 2, IIV Baseline FVIII
IIV etalvc 43% CV (var = log(1 + 0.43^2) = 0.1697) Schutte 2018 Table 2, IIV V1
IIV etalcl 50% CV (var = log(1 + 0.50^2) = 0.2231) Schutte 2018 Table 2, IIV CL
correlation(etalbase_fviii, etalvc) -0.87 (cov = -0.1284) Schutte 2018 Table 2, Correlation IIV baseline FVIII and IIV V1
propSd 12% Schutte 2018 Table 2, Proportional error
addSd 0.018 IU/mL Schutte 2018 Table 2, Additive error
Two-compartment structure with first-order absorption n/a Schutte 2018 Population Pharmacokinetic Modelling; Fig. 3
FVIII:C = baseline + apparent increase n/a Schutte 2018 Population Pharmacokinetic Modelling (paragraph 2: “FVIII:C increase … was added to the estimated baseline FVIII:C”)
Reference value FVIIIRECENT = 0.15 IU/mL n/a Schutte 2018 Table 1 (population median FVIII-recent)

Virtual cohort

Original observed data are not publicly available. The cohort below approximates the Schutte 2018 demographics for FVIIIRECENT (median 0.15 IU/mL, IQR 0.08-0.24 from Table 1). FVIIIRECENT is sampled from a log-normal distribution whose median and IQR match the published values; the fit is FVIIIRECENT_i = exp(rnorm(n, mean = log(0.15), sd = 0.815)), with sd chosen so that the 25th-75th percentile ratio matches the reported IQR of 0.24 / 0.08 = 3.0.

set.seed(20180330)
n_subjects <- 200

cohort <- tibble(
  id = seq_len(n_subjects),
  FVIIIRECENT = exp(rnorm(n_subjects, mean = log(0.15), sd = 0.815))
)

# Truncate to a plausible range (the paper's observed range was effectively
# 0.01 - 0.50 IU/mL; nonsevere HA patients by definition have FVIII >= 0.01).
cohort$FVIIIRECENT <- pmax(pmin(cohort$FVIIIRECENT, 0.50), 0.01)

# Observation grid: 10-minute spacing for 24 h to match the paper's
# individual FVIII:C response time grid (Schutte 2018 FVIII:C Response).
obs_times <- seq(0, 24, by = 1/6)

events <- bind_rows(
  cohort %>% mutate(time = 0, evid = 1, amt = 1, cmt = "depot"),
  cohort %>%
    tidyr::expand_grid(time = obs_times) %>%
    mutate(evid = 0, amt = NA_real_, cmt = NA_character_)
) %>%
  arrange(id, time, desc(evid))

Simulation

mod <- readModelDb("Schutte_2018_desmopressin")

# Stochastic simulation with full IIV (etalbase_fviii, etalvc, etalcl) for
# variability assessments (cohort half-life distribution, duration of
# response, etc.).
sim <- rxode2::rxSolve(mod, events = events, keep = "FVIIIRECENT") |>
  as.data.frame()
#> ℹ parameter labels from comments will be replaced by 'label()'

For deterministic curves (typical-value replication of Figure 4), zero out the random effects:

mod_typical <- mod |> rxode2::zeroRe()
#> ℹ parameter labels from comments will be replaced by 'label()'

Replicate published figures

Figure 4: typical FVIII:C response by FVIII-recent quantile

Schutte 2018 Figure 4 plots typical-value FVIII:C response-time curves for five patients differing only in their FVIIIRECENT value, set to the 5th, 25th, 50th, 75th, and 95th percentile of the study cohort’s FVIII-recent distribution. The corresponding values from Table 1 / Figure 4 caption are 0.04, 0.08, 0.15, 0.24, and 0.47 IU/mL.

fviii_quantiles <- tibble(
  percentile = c("5th", "25th", "50th", "75th", "95th"),
  FVIIIRECENT = c(0.04, 0.08, 0.15, 0.24, 0.47)
) %>%
  mutate(percentile = factor(percentile, levels = c("5th", "25th", "50th", "75th", "95th")))

fig4_events <- bind_rows(
  fviii_quantiles %>% mutate(id = seq_len(n()), time = 0, evid = 1, amt = 1, cmt = "depot"),
  fviii_quantiles %>%
    mutate(id = seq_len(n())) %>%
    tidyr::expand_grid(time = obs_times) %>%
    mutate(evid = 0, amt = NA_real_, cmt = NA_character_)
) %>%
  arrange(id, time, desc(evid))

fig4_sim <- rxode2::rxSolve(mod_typical, events = fig4_events,
                            keep = c("FVIIIRECENT", "percentile")) |>
  as.data.frame()
#> ℹ omega/sigma items treated as zero: 'etalbase_fviii', 'etalvc', 'etalcl'
#> Warning: multi-subject simulation without without 'omega'

ggplot(fig4_sim, aes(time, Cc, colour = percentile, group = percentile)) +
  geom_line(linewidth = 0.9) +
  geom_hline(yintercept = c(0.30, 0.50), linetype = "dashed", alpha = 0.4) +
  scale_x_continuous(breaks = seq(0, 24, by = 4)) +
  labs(x = "Time (h)", y = "FVIII:C (IU/mL)",
       colour = "FVIII-recent percentile",
       title = "Figure 4: typical FVIII:C response curves",
       caption = "Replicates Schutte 2018 Figure 4. Dashed lines: 0.30 and 0.50 IU/mL thresholds.")

PKNCA validation

For this model the meaningful NCA quantity is the FVIII:C increase above baseline (the apparent rxode2 concentration central / vc), which is what the source paper reports as absolute increase, half-life, and duration of response. PKNCA is applied to the increase rather than to the total observed FVIII:C so that the AUC and half-life are interpretable on the dose-driven perturbation directly.

sim_nca <- sim %>%
  mutate(Cc_increase = pmax(Cc - base_fviii, 0)) %>%
  dplyr::filter(time > 0) %>%
  dplyr::select(id, time, Cc_increase, FVIIIRECENT)

conc_obj <- PKNCA::PKNCAconc(sim_nca, Cc_increase ~ time | id)

dose_df <- events %>%
  dplyr::filter(evid == 1) %>%
  dplyr::select(id, time, amt) %>%
  dplyr::left_join(cohort %>% dplyr::select(id, FVIIIRECENT), by = "id")

dose_obj <- PKNCA::PKNCAdose(dose_df, amt ~ time | id)

intervals <- data.frame(
  start      = 0,
  end        = Inf,
  cmax       = TRUE,
  tmax       = TRUE,
  aucinf.obs = TRUE,
  half.life  = TRUE
)

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

nca_wide <- as.data.frame(nca_res$result) %>%
  dplyr::select(id, PPTESTCD, PPORRES) %>%
  tidyr::pivot_wider(names_from = PPTESTCD, values_from = PPORRES)

Comparison against published metrics

Schutte 2018 reports (Results, FVIII:C Response to Desmopressin):

  • Median absolute increase in FVIII:C: 0.47 IU/mL (IQR 0.32-0.65; n = 142)
  • Median half-life of FVIII:C: 5.8 h (IQR 4.2-7.9)
  • Median duration FVIII:C > 0.30 IU/mL: 9.8 h (IQR 4.3-22.6); 90% of administrations exceed 0.30
  • Median duration FVIII:C > 0.50 IU/mL: 4.8 h (IQR 2.1-10.7); 63% of administrations exceed 0.50

The simulated cohort gives:

duration_above <- function(t, x, threshold) {
  above <- x > threshold
  if (!any(above)) return(0)
  dt <- diff(c(t, max(t)))
  sum(dt[above[-length(above)]])
}

per_subject <- sim %>%
  dplyr::filter(time > 0) %>%
  dplyr::group_by(id, FVIIIRECENT) %>%
  dplyr::summarise(
    peak_total    = max(Cc),
    peak_increase = max(Cc - base_fviii),
    dur_above_030 = duration_above(time, Cc, 0.30),
    dur_above_050 = duration_above(time, Cc, 0.50),
    .groups = "drop"
  ) %>%
  dplyr::left_join(
    nca_wide %>% dplyr::select(id, half.life),
    by = "id"
  )

# Paper's duration medians are conditional on subjects whose peak FVIII:C
# exceeded the threshold (Results paragraph: "FVIII:C remained above 0.50
# IU/mL in these patients [the 63% exceeding 0.50] for a median time of 4.8
# hours"). Reproduce the conditional medians here.
dur_030 <- per_subject %>% dplyr::filter(peak_total > 0.30) %>% dplyr::pull(dur_above_030)
dur_050 <- per_subject %>% dplyr::filter(peak_total > 0.50) %>% dplyr::pull(dur_above_050)

q <- function(x, p) {
  if (length(x) == 0) return(NA_real_)
  round(stats::quantile(x, p, na.rm = TRUE), 2)
}
qrange <- function(x) paste(q(x, 0.25), "-", q(x, 0.75))

comparison <- tibble::tribble(
  ~metric,                                              ~paper_median, ~paper_iqr,            ~sim_median,                             ~sim_iqr,
  "Absolute FVIII:C increase (IU/mL)",                  0.47,          "0.32 - 0.65",         q(per_subject$peak_increase, 0.50),      qrange(per_subject$peak_increase),
  "Half-life of FVIII:C increase (h)",                  5.8,           "4.2 - 7.9",           q(per_subject$half.life,      0.50),     qrange(per_subject$half.life),
  "Duration FVIII:C > 0.30 IU/mL (h) (conditional)",    9.8,           "4.3 - 22.6",          q(dur_030,                    0.50),     qrange(dur_030),
  "Duration FVIII:C > 0.50 IU/mL (h) (conditional)",    4.8,           "2.1 - 10.7",          q(dur_050,                    0.50),     qrange(dur_050)
)
knitr::kable(comparison, caption = "Simulated vs Schutte 2018 published medians (Results section). Duration medians are conditional on peak FVIII:C exceeding the threshold, matching the paper's reporting convention.")
Simulated vs Schutte 2018 published medians (Results section). Duration medians are conditional on peak FVIII:C exceeding the threshold, matching the paper’s reporting convention.
metric paper_median paper_iqr sim_median sim_iqr
Absolute FVIII:C increase (IU/mL) 0.47 0.32 - 0.65 0.46 0.34 - 0.68
Half-life of FVIII:C increase (h) 5.80 4.2 - 7.9 5.43 3.77 - 8.28
Duration FVIII:C > 0.30 IU/mL (h) (conditional) 9.80 4.3 - 22.6 9.17 5 - 23.83
Duration FVIII:C > 0.50 IU/mL (h) (conditional) 4.80 2.1 - 10.7 4.67 2 - 10.67

pct_above_030 <- round(mean(per_subject$peak_total > 0.30) * 100, 0)
pct_above_050 <- round(mean(per_subject$peak_total > 0.50) * 100, 0)

In the virtual cohort, 90% of administrations exceed peak FVIII:C 0.30 IU/mL (paper: 90%) and 66% exceed peak FVIII:C 0.50 IU/mL (paper: 63%).

Assumptions and deviations

  • Unit dose abstraction. The source paper fixed the desmopressin dose to unity because no FVIII concentrate was administered; the structural parameters are therefore apparent (CL/F, V1/F, V2/F, Q/F) and the model is simulated by dosing 1 unit into the depot compartment. The route of administration (IV vs intranasal) is not distinguished – Schutte 2018 lumps both into a single ka and so does this model file.
  • FVIIIRECENT missing-data branch not encoded. Schutte 2018 Eqs. 1-3 define a different covariate form when the patient’s FVIIIRECENT value was unavailable for the fitted occasion: baseline FVIII = 0.15 * 1.2 (no FVIIIRECENT dependence), V1 = 1.7 * 1.1, CL = 0.26 * 0.78 (Table 2 final-model column). This branch is documented here but is NOT implemented in model(); simulation users are expected to supply a FVIIIRECENT value for every simulated subject. If reproducing a missing-FVIIIRECENT subgroup is required, set FVIIIRECENT to its reference value (0.15) and multiply the typical-value outputs by the correction factors above.
  • CL correction factor 0.78 vs 0.77 typo. Schutte 2018 Table 2 reports the missing-FVIIIRECENT correction factor on CL as 0.78 (RSE 17%), but Eq. 2 in the body text shows 0.77 in the analogous position. We treat the parameter-table value (0.78) as authoritative because it is the primary parameter report; the 0.77 in the equation is most likely a transcription typo. Since the missing-FVIIIRECENT branch is documented-only (not encoded), the choice has no effect on simulation.
  • Inter-occasion variability omitted. Schutte 2018 Table 2 reports intra-individual (between-occasion) variability of 38% on baseline FVIII and 38% on V1 (final-model column). nlmixr2lib models conventionally encode IIV but not IOV; the same convention applies in the analogous Nestorov_2014_factorviii FVIII model. Single-occasion simulations from this model will under-represent the per-patient variability that the original fit characterised, but typical-value predictions and population summaries are not affected.
  • PKNCA half-life is on the apparent FVIII:C increase, not on the total observed FVIII:C. Total observed FVIII:C does not return to zero (it returns to the baseline FVIII), so a half-life computed on Cc would mix the baseline plateau with the decline phase. The paper’s reported “half-life of FVIII:C” is on the increase above baseline (see Schutte 2018 Discussion paragraph on half-life), so we apply PKNCA to Cc - base_fviii to match. The simulated terminal half-life is computed by PKNCA via log-linear regression on the late-phase samples; this can deviate from the paper’s Bayesian individual-estimate-derived half-life because the late-phase signal of the increase is small (close to or below the additive residual error) for patients with low FVIIIRECENT.
  • Cohort size and FVIIIRECENT distribution. The virtual cohort uses 200 subjects with FVIIIRECENT sampled from a log-normal distribution matching the published median (0.15 IU/mL) and IQR (0.08-0.24 IU/mL) from Schutte 2018 Table 1. The original observed cohort is 128 subjects with 142 administrations; the larger simulated n is to reduce Monte Carlo noise in the simulated medians, not to extend the population beyond its source.