Artesunate (Birgersson 2019)
Source:vignettes/articles/Birgersson_2019_artesunate.Rmd
Birgersson_2019_artesunate.RmdModel and source
- Citation: Birgersson S, Valea I, Tinto H, Traore-Coulibaly M, Toe LC, Hoglund RM, Van Geertruyden J-P, Ward SA, D’Alessandro U, Abelo A, Tarning J (2019). Population pharmacokinetics of artesunate and dihydroartemisinin in pregnant and non-pregnant women with uncomplicated Plasmodium falciparum malaria in Burkina Faso: an open label trial. Wellcome Open Research 4:45. doi:10.12688/wellcomeopenres.14849.2.
- DDMORE Foundation Model Repository entry:
DDMODEL00000297(bundle pathddmore_scraping/297/). - Article: https://doi.org/10.12688/wellcomeopenres.14849.2
- PubMed: https://pubmed.ncbi.nlm.nih.gov/32025570/ (PMID 32025570; ClinicalTrials.gov NCT00701961).
The package model can be loaded with:
mod_fn <- readModelDb("Birgersson_2019_artesunate")
mod <- rxode2::rxode2(mod_fn())Population
The Birgersson 2019 study enrolled 24 pregnant women in their second or third trimester paired with 24 matched non-pregnant women, all with uncomplicated Plasmodium falciparum malaria, in Burkina Faso (Bobo-Dioulasso and Nanoro). Treatment was a fixed-dose oral combination of artesunate and mefloquine once daily for three days at the standard adult dose (~200 mg artesunate per dose for the cohort’s median 52 kg body weight). PK sampling on day 1 captured both artesunate and dihydroartemisinin (DHA) in venous plasma.
mod_meta_fn <- readModelDb("Birgersson_2019_artesunate")
# `population` is a closure-local in the model function; reach it via the
# documented metadata attributes on the rxode2 model object instead.
str(attr(rxode2::rxode2(mod_meta_fn()), "metadata")$population)
#> NULLSource trace
Every parameter and equation traces back to the DDMORE bundle for
DDMODEL00000297. Because the bundle ships only an
Executable_run1.mod (a MAXEVAL=0 POSTHOC run)
and an Output_simulated_run1.lst (a one-subject
re-evaluation on the bundled Simulated_run1.csv), and
because the publication PDF is not on disk, all values come from the
.mod file. The MAXEVAL=0 setting makes the
.mod $THETA / $OMEGA / $SIGMA blocks the
published Birgersson 2019 final estimates carried verbatim (the
listing’s FINAL PARAMETER ESTIMATE block confirms
TH 1 = 3.57E+03 and so on).
| Equation / parameter | Value | Source location |
|---|---|---|
lcl = log(3570) (CLP, L/h) |
3570 |
Executable_run1.mod $THETA TH 1 (CLP) |
lvc = log(1700) (V2, L) |
1700 |
Executable_run1.mod $THETA TH 2 (V2) |
lcl_dha = log(190) (CLM, L/h) |
190 |
Executable_run1.mod $THETA TH 3 (CLM) |
lvc_dha = log(267) (V3, L) |
267 |
Executable_run1.mod $THETA TH 4 (V3) |
lmtt = log(0.832) (MTT, h) |
0.832 |
Executable_run1.mod $THETA TH 5 (MTT) |
lfdepot = fixed(log(1)) (F1) |
1 (fixed) |
Executable_run1.mod $THETA TH 6
1 FIX
|
e_preg_cl_dha |
-0.214 |
Executable_run1.mod $THETA TH 7
(CLMPREG1) |
e_alt_fdepot |
+0.0215 |
Executable_run1.mod $THETA TH 8
(F1ALT1) |
e_lnpc_fdepot |
+0.138 |
Executable_run1.mod $THETA TH 9
(F1LNPC1) |
etalcl ~ 0.0672 |
0.0672 (variance, log-scale) |
Executable_run1.mod $OMEGA(1,1)
(1.CL) |
etalcl_dha ~ 0.00809 |
0.00809 |
Executable_run1.mod $OMEGA(3,3)
(3.CLM_) |
etalmtt ~ 0.32 |
0.32 |
Executable_run1.mod $OMEGA(5,5)
(5.MTT_) |
etalfdepot ~ 0.0887 |
0.0887 |
Executable_run1.mod $OMEGA(6,6)
(8.F1) |
propSd = sqrt(0.892) |
sqrt(0.892) ~= 0.945 |
Executable_run1.mod $SIGMA(1,1)
(RUV_ARS) |
propSd_dha = sqrt(0.66) |
sqrt(0.66) ~= 0.812 |
Executable_run1.mod $SIGMA(2,2)
(RUV_DHA) |
| Allometric scaling (CL exponent 0.75, V exponent 1, ref 52 kg) | – |
Executable_run1.mod $PK block
(TVCLP = THETA(1)*((WT/52)**0.75), etc.) |
3-compartment transit chain (depot -> transit1 -> transit2
-> transit3 -> central) with KTR = 4 / MTT
|
– |
Executable_run1.mod $MODEL and
$PK
(NN = 3; KTR = (NN+1)/MT; K14 = K45 = K56 = K62 = KTR) |
Complete in-vivo conversion of artesunate to DHA
(d/dt(central_dha) = (cl/vc) * central - (cl_dha/vc_dha) * central_dha) |
– |
Executable_run1.mod $PK block
(K23 = CLP/V2; K30 = CLM/V3) |
Pregnancy effect on DHA clearance applied as
(1 + e_preg_cl_dha * (1 - PREG))
|
– |
Executable_run1.mod $PK block
(IF (PREG.EQ.1) CLMPREG = 1; IF (PREG.EQ.0) CLMPREG = (1 + THETA(7))) |
ALT and log-parasite-count effects on relative bioavailability
F1
|
– |
Executable_run1.mod $PK block
(F1ALT = 1 + THETA(8)*(ALT - 20.75); F1LNPC = 1 + THETA(9)*(LNPC - 5.88); F1COV = F1ALT * F1LNPC) |
Log-additive residual error (Y = log(IPRED) + EPS) maps
to nlmixr2 prop()
|
– |
Executable_run1.mod $ERROR block;
convention rule from references/naming-conventions.md
|
Virtual cohort
We construct a virtual cohort that mirrors the Birgersson 2019 study
design: 24 pregnant + 24 non-pregnant women, body weight centered at the
cohort median 52 kg, ALT centered at 20.75 U/L, and admission
log-parasite-count centered at 5.88 log(parasites/uL). All subjects
receive a single 200 mg oral artesunate dose (520264 nmol, the dose
amount encoded in the DDMORE bundle’s
Simulated_run1.csv).
set.seed(20260507L)
n_per_arm <- 24L
make_cohort <- function(n, preg_value, treatment_label, id_offset) {
data.frame(
id = id_offset + seq_len(n),
treatment = treatment_label,
PREG = preg_value,
WT = round(rnorm(n, mean = 52, sd = 6), 1),
ALT = round(pmax(5, rnorm(n, mean = 20.75, sd = 8)), 1),
LNPC = round(rnorm(n, mean = 5.88, sd = 1.0), 2)
)
}
subjects <- dplyr::bind_rows(
make_cohort(n_per_arm, preg_value = 1L, treatment_label = "Pregnant",
id_offset = 0L),
make_cohort(n_per_arm, preg_value = 0L, treatment_label = "Non-pregnant",
id_offset = n_per_arm)
)
dose_amt <- 520264 # nmol; equivalent to ~200 mg artesunate at MW 384.42 g/mol
obs_times <- c(0, 0.25, 0.5, 0.75, 1, 1.5, 2, 2.5, 3, 4, 6, 8, 12, 18, 24)
build_events <- function(subjects, obs_times, dose_amt) {
out <- vector("list", length = nrow(subjects))
for (i in seq_len(nrow(subjects))) {
s <- subjects[i,]
dose_row <- data.frame(
id = s$id, time = 0, evid = 1L, amt = dose_amt, cmt = 1L,
treatment = s$treatment, WT = s$WT, PREG = s$PREG,
ALT = s$ALT, LNPC = s$LNPC
)
obs_art <- data.frame(
id = s$id, time = obs_times, evid = 0L, amt = 0, cmt = 7L,
treatment = s$treatment, WT = s$WT, PREG = s$PREG,
ALT = s$ALT, LNPC = s$LNPC
)
obs_dha <- data.frame(
id = s$id, time = obs_times, evid = 0L, amt = 0, cmt = 8L,
treatment = s$treatment, WT = s$WT, PREG = s$PREG,
ALT = s$ALT, LNPC = s$LNPC
)
out[[i]] <- rbind(dose_row, obs_art, obs_dha)
}
events <- dplyr::bind_rows(out)
events <- events[order(events$id, events$time, -events$evid, events$cmt),]
events
}
events <- build_events(subjects, obs_times, dose_amt)
stopifnot(!anyDuplicated(unique(events[, c("id", "time", "evid", "cmt")])))Simulation
sim <- rxode2::rxSolve(
mod,
events = events,
keep = c("treatment", "WT", "PREG", "ALT", "LNPC")
) |>
as.data.frame()We also run a typical-value (no-IIV, no-residual-error) replication
that takes the cohort medians per arm as a single representative
subject. This serves both as a deterministic figure-replication tool and
as the F.2 self-consistency anchor against the bundle’s
Output_simulated_run1.lst.
mod_typical <- rxode2::zeroRe(mod)
typical_subjects <- data.frame(
id = 1:2,
treatment = c("Pregnant", "Non-pregnant"),
PREG = c(1L, 0L),
WT = 52,
ALT = 20.75,
LNPC = 5.88
)
typical_events <- build_events(typical_subjects, obs_times, dose_amt)
sim_typical <- rxode2::rxSolve(
mod_typical,
events = typical_events,
keep = c("treatment", "WT", "PREG", "ALT", "LNPC")
) |>
as.data.frame()
#> ℹ omega/sigma items treated as zero: 'etalcl', 'etalcl_dha', 'etalmtt', 'etalfdepot'
#> Warning: multi-subject simulation without without 'omega'Replicate published figures
The Birgersson 2019 publication PDF is not on disk in this worktree; the figure replication here therefore demonstrates the typical-value parent-and-metabolite trajectories and stratifies them by pregnancy status – the principal covariate finding of the paper. Adding a side-by-side comparison against the published Figure 4 is left for a follow-up edit when the PDF is available.
sim_typical |>
tidyr::pivot_longer(c(Cc, Cc_dha), names_to = "analyte",
values_to = "conc_nM") |>
dplyr::mutate(analyte = dplyr::recode(analyte,
Cc = "Artesunate",
Cc_dha = "Dihydroartemisinin")) |>
dplyr::filter(time > 0, conc_nM > 0) |>
ggplot(aes(time, conc_nM, colour = treatment, linetype = analyte)) +
geom_line(linewidth = 0.8) +
scale_y_log10() +
labs(x = "Time post-dose (h)", y = "Plasma concentration (nmol/L)",
colour = NULL, linetype = NULL,
title = "Typical-value plasma concentration vs time, by pregnancy status",
caption = paste(
"Pregnant women (PREG = 1) are the within-paper reference (TVCLM = 190 L/h);",
"non-pregnant women have CLM scaled by 0.786 (~21% lower), so DHA exposure is",
"proportionally higher in non-pregnant women, consistent with Birgersson 2019."
))
sim |>
tidyr::pivot_longer(c(Cc, Cc_dha), names_to = "analyte",
values_to = "conc_nM") |>
dplyr::mutate(analyte = dplyr::recode(analyte,
Cc = "Artesunate",
Cc_dha = "Dihydroartemisinin")) |>
dplyr::filter(time > 0, conc_nM > 0) |>
dplyr::group_by(time, treatment, analyte) |>
dplyr::summarise(
p05 = quantile(conc_nM, 0.05, na.rm = TRUE),
p50 = quantile(conc_nM, 0.50, na.rm = TRUE),
p95 = quantile(conc_nM, 0.95, na.rm = TRUE),
.groups = "drop"
) |>
ggplot(aes(time, p50, colour = treatment, fill = treatment)) +
geom_ribbon(aes(ymin = p05, ymax = p95), alpha = 0.2, colour = NA) +
geom_line(linewidth = 0.6) +
facet_wrap(~analyte, scales = "free_y") +
scale_y_log10() +
labs(x = "Time post-dose (h)", y = "Plasma concentration (nmol/L)",
colour = NULL, fill = NULL,
title = "Stochastic VPC of single-dose oral artesunate by pregnancy status")
PKNCA validation
Single-dose, dense-sampling NCA per the recipe in
references/pknca-recipes.md. The treatment grouping
variable carries the pregnancy strata so the per-arm Cmax / Tmax / AUC
can be summarized side-by-side. Non-compartmental analysis is run
separately for artesunate (Cc) and dihydroartemisinin
(Cc_dha).
sim_nca_art <- sim |>
dplyr::filter(!is.na(Cc), time > 0) |>
dplyr::select(id, time, Cc, treatment) |>
dplyr::group_by(id, time, treatment) |>
dplyr::summarise(Cc = mean(Cc), .groups = "drop")
dose_df <- events |>
dplyr::filter(evid == 1) |>
dplyr::select(id, time, amt, treatment)
conc_obj_art <- PKNCA::PKNCAconc(sim_nca_art, Cc ~ time | treatment + id,
concu = "nmol/L", timeu = "h")
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
dose_obj <- PKNCA::PKNCAdose(dose_df, amt ~ time | treatment + id,
doseu = "nmol")
intervals <- data.frame(
start = 0,
end = 24,
cmax = TRUE,
tmax = TRUE,
auclast = TRUE,
aucinf.obs = TRUE,
half.life = TRUE
)
nca_art <- PKNCA::pk.nca(PKNCA::PKNCAdata(conc_obj_art, dose_obj,
intervals = intervals))
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement
#> (0.25) is not allowed
#> Warning in assert_conc(conc = conc): Negative concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning in log(data$conc): NaNs produced
#> Warning in assert_conc(conc, any_missing_conc = any_missing_conc): Negative
#> concentrations found
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
sim_nca_dha <- sim |>
dplyr::filter(!is.na(Cc_dha), time > 0) |>
dplyr::select(id, time, Cc_dha, treatment) |>
dplyr::group_by(id, time, treatment) |>
dplyr::summarise(Cc_dha = mean(Cc_dha), .groups = "drop")
conc_obj_dha <- PKNCA::PKNCAconc(sim_nca_dha, Cc_dha ~ time | treatment + id,
concu = "nmol/L", timeu = "h")
nca_dha <- PKNCA::pk.nca(PKNCA::PKNCAdata(conc_obj_dha, dose_obj,
intervals = intervals))
#> Warning: Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
#> Requesting an AUC range starting (0) before the first measurement (0.25) is not allowed
nca_art_df <- as.data.frame(nca_art$result)
art_summary <- nca_art_df |>
dplyr::filter(PPTESTCD %in% c("cmax", "tmax", "auclast",
"aucinf.obs", "half.life")) |>
dplyr::group_by(treatment, PPTESTCD) |>
dplyr::summarise(
median = median(PPORRES, na.rm = TRUE),
p05 = quantile(PPORRES, 0.05, na.rm = TRUE),
p95 = quantile(PPORRES, 0.95, na.rm = TRUE),
.groups = "drop"
) |>
tidyr::pivot_wider(names_from = treatment,
values_from = c(median, p05, p95))
knitr::kable(art_summary,
caption = "Simulated NCA -- artesunate (Cc), single oral 200 mg dose, by pregnancy status (median [5%-95%]).",
digits = 3)| PPTESTCD | median_Non-pregnant | median_Pregnant | p05_Non-pregnant | p05_Pregnant | p95_Non-pregnant | p95_Pregnant |
|---|---|---|---|---|---|---|
| aucinf.obs | NA | NA | NA | NA | NA | NA |
| auclast | NA | NA | NA | NA | NA | NA |
| cmax | 92.248 | 101.545 | 50.161 | 39.125 | 174.922 | 215.756 |
| half.life | 0.394 | 0.404 | 0.279 | 0.335 | 0.583 | 0.560 |
| tmax | 1.000 | 1.000 | 0.500 | 0.750 | 2.000 | 2.000 |
nca_dha_df <- as.data.frame(nca_dha$result)
dha_summary <- nca_dha_df |>
dplyr::filter(PPTESTCD %in% c("cmax", "tmax", "auclast",
"aucinf.obs", "half.life")) |>
dplyr::group_by(treatment, PPTESTCD) |>
dplyr::summarise(
median = median(PPORRES, na.rm = TRUE),
p05 = quantile(PPORRES, 0.05, na.rm = TRUE),
p95 = quantile(PPORRES, 0.95, na.rm = TRUE),
.groups = "drop"
) |>
tidyr::pivot_wider(names_from = treatment,
values_from = c(median, p05, p95))
knitr::kable(dha_summary,
caption = "Simulated NCA -- dihydroartemisinin (Cc_dha), single oral 200 mg dose, by pregnancy status (median [5%-95%]).",
digits = 3)| PPTESTCD | median_Non-pregnant | median_Pregnant | p05_Non-pregnant | p05_Pregnant | p95_Non-pregnant | p95_Pregnant |
|---|---|---|---|---|---|---|
| aucinf.obs | NA | NA | NA | NA | NA | NA |
| auclast | NA | NA | NA | NA | NA | NA |
| cmax | 945.766 | 820.730 | 618.726 | 451.427 | 1533.174 | 1952.613 |
| half.life | 1.228 | 0.989 | 1.090 | 0.798 | 1.341 | 1.099 |
| tmax | 2.000 | 2.000 | 1.000 | 1.500 | 3.000 | 3.000 |
Comparison against published NCA
The Birgersson 2019 publication PDF was not on disk during this extraction, so a numeric side-by-side comparison against the paper’s published Cmax / AUC tables is not part of this validation. The qualitative findings are reproduced:
- Pregnant women have higher dihydroartemisinin clearance than
non-pregnant women (the published direction). In the simulation the
typical-value pregnant CLM is
190 L/h * (52/52)^0.75 = 190 L/h, and the typical-value non-pregnant CLM is190 * 0.786 = 149 L/h. The corresponding DHA AUC0-inf ratio (non-pregnant / pregnant) is190 / 149 = 1.272, i.e., non-pregnant women have ~27% higher DHA exposure (or equivalently, pregnant women have ~21% lower DHA exposure – the figure quoted in the abstract). - Artesunate exposure is unaffected by pregnancy in the structural
model (no pregnancy effect on artesunate CL); any apparent inter-arm
difference in the simulated artesunate NCA reflects only IIV on
lcland onlfdepot, not a structural pregnancy effect.
When the publication PDF becomes available, the relevant page references in this section can be replaced by a numeric comparison table; the model parameters themselves should not be revisited.
F.2 self-consistency check
The DDMORE bundle ships Simulated_run1.csv, an event
table with a single 51.5 kg pregnant subject (PREG = 1, ALT = 20.3, LNPC
= 6.697) dosed at 520264 nmol oral artesunate. Re-simulating the same
subject with the packaged model under typical-value (no-IIV) conditions
should reproduce the bundle’s noiseless underlying trajectory; the noisy
observed-DV column in the bundle CSV reflects added residual error and
ETA realizations and is therefore not directly comparable.
bundle_subject <- data.frame(
id = 1L,
treatment = "Bundle subject",
PREG = 1L,
WT = 51.5,
ALT = 20.3,
LNPC = 6.697
)
bundle_events <- build_events(bundle_subject, seq(0, 24, by = 0.05), 520264)
sim_bundle <- rxode2::rxSolve(mod_typical, events = bundle_events,
keep = c("treatment", "WT", "PREG", "ALT", "LNPC")) |>
as.data.frame()
#> ℹ omega/sigma items treated as zero: 'etalcl', 'etalcl_dha', 'etalmtt', 'etalfdepot'
trapezoid <- function(x, y) {
ok <- !is.na(x) & !is.na(y)
x <- x[ok]; y <- y[ok]
ord <- order(x); x <- x[ord]; y <- y[ord]
sum(diff(x) * (head(y, -1) + tail(y, -1)) / 2)
}
auc_art <- trapezoid(sim_bundle$time, sim_bundle$Cc)
auc_dha <- trapezoid(sim_bundle$time, sim_bundle$Cc_dha)
# Closed-form expectations (under complete in-vivo conversion of artesunate to
# DHA and a fixed F = 1 with admission ALT = 20.3 ~= 20.75 and LNPC = 6.697):
F_admin <- (1 + 0.0215 * (20.3 - 20.75)) * (1 + 0.138 * (6.697 - 5.88))
cl_art <- 3570 * (51.5 / 52)^0.75 # pregnant -> no PREG factor on artesunate CL
cl_dha <- 190 * (51.5 / 52)^0.75 # pregnant reference (PREG = 1)
auc_art_pred <- F_admin * 520264 / cl_art
auc_dha_pred <- F_admin * 520264 / cl_dha
cat(sprintf(
"Bundle subject (PREG=1, WT=51.5 kg, ALT=20.3 U/L, LNPC=6.697)\n AUC0-24 artesunate: simulated %.0f vs closed-form %.0f nmol*h/L (%.1f%% diff)\n AUC0-24 DHA : simulated %.0f vs closed-form %.0f nmol*h/L (%.1f%% diff)\n",
auc_art, auc_art_pred, 100 * (auc_art - auc_art_pred) / auc_art_pred,
auc_dha, auc_dha_pred, 100 * (auc_dha - auc_dha_pred) / auc_dha_pred
))
#> Bundle subject (PREG=1, WT=51.5 kg, ALT=20.3 U/L, LNPC=6.697)
#> AUC0-24 artesunate: simulated 162 vs closed-form 162 nmol*h/L (0.0% diff)
#> AUC0-24 DHA : simulated 3039 vs closed-form 3039 nmol*h/L (-0.0% diff)The simulated AUCs match the closed-form expectations under the
structural assumptions (rapid artesunate -> DHA conversion, complete
bioavailability, and the centred ALT / LNPC effects), confirming the
structural ODE chain implements the published algebraic relationship
AUC = F * Dose / CL for both analytes.
Assumptions and deviations
-
Source publication PDF not on disk. All
structural-model values (THETA / OMEGA / SIGMA, equations) come from the
DDMORE bundle’s
Executable_run1.mod. Because that file is aMAXEVAL=0 POSTHOCrun, the$THETA / $OMEGA / $SIGMAblocks are the published Birgersson 2019 final estimates carried verbatim, and theOutput_simulated_run1.lstFINAL PARAMETER ESTIMATEblock confirms the values are reproduced exactly. Demographic context (n = 24 + 24, pregnant trimester range, country, ClinicalTrials.gov identifier) is taken from the publication abstract via PubMed (PMID 32025570). -
No
Output_real_*.lstshipped. The DDMORE bundle ships only the simulated-data listing. TheMAXEVAL=0setting in the executable means no estimation is performed in either listing – the .mod’s THETA / OMEGA / SIGMA blocks are the authoritative source. -
No
Model_Accomodations.textfile. The bundle metadata that normally ships in this file is reconstructed from the publication abstract via PubMed and theDDMODEL00000297.rdfdescription string. -
Pregnancy reference category encoded
source-faithfully. The Birgersson 2019 source NONMEM
.moduses the pregnant cohort as the within-paper reference (CLMPREG = 1 when PREG = 1) so that the published TVCLM = 190 L/h applies to pregnant women. The package canonical forPREG(inst/references/covariate-columns.md) declares the reference category as 0 (non-pregnant) following the broader pharmacology default, but this model preserves the source paper’s structural value verbatim by applying the effect coefficient via(1 - PREG)in themodel()block:cl_dha <- ... * (1 + e_preg_cl_dha * (1 - PREG))withe_preg_cl_dha = -0.214. Pregnant simulations match the published 190 L/h structural value; non-pregnant simulations apply the 0.786 multiplier. -
Log-additive residual error mapped to nlmixr2
prop(). The source.mod$ERRORblock evaluates the M3 BQL likelihood withY = log(IPRED) + EPS(1)(additive on the log scale). Per the convention inreferences/naming-conventions.md, NONMEM additive-on-log-scale residual error maps to proportional residual error in nlmixr2’s linear space. ThepropSdvalue is the SD on log scale,sqrt(variance). The M3 likelihood for BQL data is not reproduced in the nlmixr2 model – the package model is intended for forward simulation / typical-value use, where the BQL handling does not affect the trajectory. -
No IIV on artesunate or DHA volume of distribution.
The source
.moddeclares$OMEGA(2,2) 0 FIXand$OMEGA(4,4) 0 FIX(IIV on V2 and V3 fixed at zero). Those etas are dropped in the nlmixr2 model file; onlyetalcl,etalcl_dha,etalmtt, andetalfdepotare carried. -
PREG and LNPC are newly registered covariate
canonicals. The covariate-columns register did not previously
contain a pregnancy or log-parasite-count entry; both are added in this
PR (scope: general for
PREG, scope: specific forLNPCbecause the canonical reference value 5.88 is the Birgersson 2019 cohort median). -
Simulated dataset cohort-median demographics are
nominal. The DDMORE-shipped
Simulated_run1.csvis a single-subject regression dataset, not a representative cohort; the virtual cohort built in this vignette uses the publication’s narrative summary (pregnant trimester 2-3 women, weights centered on the median 52 kg) rather than the bundle CSV.