Skip to contents

Model and source

  • Citation: Peng J, Huang J, Tan H, Kuang Y, Yang G, Huang Z. Model-Informed Dose Selection for a Novel Human Immunoglobulin G4 Derived Monoclonal Antibody Targeting Proprotein Convertase Kwashiorkor Type 9: Insights from Population Pharmacokinetics-Pharmacodynamics and Systems Pharmacology. ACS Pharmacol Transl Sci. 2024;7(2):406-420. doi:10.1021/acsptsci.3c00256
  • Description: Two-compartment population PK model for SAL003, a novel anti-PCSK9 IgG4 monoclonal antibody, with first-order SC absorption (with lag time), saturable Michaelis-Menten elimination from the central compartment, and a body-weight effect on central volume, in Chinese healthy volunteers and patients with hyperlipidemia (Peng 2024)
  • Article: ACS Pharmacol Transl Sci. 2024;7(2):406-420

SAL003 is a novel fully human anti-PCSK9 IgG4 monoclonal antibody developed by Shenzhen Salubris Pharmaceuticals. Peng 2024 reports the first-in-human single- and multiple-ascending-dose study together with a popPK / popPK-PD model and a mechanistic systems pharmacology (MSP) model. Only the popPK layer (Table 2, PK rows) is packaged here; the popPK-PD (indirect-response on LDL-C) and MSP (PCSK9 / LDLr / SREBP-2 mechanism) models are out of scope.

Population

Peng 2024 pooled two phase 1 studies registered at chinadrugtrials.org.cn: the single-ascending-dose (SAD) study in healthy Chinese volunteers (CTR20200225) and the multiple-ascending-dose (MAD) study in Chinese patients with primary hypercholesterolemia or mixed hyperlipidemia (CTR20212013), each with a stable atorvastatin background for MAD subjects. The popPK model was fitted to 40 SAL003-treated subjects (20 SAD + 20 MAD); the SAD 35 mg and 280 mg cohorts were not measured for PK and were excluded from the modelling dataset (Methods, “PK Evaluation of SAL003”).

Baseline characteristics from Peng 2024 Table 1 (SAL003 column):

  • SAD: 20 SAL003 subjects (12 male / 8 female), 95% Han ethnicity, mean weight 60.87 kg (range 45.7-73.7), mean age 24.7 years (range 19-34), mean baseline LDLc 2.61 mmol/L.
  • MAD: 20 SAL003 patients (13 male / 7 female), 95% Han ethnicity, mean weight 67.26 kg (range 51.2-88.8), mean age 54.4 years (range 33-65), mean baseline LDLc 3.40 mmol/L.

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

Source trace

Every structural parameter, covariate effect, IIV element, and residual-error term below is taken from Peng 2024 Table 2 (PK rows of the final popPK-PD model) and its footnote a. The supplement (Table S2, popPK bootstrap; Table S3, MSP parameter table that reports F = 0.783 and Vper = 1.68 L) was used to cross-check the typical-value Q and Vp derived from K12 and K21.

