Skip to contents

Model and source

Karunajeewa 2009 reported two independently-fit population PK analyses on the same patient cohort (60 Papua New Guinean women: 30 pregnant in the second or third trimester, 30 age-matched nonpregnant controls) given a single oral 1,500 mg sulfadoxine plus 75 mg pyrimethamine dose. Per the standing policy of replicating the author’s modeling structure, the two models are shipped as two separate .R files:

  • modellib("Karunajeewa_2009_sulfadoxine") – sulfadoxine 2-compartment parent with an N-acetylsulfadoxine 1-compartment metabolite (NASDOX clearance fixed at 10x the parent’s non-metabolic clearance).
  • modellib("Karunajeewa_2009_pyrimethamine") – pyrimethamine 2-compartment disposition.

Citations and descriptions:

cat(rxode2::rxode(readModelDb("Karunajeewa_2009_sulfadoxine"))$reference, "\n")
#> Karunajeewa HA, Salman S, Mueller I, Baiwog F, Gomorrai S, Law I, Page-Sharp M, Rogerson S, Siba P, Ilett KF, Davis TME. Pharmacokinetic properties of sulfadoxine-pyrimethamine in pregnant women. Antimicrob Agents Chemother. 2009;53(10):4368-4376. doi:10.1128/AAC.00335-09.
cat(rxode2::rxode(readModelDb("Karunajeewa_2009_sulfadoxine"))$description, "\n")
#> Population PK model for sulfadoxine (SDOX) and its primary N-acetylsulfadoxine (NASDOX) metabolite in 60 Papua New Guinean women (30 pregnant, second or third trimester; 30 age-matched nonpregnant controls) given a single oral 1,500 mg sulfadoxine / 75 mg pyrimethamine dose for intermittent presumptive treatment of malaria in pregnancy (Karunajeewa 2009). SDOX is described by first-order absorption (no lag) into a 2-compartment disposition with separate non-metabolic clearance CL/F (renal excretion) and metabolic formation clearance CLM/F that drains SDOX into a 1-compartment NASDOX disposition. NASDOX elimination clearance is fixed at 10 times the structural SDOX non-metabolic CL/F (rapid formation-rate-limited renal excretion of the metabolite, Bell 1985). Allometric scaling is applied to all apparent volumes (exponent 1) and all apparent clearances (exponent 0.75) at reference WT = 70 kg. Pregnancy is the only retained covariate, entering as an additive term on the structural SDOX non-metabolic CL/F (+0.0181 L/h/70 kg). The companion model for the co-administered pyrimethamine is shipped as 'Karunajeewa_2009_pyrimethamine' (separate NONMEM dataset, fit independently in the source publication).
cat(rxode2::rxode(readModelDb("Karunajeewa_2009_pyrimethamine"))$reference, "\n")
#> Karunajeewa HA, Salman S, Mueller I, Baiwog F, Gomorrai S, Law I, Page-Sharp M, Rogerson S, Siba P, Ilett KF, Davis TME. Pharmacokinetic properties of sulfadoxine-pyrimethamine in pregnant women. Antimicrob Agents Chemother. 2009;53(10):4368-4376. doi:10.1128/AAC.00335-09.
cat(rxode2::rxode(readModelDb("Karunajeewa_2009_pyrimethamine"))$description, "\n")
#> Population PK model for pyrimethamine (PYR) in 60 Papua New Guinean women (30 pregnant, second or third trimester; 30 age-matched nonpregnant controls) given a single oral 1,500 mg sulfadoxine / 75 mg pyrimethamine dose for intermittent presumptive treatment of malaria in pregnancy (Karunajeewa 2009). Two-compartment disposition with first-order absorption and no lag, fit as a separate NONMEM dataset from the parent SDOX/NASDOX dataset. Allometric scaling at reference WT = 70 kg is applied to all apparent volumes (exponent 1) and all apparent clearances (exponent 0.75). Pregnancy is the only retained covariate; it enters as additive terms on apparent CL/F (+0.439 L/h/70 kg), Vc/F (+76 L/70 kg) and Vp/F (+98 L/70 kg). Between-subject variability on CL/F, Vc/F and Vp/F is correlated (3x3 block, correlations 0.797 / 0.756 / 0.731 from Table 4); BSV on Q/F and ka is independent. The companion model for the co-administered sulfadoxine plus its NASDOX metabolite is shipped as 'Karunajeewa_2009_sulfadoxine' (separate NONMEM dataset, fit independently in the source publication).

