Structural identifiability of reference PK/PD models

library(pkident)

pkident decides local structural identifiability: whether the unknown parameters of an ODE model are determined, in a neighbourhood of their values, by continuous noise-free observation of the outputs after the known doses. Two independent methods are used and must agree:

  • Lie derivatives of the outputs evaluated at the known initial state (the Taylor-series approach), which keeps the information that a dose gives about volumes;
  • the rank of the output sensitivity matrix, solved with rxode2.

A model, step by step

A one-compartment model with first-order absorption and unknown bioavailability F:

m <- pkpd_model(
  "d/dt(depot)   = -ka*depot
   d/dt(central) = ka*depot - CL/V*central
   cp            = central/V",
  outputs = "cp",
  doses   = bolus_dose("depot", "F*DOSE"),
  known   = "DOSE"
)
m
#> <pkident_model>
#> States:      depot, central 
#> Outputs:     cp 
#> Parameters:  CL, F, V, ka 
#> Known:       DOSE 
#>   d/dt(depot) = -ka*depot;  depot(0) = F*DOSE
#>   d/dt(central) = ka*depot - CL*central/V;  central(0) = 0
#>   cp = central/V
r <- structural_identifiability(m)
r
#> <pkident structural identifiability>
#> Decision is LOCAL (Lie derivatives at the known initial state up to order 8, checked by output sensitivities; 5 random points).
#> Methods agree at 5 of 5 points.
#>   CL           combination_only
#>   F            combination_only
#>   V            combination_only
#>   ka           identifiable
#> Identifiable combinations:
#>   CL/F
#>   CL/V

CL, F and V are not identifiable alone; the reported combinations span the identifiable ones. The familiar V/F is among them:

as_table(r, "combinations")
#> # A tibble: 2 × 2
#>   combination parameters
#>   <chr>       <chr>     
#> 1 CL/F        CL,F      
#> 2 CL/V        CL,V
as_table(r, "agreement")
#> # A tibble: 5 × 5
#>   point lie_rank sensitivity_rank null_space_distance agree
#>   <int>    <int>            <int>               <dbl> <lgl>
#> 1     1        3                3        0            TRUE 
#> 2     2        3                3        0            TRUE 
#> 3     3        3                3        0.0000000211 TRUE 
#> 4     4        3                3        0            TRUE 
#> 5     5        3                3        0            TRUE

The acceptance set

The package ships ten reference models whose expected results were fixed from primary literature (Janzén et al. 2016, Front Physiol 7:590) or derived analytically before any code was written, plus a variant of A10 with total receptors known.

reference_models()
#>                id
#> 1              A1
#> 2              A2
#> 3              A3
#> 4              A4
#> 5              A5
#> 6              A6
#> 7              A7
#> 8              A8
#> 9              A9
#> 10            A10
#> 11 A10_Rtot_known
#>                                                                                title
#> 1                                                           One-compartment IV bolus
#> 2                                      One-compartment oral, bioavailability unknown
#> 3                                        One-compartment oral, bioavailability known
#> 4                             Two-compartment IV bolus, central compartment observed
#> 5                             One-compartment Michaelis-Menten elimination, IV bolus
#> 6         One-compartment parallel linear and Michaelis-Menten elimination, IV bolus
#> 7       Direct effect, steady-state receptor binding, linear transduction (known Cp)
#> 8       Indirect stimulation of production, steady-state receptor binding (known Cp)
#> 9  Effect compartment, steady-state receptor binding, linear transduction (known Cp)
#> 10      Effect compartment, dynamic receptor binding, linear transduction (known Cp)
#> 11                    As A10 with total receptors known (the paper's worked example)
#>                                                                   source
#> 1                                                  Analytical derivation
#> 2  Janzen et al. 2016 (citing Cheung et al. 2013); analytical derivation
#> 3                                                  Analytical derivation
#> 4                                                  Analytical derivation
#> 5                                                  Analytical derivation
#> 6                                                  Analytical derivation
#> 7                                            Janzen et al. 2016, Model 1
#> 8                        Janzen et al. 2016, Model 3 (baseline kin/kout)
#> 9                                            Janzen et al. 2016, Model 9
#> 10                                          Janzen et al. 2016, Model 13
#> 11                           Janzen et al. 2016, Model 13, equations 6-8
decide <- function(id) {
  m <- reference_model(id)
  r <- structural_identifiability(m)
  p <- r$parameters
  data.frame(
    model = id,
    decision = r$decision,
    methods_agree = sum(r$agreement$agree),
    identifiable = paste(p$parameter[p$status == "identifiable"], collapse = ", "),
    not_alone = paste(p$parameter[p$status != "identifiable"], collapse = ", "),
    combinations = paste(r$combinations$combination, collapse = ", "),
    matches_literature = setequal(p$parameter[p$status == "identifiable"],
                                  attr(m, "expected")$identifiable)
  )
}
results <- do.call(rbind, lapply(reference_models()$id, decide))
knitr::kable(results)
model decision methods_agree identifiable not_alone combinations matches_literature
A1 decided 5 CL, V TRUE
A2 decided 5 ka CL, F, V CL/F, CL/V TRUE
A3 decided 5 CL, V, ka TRUE
A4 decided 5 CL, Q, V1, V2 TRUE
A5 decided 5 KM, V, VMAX TRUE
A6 decided 5 CL, KM, V, VMAX TRUE
A7 decided 5 Kd Rtot, ke Rtot*ke TRUE
A8 decided 5 Kd, kin, kout Rtot, ke Rtot*ke TRUE
A9 decided 5 Kd, ke0 Rtot, ke Rtot*ke TRUE
A10 decided 5 ke0, koff, kon Rtot, ke Rtot*ke TRUE
A10_Rtot_known decided 5 ke, ke0, koff, kon TRUE

Every decision matches the expected result, and the two methods agree at all five random points for every model.

Reading the results

  • identifiable: locally identifiable. It may still have a finite number of alternative values (A3, the oral model with F known, has the flip-flop solution of absorption and elimination).
  • combination_only: not identifiable alone, but identifiable within a reported combination.
  • non_identifiable: not identifiable, and in no reported combination.
  • unresolved: the computation could not decide (limits reached, poor conditioning, or the two methods disagree). pkident never turns an undecided case into a decision.

See validation/reference-models.md in the source repository for the derivations and the full validation record.