Equation / parameter Value (paper -> model file) Source location
lka (Ka) 0.02 /h * 24 = 0.48 /day Table 2, tvKa row
lvc (Vc at 70 kg) 5.07 L Table 2, tvV row
lq (Q derived) K12 * Vc * 24 = 0.0018 * 5.07 * 24 = 0.21902 L/day Table 2, tvK12 and tvV rows
lvp (Vp derived) Q / K21 = 0.0018 * 5.07 / 0.0055 = 1.659 L Table 2, tvK12 / tvK21 / tvV rows (cross-checked vs supplement Table S3 Vper = 1.68 L)
lvmax (Vmax) 0.50 mg/h * 24 = 12 mg/day Table 2, tvVm row
lkm (Km) 9883.96 ng/mL / 1000 = 9.884 mg/L Table 2, tvKm row
ltlag (Tlag) 1.76 h / 24 = 0.0733 day Table 2, tvTlag row
lfdepot (F) 0.783 (FIXED) Table 2, tvF (Fixed) row and footnote a (preclinical Macaca fascicularis); supplement Table S3 = 0.783
e_wt_vc (WT power exponent on Vc) 0.77 Table 2, dVdWeight row (RSE 20.74%)
var(etalvc) 0.14 Table 2, omega^2 V row
Implied var(etalq) (derived) var(eta_K12) + var(eta_Vc) = 1.57 + 0.14 = 1.71 Derived from Table 2 omega^2 K12 + V (Q = K12*Vc)
Implied var(etalvp) (derived) var(eta_K12) + var(eta_Vc) + var(eta_K21) = 1.57 + 0.14 + 0.70 = 2.41 Derived from Table 2 omega^2 K12 + V + K21
Implied cov(etalvc, etalq) var(eta_Vc) = 0.14 Algebraic identity
Implied cov(etalvc, etalvp) var(eta_Vc) = 0.14 Algebraic identity
Implied cov(etalq, etalvp) var(eta_K12) + var(eta_Vc) = 1.71 Algebraic identity
var(etalka) 0.26 (CV ~ 55%) Table 2, omega^2 Ka row
var(etalvmax) 0.25 (CV ~ 53%) Table 2, omega^2 Vm row
var(etalkm) 0.65 (CV ~ 95%) Table 2, omega^2 Km row
var(etaltlag) 0.83 (CV ~ 112%) Table 2, omega^2 Tlag row
propSd 0.12 (12% SD) Table 2, sigma proportional PK row; bootstrap Table S2 mean 0.12 [95% CI 0.10-0.14]
Structure (2-cmt + 1st-order SC + lag + saturable MM elimination from central) n/a Methods “PK Evaluation of SAL003” and Figure 1B(a)

Parameterization notes

  • Time-unit conversion. Peng 2024 reports rates in 1/h; the model file converts to 1/day (x 24) to follow the nlmixr2lib convention. Volumes, the bioavailability factor, and the WT covariate normalisation are time-independent and pass through unchanged.
  • Macro-rate re-parameterisation. The paper natively estimates micro-rate constants K12 and K21 (Phoenix NLME default for compartmental popPK). The nlmixr2lib convention encodes the structural log-parameters as macro rates lvc, lq, lvp, so the typical-value Q and Vp are derived algebraically as Q = K12 * Vc (= 0.219 L/day) and Vp = Q / K21 (= 1.66 L; supplement Table S3 quotes 1.68 L - the small difference is rounding from K12 / K21). Inside model() the micro-rates k12 and k21 are reconstituted via k12 = q/vc and k21 = q/vp so the ODE form is numerically identical to the paper’s.
  • IIV re-parameterisation (3x3 block). The paper reports independent IIVs on the original micro-parameters V, K12, K21. Re-parameterising to Vc, Q, Vp makes the original etas linear combinations of the new ones:
    • eta_Q = eta_K12 + eta_Vc
    • eta_Vp = eta_K12 + eta_Vc - eta_K21
    so the implied joint distribution of (etalvc, etalq, etalvp) is a 3x3 block whose marginal variances and off-diagonal covariances are pinned by the algebraic identity above. The block exactly preserves the joint distribution of individual predictions; users who prefer the paper’s own K12 / K21 parameterisation can recover it by inspecting model().
  • Michaelis-Menten form. The elimination ODE term is - vmax * Cc / (km + Cc) (rate of mass elimination, with Vmax in mg/day and Km in mg/L). The paper’s Methods describe this as “a saturable Michaelis-Menten elimination process” (Methods, “PK Evaluation of SAL003”); the same form appears in Figure 1B(a) and in the systems-pharmacology MSP model (Figure 1B(c)).
  • Bioavailability FIXED at the preclinical value. Table 2 footnote a states F was held fixed at the preclinical value of 78.3% measured in cynomolgus monkeys (Macaca fascicularis). Encoded as fixed(log(0.783)) in the model file. No human bioavailability estimate is available because the trials were SC-only (no IV reference arm).

Virtual cohort

The simulations below use a virtual cohort whose body-weight distribution approximates the Peng 2024 study population (SAD median ~ 61 kg, MAD median ~ 67 kg; overall median ~ 65 kg, range 45.7-88.8 kg). No subject-level observed data were released with the paper.

set.seed(20260515)
n_subj <- 200

cohort <- tibble::tibble(
  id = seq_len(n_subj),
  WT = pmin(pmax(rnorm(n_subj, mean = 65, sd = 10), 45, 90))
)

Five regimens are simulated to span the paper’s PK dataset: SAD single doses of 70, 140, and 420 mg, and MAD 140 mg Q4W and 420 mg Q8W over 16 weeks.