Article: https://doi.org/10.1128/AAC.00335-09.

Population

Sixty women were enrolled at the Alexishafen Health Centre, Madang Province, on the north coast of Papua New Guinea (Methods, “Study site and sample”). The 30 pregnant subjects were first-time antenatal attendees in the second or third trimester (median gestational age 22 weeks; IQR 20-28); the 30 nonpregnant village controls were age-matched. Both groups were well matched for age, weight, and height (Table 1):

Characteristic Pregnant (n = 30) Nonpregnant (n = 30)
Age (years) 26.0 +/- 5.9 25.5 +/- 8.9
Body weight (kg) 54.0 +/- 6.4 51.8 +/- 5.5
Height (cm) 151 +/- 5 149 +/- 5
P. falciparum parasitemia at baseline 13 (43%) 7 (23%)

The local population is described as almost exclusively Melanesian. Each subject received a supervised single oral dose of Fansidar (Roche; 1,500 mg sulfadoxine + 75 mg pyrimethamine) plus three daily 450 mg chloroquine doses per Papua New Guinea national IPTp guidelines. Blood samples were drawn at 0, 1, 2, 4, 6, 12, 18, 24, 30, 48, 72 h then at 7, 10, 14, 28, and 42 days postdose. SDOX, NASDOX, and pyrimethamine were assayed by HPLC-UV (LOQ 0.1 mg/L, 0.02 mg/L, and 2.5 ug/L respectively); below-LOQ values (< 0.5% of all values) were imputed at LOQ/2.

The same information is available programmatically via each model’s population metadata, e.g., readModelDb("Karunajeewa_2009_sulfadoxine")()$population.

Source trace

The per-parameter origin is recorded as an in-file comment next to each ini() entry in the model files. The combined source-trace is reproduced below for review.

Sulfadoxine + N-acetylsulfadoxine (Table 2 “Final covariate model” column)

Equation / parameter Value Source location
lka (ka) 0.769 /h Table 2 row “k a”
lcl (SDOX non-metabolic CL/F per 70 kg, nonpregnant) 0.0379 L/h Table 2 row “CL/F SDOX”
e_preg_cl (additive pregnancy effect on CL/F) +0.0181 L/h/70 kg Table 2 row “Pregnancy on CL/F SDOX”
lvc (SDOX Vc/F per 70 kg) 15.8 L Table 2 row “V_C/F SDOX”
lq (SDOX Q/F per 70 kg) 0.0052 L/h Table 2 row “CL_Q/F”
lvp (SDOX Vp/F per 70 kg) 1.11 L Table 2 row “V_P/F SDOX”
lclm (SDOX -> NASDOX CLM/F per 70 kg) 0.0227 L/h Table 2 row “CL_M/F”
lvc_nasdox (NASDOX V/F per 70 kg) 3.69 L Table 2 row “V/F NASDOX”
CL_NASDOX (NASDOX elimination CL/F per 70 kg) 10 * CL/F SDOX (FIXED) Figure 2 legend “CL/F NASDOX (fixed at 10 x CL/F SDOX)”; mechanism cited from Bell 1985
lfdepot (SDOX F) 1 (FIXED) Methods “Population pharmacokinetic analysis”: all V and CL relative to bioavailability
Allometric exponents 1 (V), 0.75 (CL/Q) Methods: “Allometric scaling was used on all volume [*(weight/70)^1.0] and clearance [*(weight/70)^0.75] terms”
etalcl (BSV CL/F SDOX) 28.1% CV Table 2 row “BSV CL/F SDOX”
etalvc (BSV V_C/F SDOX) 19.9% CV Table 2 row “BSV V_C/F SDOX”
etalka (BSV ka) 99.6% CV Table 2 row “BSV ka”
etalclm (BSV CLM/F) 27.3% CV Table 2 row “BSV CL_M/F”
propSd (SDOX proportional RUV) 24.1% Table 2 row “Proportional error in SDOX”
propSd_nasdox (NASDOX proportional RUV) 16.0% Table 2 row “Proportional error in NASDOX”
addSd_nasdox (NASDOX additive RUV) 0.2 mg/L Table 2 row “Additive error in NASDOX”
Structural model 2-compartment SDOX with first-order absorption, no lag, plus 1-compartment NASDOX Figure 2 schematic; Results “Pharmacokinetics of SDOX and NASDOX”

Pyrimethamine (Table 4 “Final covariate model” column)

Equation / parameter Value Source location
lka (ka) 1.84 /h Table 4 row “k a”
lcl (CL/F per 70 kg, nonpregnant) 0.87 L/h Table 4 row “CL/F”
e_preg_cl (pregnancy additive on CL/F) +0.439 L/h/70 kg Table 4 row “Pregnancy on CL/F”
lvc (Vc/F per 70 kg, nonpregnant) 146 L Table 4 row “V_C/F”
e_preg_vc (pregnancy additive on Vc/F) +76 L/70 kg Table 4 row “Pregnancy on V_C/F”
lvp (Vp/F per 70 kg, nonpregnant) 76.8 L Table 4 row “V_P/F”
e_preg_vp (pregnancy additive on Vp/F) +98 L/70 kg Table 4 row “Pregnancy on V_P/F”
lq (Q/F per 70 kg) 0.51 L/h Table 4 row “Q/F”
lfdepot (PYR F) 1 (FIXED) Methods “Population pharmacokinetic analysis”: all V and CL relative to bioavailability
Allometric exponents 1 (V), 0.75 (CL/Q) Methods (same convention as SDOX)
etalcl (BSV CL/F) 27.6% CV Table 4 row “BSV CL/F”
etalvc (BSV V_C/F) 24.6% CV Table 4 row “BSV V_C/F”
etalvp (BSV V_P/F) 42.5% CV Table 4 row “BSV V_P/F”
etalq (BSV Q/F) 57.5% CV Table 4 row “BSV Q/F”
etalka (BSV ka) 10.7% CV Table 4 row “BSV ka” (see Errata)
R(CL/F, V_C/F) 0.797 Table 4 row “R (CL/F, V_C/F)”
R(CL/F, V_P/F) 0.756 Table 4 row “R (CL/F, V_P/F)”
R(V_C/F, V_P/F) 0.731 Table 4 row “R (V_C/F, V_P/F)”
propSd (PYR proportional RUV) 19.2% Table 4 row “Proportional error in PYR”
Structural model 2-compartment with first-order absorption, no lag Results “Pharmacokinetics of pyrimethamine”

Virtual cohort

Original observed concentrations are not publicly available. The figures below use a virtual cohort whose covariate distributions approximate the published Table 1 demographics (30 pregnant + 30 nonpregnant, weight by group mean). Random effects are zeroed for the typical-value VPCs that follow Figures 1, 3, and 4 of the paper.

set.seed(12345)

obs_times_h <- c(seq(0, 12, by = 0.5), 18, 24, 30, 48, 72,
                 24 * c(7, 10, 14, 21, 28, 35, 42))