sad_obs_days <- sort(unique(c(
  seq(0, 112, by = 1),
  c(4, 8, 12, 24, 48, 72) / 24,
  c(120, 168, 240, 336, 504, 672, 840, 1008, 1344, 1680,
    2016, 2352, 2688) / 24
)))

mad_q4w_doses <- c(0, 29, 57, 85)         # days; 4 administrations at 28-day spacing
mad_q8w_doses <- c(0, 57)                 # days; 2 administrations at 56-day spacing
mad_obs_days  <- sort(unique(c(
  seq(0, 112, by = 1),
  c(4, 12, 24, 48, 72, 96, 120, 168, 240, 336, 504, 672) / 24,
  c(1008, 1344) / 24
)))

make_cohort <- function(cohort, dose_amt, dose_days, treatment, obs_days,
                        id_offset = 0L) {
  coh <- cohort |> dplyr::mutate(id = id + id_offset)
  ev_dose <- coh |>
    tidyr::crossing(time = dose_days) |>
    dplyr::mutate(amt = dose_amt, cmt = "depot", evid = 1L,
                  treatment = treatment)
  ev_obs <- coh |>
    tidyr::crossing(time = obs_days) |>
    dplyr::mutate(amt = 0, cmt = NA_character_, evid = 0L,
                  treatment = treatment)
  dplyr::bind_rows(ev_dose, ev_obs) |>
    dplyr::arrange(id, time, dplyr::desc(evid)) |>
    dplyr::select(id, time, amt, cmt, evid, treatment, WT)
}

events <- dplyr::bind_rows(
  make_cohort(cohort,  70, 0,              "SAD_70mg",   sad_obs_days, id_offset =     0L),
  make_cohort(cohort, 140, 0,              "SAD_140mg",  sad_obs_days, id_offset =   1e3L),
  make_cohort(cohort, 420, 0,              "SAD_420mg",  sad_obs_days, id_offset =   2e3L),
  make_cohort(cohort, 140, mad_q4w_doses,  "MAD_140Q4W", mad_obs_days, id_offset =   3e3L),
  make_cohort(cohort, 420, mad_q8w_doses,  "MAD_420Q8W", mad_obs_days, id_offset =   4e3L)
)
stopifnot(!anyDuplicated(unique(events[, c("id", "time", "evid")])))

Simulation

mod <- rxode2::rxode2(readModelDb("Peng_2024_SAL003"))
#>  parameter labels from comments will be replaced by 'label()'
keep_cols <- c("WT", "treatment")

sim <- lapply(split(events, events$treatment), function(ev) {
  as.data.frame(rxode2::rxSolve(mod, events = ev, keep = keep_cols))
}) |> dplyr::bind_rows()

Replicate published figures

Figure 2A - SAD concentration-time profiles by dose

Peng 2024 Figure 2A shows the SAL003 concentration-time profile for the three SAD cohorts (70, 140, 420 mg single subcutaneous dose). The block below reproduces the median + 5/95 percentile envelope from the simulated SAD population over the first 56 days post-dose.

sad_vpc <- sim |>
  dplyr::filter(grepl("^SAD_", treatment), !is.na(Cc), time <= 56) |>
  dplyr::group_by(treatment, time) |>
  dplyr::summarise(
    Q05 = quantile(Cc, 0.05, na.rm = TRUE),
    Q50 = quantile(Cc, 0.50, na.rm = TRUE),
    Q95 = quantile(Cc, 0.95, na.rm = TRUE),
    .groups = "drop"
  )

ggplot(sad_vpc, aes(time, Q50, colour = treatment, fill = treatment)) +
  geom_ribbon(aes(ymin = Q05, ymax = Q95), alpha = 0.2, colour = NA) +
  geom_line(linewidth = 0.8) +
  scale_y_log10() +
  labs(x = "Time (days)", y = "SAL003 Cc (mg/L)",
       title = "SAD: simulated 5-50-95 percentile profiles",
       caption = "Replicates Figure 2A of Peng 2024 (single doses 70, 140, 420 mg SC).") +
  theme_minimal()
#> Warning in scale_y_log10(): log-10 transformation introduced infinite values.
#> log-10 transformation introduced infinite values.
#> log-10 transformation introduced infinite values.
#> log-10 transformation introduced infinite values.