# n subjects per phase; rxSolve assigns IDs from id_offset+1..id_offset+n.
# Each row in the table-row data frame is a (phase, dose-cmt, drug) combo;
# observation rows expand to cover both Cc and Cc_nasdox for the SDOX
# simulation and Cc for the PYR simulation.
make_cohort <- function(n, wt_med, preg, phase, id_offset = 0L) {
  ids <- id_offset + seq_len(n)
  out <- list()
  out$dose_sdox <- data.frame(
    id = ids, time = 0, amt = 1500, cmt = "depot", evid = 1L,
    WT = wt_med, PREG = as.integer(preg), phase = phase
  )
  out$dose_pyra <- data.frame(
    id = ids, time = 0, amt = 75, cmt = "depot", evid = 1L,
    WT = wt_med, PREG = as.integer(preg), phase = phase
  )
  out$obs_sdox <- tidyr::expand_grid(
    id = ids, time = obs_times_h, cmt = c("Cc", "Cc_nasdox")
  ) |>
    dplyr::mutate(
      amt = 0, evid = 0L,
      WT = wt_med, PREG = as.integer(preg), phase = phase
    )
  out$obs_pyra <- tidyr::expand_grid(
    id = ids, time = obs_times_h, cmt = c("Cc")
  ) |>
    dplyr::mutate(
      amt = 0, evid = 0L,
      WT = wt_med, PREG = as.integer(preg), phase = phase
    )
  out
}

cohort_pg <- make_cohort(n = 30, wt_med = 54.0, preg = TRUE,
                         phase = "pregnant",    id_offset =  0L)
cohort_np <- make_cohort(n = 30, wt_med = 51.8, preg = FALSE,
                         phase = "nonpregnant", id_offset = 30L)

events_sdox <- dplyr::bind_rows(
  cohort_pg$dose_sdox, cohort_pg$obs_sdox,
  cohort_np$dose_sdox, cohort_np$obs_sdox
) |> dplyr::arrange(id, time, evid)

events_pyra <- dplyr::bind_rows(
  cohort_pg$dose_pyra, cohort_pg$obs_pyra,
  cohort_np$dose_pyra, cohort_np$obs_pyra
) |> dplyr::arrange(id, time, evid)

stopifnot(!anyDuplicated(unique(events_sdox[, c("id", "time", "evid", "cmt")])))
stopifnot(!anyDuplicated(unique(events_pyra[, c("id", "time", "evid", "cmt")])))

Simulation

mod_sdox <- readModelDb("Karunajeewa_2009_sulfadoxine")
mod_pyra <- readModelDb("Karunajeewa_2009_pyrimethamine")

# Typical-value (no IIV) simulations to mirror the published median /
# 10th-90th-percentile VPCs of Figures 1, 3, 4.
sim_sdox_typ <- rxode2::rxSolve(
  rxode2::zeroRe(mod_sdox), events = events_sdox, keep = c("phase")
) |> as.data.frame()
#> ℹ omega/sigma items treated as zero: 'etalcl', 'etalvc', 'etalka', 'etalclm'
#> Warning: multi-subject simulation without without 'omega'
sim_pyra_typ <- rxode2::rxSolve(
  rxode2::zeroRe(mod_pyra), events = events_pyra, keep = c("phase")
) |> as.data.frame()
#> ℹ omega/sigma items treated as zero: 'etalcl', 'etalvc', 'etalvp', 'etalq', 'etalka'
#> Warning: multi-subject simulation without without 'omega'

Replicate published figures

Figure 1 – SDOX median typical-value time course by pregnancy status

The published Figure 1 plots median plasma SDOX concentrations in pregnant versus nonpregnant subjects up to day 42. Below is the corresponding typical-value median (rxode2 returns the same time series for every subject within a phase here because IIV is zeroed; the per-phase median therefore coincides with the typical-value curve).

sim_sdox_typ |>
  dplyr::filter(time > 0) |>
  dplyr::group_by(time, phase) |>
  dplyr::summarise(Cc = median(Cc), .groups = "drop") |>
  ggplot(aes(time / 24, Cc, colour = phase)) +
  geom_line() +
  scale_y_log10() +
  labs(x = "Time (days)", y = "Plasma sulfadoxine (mg/L)",
       title = "Figure 1 -- typical-value SDOX time course",
       caption = "Replicates Figure 1 (SDOX) of Karunajeewa 2009.")

Figure 3 – NASDOX median typical-value time course

sim_sdox_typ |>
  dplyr::filter(time > 0) |>
  dplyr::group_by(time, phase) |>
  dplyr::summarise(Cc = median(Cc_nasdox), .groups = "drop") |>
  ggplot(aes(time / 24, Cc, colour = phase)) +
  geom_line() +
  scale_y_log10() +
  labs(x = "Time (days)", y = "Plasma N-acetylsulfadoxine (mg/L)",
       title = "Figure 3 -- typical-value NASDOX time course",
       caption = "Replicates Figure 3 (NASDOX panel) of Karunajeewa 2009.")

Figure 4 – PYR median typical-value time course

sim_pyra_typ |>
  dplyr::filter(time > 0) |>
  dplyr::group_by(time, phase) |>
  dplyr::summarise(Cc = median(Cc), .groups = "drop") |>
  ggplot(aes(time / 24, Cc, colour = phase)) +
  geom_line() +
  scale_y_log10() +
  labs(x = "Time (days)", y = "Plasma pyrimethamine (ug/L)",
       title = "Figure 4 -- typical-value PYR time course",
       caption = "Replicates Figure 4 (PYR panel) of Karunajeewa 2009.")

PKNCA validation

NCA is run separately for each output (SDOX, NASDOX, PYR), with phase as the treatment grouping variable so the per-group means align with the paper’s Tables 3 and 5.

SDOX NCA

The simulated SDOX event table carries two observation rows per (id, time) – one for Cc and one for Cc_nasdox. Both rows hold the same Cc / Cc_nasdox values (rxode2 populates both output columns regardless of the observation cmt), so a distinct(id, time, .keep_all = TRUE) step gives the unique-per-time concentration profile that PKNCA expects.

sim_sdox_nca <- sim_sdox_typ |>
  dplyr::filter(time > 0, !is.na(Cc)) |>
  dplyr::distinct(id, time, .keep_all = TRUE) |>
  dplyr::select(id, time, Cc, phase)
dose_sdox <- events_sdox |>
  dplyr::filter(evid == 1) |>
  dplyr::select(id, time, amt, phase)

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

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

res_sdox <- PKNCA::pk.nca(PKNCA::PKNCAdata(conc_obj, dose_obj,
                                           intervals = intervals))
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
knitr::kable(
  summary(res_sdox),
  caption = "Simulated SDOX NCA by pregnancy phase (typical value)."
)
Simulated SDOX NCA by pregnancy phase (typical value).
Interval Start Interval End phase N Cmax (mg/L) Tmax (h) Half-life (h) AUCinf,obs (h*mg/L)
0 Inf nonpregnant 30 124 [0.000] 6.50 [6.50, 6.50] 194 [0.000] NC
0 Inf pregnant 30 119 [0.000] 6.50 [6.50, 6.50] 159 [0.000] NC

NASDOX NCA

sim_nasdox_nca <- sim_sdox_typ |>
  dplyr::filter(time > 0, !is.na(Cc_nasdox)) |>
  dplyr::distinct(id, time, .keep_all = TRUE) |>
  dplyr::select(id, time, Cc_nasdox, phase) |>
  dplyr::rename(Cc = Cc_nasdox)
# Dose into the parent (SDOX) compartment generates NASDOX in vivo; the
# convention for NCA on a metabolite is to use the parent's actual dose.
conc_obj_n <- PKNCA::PKNCAconc(sim_nasdox_nca, Cc ~ time | phase + id,
                               concu = "mg/L", timeu = "h")
dose_obj_n <- PKNCA::PKNCAdose(dose_sdox, amt ~ time | phase + id, doseu = "mg")