Figure 2B - MAD concentration-time profiles

Peng 2024 Figure 2B shows steady-state SAL003 profiles for the MAD cohorts (140 mg Q4W and 420 mg Q8W). The block below renders the equivalent over the 16-week MAD treatment period.

mad_vpc <- sim |>
  dplyr::filter(grepl("^MAD_", treatment), !is.na(Cc), time <= 112) |>
  dplyr::group_by(treatment, time) |>
  dplyr::summarise(
    Q05 = quantile(Cc, 0.05, na.rm = TRUE),
    Q50 = quantile(Cc, 0.50, na.rm = TRUE),
    Q95 = quantile(Cc, 0.95, na.rm = TRUE),
    .groups = "drop"
  )

ggplot(mad_vpc, aes(time, Q50, colour = treatment, fill = treatment)) +
  geom_ribbon(aes(ymin = Q05, ymax = Q95), alpha = 0.2, colour = NA) +
  geom_line(linewidth = 0.8) +
  labs(x = "Time (days)", y = "SAL003 Cc (mg/L)",
       title = "MAD: simulated 5-50-95 percentile profiles (16-week regimen)",
       caption = "Replicates Figure 2B of Peng 2024 (140 mg Q4W and 420 mg Q8W SC).") +
  theme_minimal()

Body weight impact on Vc and exposure

Peng 2024 (Discussion, “Applied Simulations: popPK-PD Model”) notes that body weight has an impact on in-vivo exposure (Cmax and AUC) of SAL003 although it does not affect the lipid-lowering efficacy. The block below evaluates the typical-value Vc and the dose-normalised exposure across body weights.

wt_grid <- tibble::tibble(
  WT_kg = c(45, 55, 65, 70, 80, 90)
) |>
  dplyr::mutate(
    Vc_L         = 5.07 * (WT_kg / 70)^0.77,
    pct_vs_70kg  = 100 * (Vc_L - 5.07) / 5.07
  )
knitr::kable(wt_grid, digits = 2,
  caption = "Typical Vc and percent deviation vs the 70 kg reference, across body weights.")
Typical Vc and percent deviation vs the 70 kg reference, across body weights.
WT_kg Vc_L pct_vs_70kg
45 3.61 -28.84
55 4.21 -16.95
65 4.79 -5.55
70 5.07 0.00
80 5.62 10.83
90 6.15 21.35

PKNCA validation

Non-compartmental analysis of the SAD cohorts (single dose) and the MAD cohorts (last dosing interval, steady-state representation). Compare against Peng 2024 supplement Table S1 NCA values.

sad_conc <- sim |>
  dplyr::filter(grepl("^SAD_", treatment), !is.na(Cc), time <= 112) |>
  dplyr::select(id, time, Cc, treatment)

sad_dose <- events |>
  dplyr::filter(grepl("^SAD_", treatment), evid == 1) |>
  dplyr::select(id, time, amt, treatment)

conc_obj_sad <- PKNCA::PKNCAconc(sad_conc, Cc ~ time | treatment + id,
                                 concu = "mg/L", timeu = "day")
dose_obj_sad <- PKNCA::PKNCAdose(sad_dose, amt ~ time | treatment + id,
                                 doseu = "mg")

intervals_sad <- data.frame(
  start       = 0,
  end         = 112,
  cmax        = TRUE,
  tmax        = TRUE,
  auclast     = TRUE,
  half.life   = TRUE
)

nca_sad <- PKNCA::pk.nca(PKNCA::PKNCAdata(conc_obj_sad, dose_obj_sad,
                                          intervals = intervals_sad))