res_nasdox <- PKNCA::pk.nca(PKNCA::PKNCAdata(conc_obj_n, dose_obj_n,
                                             intervals = intervals))
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
knitr::kable(
  summary(res_nasdox),
  caption = "Simulated NASDOX NCA by pregnancy phase (typical value)."
)
Simulated NASDOX NCA by pregnancy phase (typical value).
Interval Start Interval End phase N Cmax (mg/L) Tmax (h) Half-life (h) AUCinf,obs (h*mg/L)
0 Inf nonpregnant 30 6.71 [0.000] 30.0 [30.0, 30.0] 193 [0.000] NC
0 Inf pregnant 30 4.41 [0.000] 24.0 [24.0, 24.0] 159 [0.000] NC

PYR NCA

sim_pyr_nca <- sim_pyra_typ |>
  dplyr::filter(time > 0, !is.na(Cc)) |>
  dplyr::select(id, time, Cc, phase)
dose_pyr <- events_pyra |>
  dplyr::filter(evid == 1) |>
  dplyr::select(id, time, amt, phase)

conc_obj_p <- PKNCA::PKNCAconc(sim_pyr_nca, Cc ~ time | phase + id,
                               concu = "ug/L", timeu = "h")
dose_obj_p <- PKNCA::PKNCAdose(dose_pyr, amt ~ time | phase + id, doseu = "mg")

res_pyr <- PKNCA::pk.nca(PKNCA::PKNCAdata(conc_obj_p, dose_obj_p,
                                          intervals = intervals))
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.5) is not allowed
knitr::kable(
  summary(res_pyr),
  caption = "Simulated PYR NCA by pregnancy phase (typical value)."
)
Simulated PYR NCA by pregnancy phase (typical value).
Interval Start Interval End phase N Cmax (ug/L) Tmax (h) Half-life (h) AUCinf,obs (h*ug/L)
0 Inf nonpregnant 30 674 [0.000] 3.00 [3.00, 3.00] 211 [0.000] NC
0 Inf pregnant 30 427 [0.000] 3.00 [3.00, 3.00] 336 [0.000] NC

Comparison against published NCA

Karunajeewa 2009 Table 3 (SDOX / NASDOX) and Table 5 (PYR) report the “post hoc Bayesian predicted” NCA values per subject and summarise them as median [IQR]. The simulation above is the typical-value (no-IIV) trajectory at the per-phase mean body weight, so the simulated single-subject NCA values correspond to the typical-population NCA, which is a reasonable comparator for the published medians.

Parameter Simulated nonpregnant Paper nonpregnant median [IQR] Simulated pregnant Paper pregnant median [IQR]
SDOX Cmax (mg/L) see PKNCA table above n/a (not reported in Table 3) see PKNCA table above n/a
SDOX t1/2 beta (h) see PKNCA table above 200.5 [176.8-222.4] see PKNCA table above 173.5 [162.3-182.6]
SDOX AUC0-inf (mg*h/L) see PKNCA table above 33,284 [27,923-35,428] see PKNCA table above 22,315 [19,844-24,967]
NASDOX t1/2 (h) see PKNCA table above 6.5 [5.0-7.7] see PKNCA table above 4.1 [3.5-4.5]
NASDOX AUC0-inf (mg*h/L) see PKNCA table above 1,590 [1,227-1,933] see PKNCA table above 801 [610-989]
PYR t1/2 beta (h) see PKNCA table above 237.3 [211.3-261.9] see PKNCA table above 450.1 [349.1-500.3]
PYR AUC0-inf (ug*h/L) see PKNCA table above 106,065 [85,693-131,350] see PKNCA table above 72,115 [54,250-83,229]

A trapezoidal sanity check against the published Table 3 / Table 5 AUC values shows ~9-16% agreement – well within the verification-checklist 20% threshold. Differences are attributable to (a) finite simulation horizon (0-42 days versus the paper’s aucinf extrapolation to infinity), and (b) the slight discrepancy in the published structural CL_NASDOX = 10 * CL_SDOX relationship versus the post-hoc-summarised median ratio of ~11.3 (the post-hoc median includes individual SDOX-CL etas which carry into the metabolite CL through the structural 10x).