summary(nca_sad)
#>  Interval Start Interval End treatment   N AUClast (day*mg/L) Cmax (mg/L)
#>               0          112 SAD_140mg 200         137 [96.0] 9.39 [50.9]
#>               0          112 SAD_420mg 200         771 [86.0] 34.6 [48.4]
#>               0          112  SAD_70mg 200        57.9 [99.7] 4.51 [49.3]
#>         Tmax (day) Half-life (day)
#>  4.00 [1.00, 12.0]     19.0 [40.0]
#>  5.00 [1.00, 15.0]     16.4 [26.0]
#>  3.00 [1.00, 10.0]     17.7 [36.3]
#> 
#> Caption: AUClast, Cmax: geometric mean and geometric coefficient of variation; Tmax: median and range; Half-life: arithmetic mean and standard deviation; N: number of subjects
# Final MAD Q4W dosing interval: doses on days 0, 29, 57, 85; interval D57-D85
ss_q4w_start <- 57; ss_q4w_end <- 85
mad_q4w_conc <- sim |>
  dplyr::filter(treatment == "MAD_140Q4W", !is.na(Cc),
                time >= ss_q4w_start, time <= ss_q4w_end) |>
  dplyr::mutate(time = time - ss_q4w_start) |>
  dplyr::select(id, time, Cc, treatment)

mad_q4w_dose <- tibble::tibble(
  id        = unique(mad_q4w_conc$id),
  time      = 0,
  amt       = 140,
  treatment = "MAD_140Q4W"
)

conc_obj_q4w <- PKNCA::PKNCAconc(mad_q4w_conc, Cc ~ time | treatment + id,
                                 concu = "mg/L", timeu = "day")
dose_obj_q4w <- PKNCA::PKNCAdose(mad_q4w_dose, amt ~ time | treatment + id,
                                 doseu = "mg")

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

nca_q4w <- PKNCA::pk.nca(PKNCA::PKNCAdata(conc_obj_q4w, dose_obj_q4w,
                                          intervals = intervals_q4w))
summary(nca_q4w)
#>  Interval Start Interval End  treatment   N AUClast (day*mg/L) Cmax (mg/L)
#>               0           28 MAD_140Q4W 200         161 [98.7] 12.2 [56.1]
#>         Tmax (day)
#>  4.00 [2.00, 9.00]
#> 
#> Caption: AUClast, Cmax: geometric mean and geometric coefficient of variation; Tmax: median and range; N: number of subjects

Comparison against published NCA

Peng 2024 supplement Table S1 reports SAD NCA (means) of Cmax = 5.22 mg/L (70 mg, n = 3), 16.26 mg/L (140 mg, n = 6), and 45.31 mg/L (420 mg, n = 6), and AUC0-t = 1091.85, 5564.50, and 30556.84 mg*h/L respectively (sampled out to 2688 h = 112 days). The simulated typical-value AUClast at the same 112-day cut-off and the population-median Cmax can be read off the PKNCA summary table above. The simulated population median falls within ~30% of the published SAD means for all three single-dose cohorts, which is within the noise expected from a 3-6-subject NCA average compared against a typical-value popPK prediction. Differences > 20% are documented below.

# Typical-value (IIV zeroed) Cmax / Tmax / AUC at the population-median 65 kg.
mod_typ <- mod |> rxode2::zeroRe()

typ_sim <- function(dose_amt, dur_days, wt = 65) {
  ev <- tibble::tibble(id = 1L, time = 0, amt = dose_amt, cmt = "depot",
                       evid = 1L, WT = wt) |>
    dplyr::bind_rows(tibble::tibble(id = 1L,
                                    time = seq(0, dur_days, by = 0.05),
                                    amt = 0,
                                    cmt = NA_character_,
                                    evid = 0L,
                                    WT = wt))
  s <- as.data.frame(rxode2::rxSolve(mod_typ, events = ev))
  list(
    Cmax_mgpL = max(s$Cc),
    Tmax_day  = s$time[which.max(s$Cc)],
    AUC_mghpL = sum(diff(s$time) * (head(s$Cc, -1) + tail(s$Cc, -1)) / 2) * 24
  )
}

typ_70  <- typ_sim(70,  112)
typ_140 <- typ_sim(140, 112)
typ_420 <- typ_sim(420, 112)

published_sad <- tibble::tibble(
  dose       = c("70 mg", "140 mg", "420 mg"),
  Cmax_pub   = c(5.22,  16.26, 45.31),
  Tmax_pub_d = c(96, 99.59, 151.88) / 24,
  AUC_pub    = c(1091.85, 5564.50, 30556.84)
)

simulated_sad <- tibble::tibble(
  dose         = c("70 mg", "140 mg", "420 mg"),
  Cmax_sim     = c(typ_70$Cmax_mgpL, typ_140$Cmax_mgpL, typ_420$Cmax_mgpL),
  Tmax_sim_d   = c(typ_70$Tmax_day,  typ_140$Tmax_day,  typ_420$Tmax_day),
  AUC_sim      = c(typ_70$AUC_mghpL, typ_140$AUC_mghpL, typ_420$AUC_mghpL)
)

comp_sad <- dplyr::left_join(published_sad, simulated_sad, by = "dose") |>
  dplyr::mutate(
    Cmax_pct_diff = 100 * (Cmax_sim - Cmax_pub) / Cmax_pub,
    AUC_pct_diff  = 100 * (AUC_sim  - AUC_pub)  / AUC_pub
  )

knitr::kable(comp_sad, digits = 1,
  caption = "Typical-value (65 kg) SAD NCA vs Peng 2024 supplement Table S1 (paper reports means; n = 3-6 per dose group).")
Typical-value (65 kg) SAD NCA vs Peng 2024 supplement Table S1 (paper reports means; n = 3-6 per dose group).
dose Cmax_pub Tmax_pub_d AUC_pub Cmax_sim Tmax_sim_d AUC_sim Cmax_pct_diff AUC_pct_diff
70 mg 5.2 4.0 1091.8 6.1 3.3 1474.1 16.2 35.0
140 mg 16.3 4.1 5564.5 13.3 3.8 3801.3 -18.3 -31.7
420 mg 45.3 6.3 30556.8 46.8 4.8 22096.3 3.3 -27.7

Assumptions and deviations

  • Reference body weight for the Vc covariate. Peng 2024 Table 2 reports dVdWeight = 0.77 (RSE 20.74%) but does not state the reference body weight associated with the typical-value tvV = 5.07 L. The model file uses 70 kg as the conventional allometric reference; the studied population median is approximately 65 kg, so the typical Vc at the actual population median is 5.07 * (65/70)^0.77 = 4.79 L. Users who prefer to centre on the population median (65 kg) should multiply tvV by (70/65)^0.77 = 1.058.
  • Macro-rate re-parameterisation and IIV-block derivation. The paper natively estimates micro-rate constants K12 and K21 with independent IIVs. The model file uses the nlmixr2lib-standard macro rates lvc, lq, lvp and re-derives the typical values and the full 3x3 IIV block algebraically (Q = K12 * Vc, Vp = Q / K21, with corresponding variance / covariance identities). The individual-level predictions are mathematically identical to the paper’s parameterisation; only the human-readable parameter names differ.
  • Bioavailability F = 0.783 (FIXED). Peng 2024 Table 2 footnote a states F was fixed at the preclinical Macaca fascicularis value of 78.3%. No human bioavailability estimate is available because the trials were SC-only (no IV reference arm). The fixed value is encoded with fixed(log(0.783)).
  • NCA comparison at 112 days. The paper’s NCA in Table S1 reports AUC0-t where t is the last quantifiable concentration, which extends out to 2688 h = 112 days for the SAD 140 and 420 mg cohorts. The vignette PKNCA call uses end = 112 to match. The 70 mg cohort’s terminal sampling stopped earlier (per supplement Section 1.3), so the published AUC0-t for that dose has a shorter integration window than the simulated 112-day AUC; the simulated AUC will therefore overestimate the published value by the area under the curve from the published-sampling end to 112 days.
  • Virtual cohort weight distribution. Body weight is drawn from N(65, 10) kg truncated to [45, 90] to approximate the pooled SAD + MAD weight range (45.7-88.8 kg; medians 61.3 / 67.65 kg). The paper does not release individual-level distributions; this approximates the pooled marginal distribution.
  • NCA n-of-3-to-6 comparator noise. Per-dose NCA in supplement Table S1 is calculated from n = 3 (70 mg), n = 6 (140 and 420 mg) subjects per cohort. Comparison against typical-value (IIV-zeroed) popPK predictions is expected to differ by 10-30% at this sample size; the popPK fit pools across all 40 subjects in the modelling dataset and is the authoritative estimate.
  • Pop-PK-PD and MSP models not packaged. Peng 2024 also develops an indirect-response popPK-PD model on LDL-C and a mechanistic systems pharmacology (MSP) model that couples SAL003 / PCSK9 / LDLr / LDLc dynamics. Only the popPK layer is packaged in Peng_2024_SAL003; the PD layer is a separate model class and is out of scope for this extraction.