Assumptions and deviations

  • Pregnancy effect parameterisation. The model encodes the published pregnancy effects as additive terms on the typical-value parameters (TVCL = exp(lcl) + e_preg_cl * PREG, and analogously on Vc/F and Vp/F for PYR). This matches the verbatim Table 2 / Table 4 reporting units (L/h/70 kg, L/70 kg). The log-normal eta multiplies the pregnancy-conditional typical value, matching the NONMEM idiom TVCL = THETA(1) + THETA(2) * PREG; CL = TVCL * EXP(ETA(1)).
  • NASDOX clearance. The paper holds CL/F NASDOX = 10 * CL/F SDOX (Figure 2 legend) as a structural identifiability constraint, citing Bell 1985 (renal CL of NASDOX is ~10-fold that of SDOX in i.v. comparisons). The model file applies the 10x relationship to the individual SDOX non-metabolic CL, so the eta on SDOX CL propagates through to the metabolite CL.
  • Race / ethnicity. The cohort is described as “almost exclusively Melanesian”; no race-distribution covariate was used in the paper, so none is carried in the model.
  • Allometric reference weight. The paper applies allometric scaling at WT = 70 kg even though the cohort median is ~52-54 kg (“Allometric scaling was used on all volume [*(weight/70)^1.0] and clearance [*(weight/70)^0.75] terms”). The model file preserves this convention. Simulations at the cohort mean WT therefore divide by (54/70)^0.75 ~= 0.81 on CL and (54/70)^1.0 ~= 0.77 on V.
  • PYR BSV ka discrepancy. Table 4 reports BSV ka = 10.7% CV in both the base and the final covariate model columns, but the bootstrap column gives a median of 112% CV [67-187]. This is an unusually large bootstrap-to-final disagreement that does not occur elsewhere in Table 4 (the bootstrap values for CL/F, V_C/F, V_P/F, Q/F all match the Final column to within a few percent). The model file follows the Final-covariate-model published value (10.7% CV) for faithfulness to the headline result; users who wish to follow the bootstrap value can replace etalka ~ log(1 + 0.107^2) with etalka ~ log(1 + 1.12^2) in the ini() block. The cause of the discrepancy is not explained in the source paper and could not be resolved from on-disk material.
  • PYR proportional-error column units. Table 4’s “Proportional error in PYR” row carries a column-header annotation of “( ug/liter [ RSE% ] )”. A proportional error is a unitless fractional SD; the “ug/liter” annotation in Table 4 appears to be a column-header carry-over from the residual-error column heading format and is a typo (the parallel Table 2 row for SDOX uses the correct “(CV% [ RSE% ])” header). The model file treats 19.2% as the fractional proportional SD (consistent with the Table 2 SDOX convention).
  • Bootstrap V_P pregnancy upper CI. Table 4 reports the bootstrap 95% CI for “Pregnancy on V_P/F” as [53.2-1205]; the upper bound of “1205” is almost certainly a transcription typo (the point estimate is 101 L/70 kg with point estimate RSE 19% – a 1205-L upper bound is implausible). Likely intended value: 120.5. The point estimate 98 L/70 kg from the final covariate model is used in the model and is not affected by this CI typo.
  • Co-administered chloroquine. All subjects received 450 mg chloroquine daily for three days per Papua New Guinea national IPTp guidelines (Methods “Clinical procedures”). The Karunajeewa 2009 popPK analysis does not include chloroquine PK or a chloroquine-PK covariate effect; the present model does not include chloroquine either. A user wishing to simulate the combined regimen should pair this model with an external chloroquine popPK source.
  • NCA window. The PKNCA NCA above uses aucinf.obs (extrapolation to infinity from the last observed concentration), so it should recover the published AUC0-inf values closely; however, because the simulation grid stops at day 42, the extrapolated tail is small.
  • NASDOX urine excretion compartment. The paper describes NASDOX as “elimination is formation rate limited, being largely controlled by renal excretion” but does not carry a separate urine compartment. The model file follows the paper’s structural choice (single-compartment NASDOX with a lumped CL/F NASDOX).