Generate data and Fit using Simple PopPK Model

PoPy provides a method to simulate, analyse and compare results in a single script, which is ideal for generating tutorials or illustrative examples. Here we will demonstrate a Tut Script using the same compartment model as used in Fitting a Simple PopPK Model using PoPy, see Figure fig_simple_popkp_diagram_tut:-

../../_images/compartment_diagram461.svg

One compartment model with bolus dosing for Tut Script. Here c[AMT] is the amount of the bolus dose. m[KE] is the elimination rate and s[CENTRAL] is the current amount in the central compartment.

Note

See the Simple Tut Example obtained by the PoPy developers for this example, including input script and output data file.

A Tut Script can be used as a theoretical tool to investigate identifiability of PK/PD models, because the true f[X] parameters and underlying structure of the data are known. Unfortunately this is never the case in a real life analysis.

This documentation makes extensive use of tut_scripts to create examples to illustrate different Simulating A Single Individual.

Running the Tutorial Script

This tutorial example requires a single input file, c:\PoPy\examples\tut_example1.pyml

PoPy Terminal to set up the PoPy environment in the folder c:\PoPy\examples\

With the PoPy environment enabled, you can call popy run on the Tut Script from the command line:-

popy run tut_example1.pyml

When the tut script has completed, you can view the output of the fit using popy view, by typing the following command:-

popy view tut_example1.pyml.html

Note the extra ‘.html’ extension in the above command. This command opens a local .html file in your web browser to summarise the result of the generating process.

You can compare your local html output with the pre-computed documentation output, see Simple Tut Example. You should expect some minor numerical differences when comparing results with the documentation.

Syntax of Tut Script

The major structural difference between a Gen Script or Fit Script and a Tut Script is that the tut_script has separate GEN_EFFECTS and FIT_EFFECTS sections to describe both the generating and fitting effects. The GEN_EFFECTS section for this tutorial example is as follows:-

GEN_EFFECTS:
    POP: |
        c[AMT] = 100.0
        f[KE] = 0.1
        f[PNOISE] = 0.05
        f[KE_isv] = 0.03
    ID: |
        c[ID] = sequential(20)
        t[DOSE] = 1.0
        t[OBS] ~ unif(1.0, 50.0; 5)
        r[KE] ~ norm(0, f[KE_isv])

The FIT_EFFECTS section for this tutorial example is as follows:-

FIT_EFFECTS:
    POP: |
        f[KE] ~ unif(0.001, 100) 0.05
        f[PNOISE] ~ unif(0.001, 100) 0.1
        f[KE_isv] ~ unif(0.001, 100) 0.1
    ID: |
        r[KE] ~ norm(0, f[KE_isv])

The GEN_EFFECTS get copied into the Gen Script and renamed EFFECTS. Similarly the FIT_EFFECTS get copied into the Fit Script and also renamed EFFECTS. From the examples above you can see that the GEN_EFFECTS->POP section has:-

f[X] = true_value

Whereas the FIT_EFFECTS->POP section has:-

f[X] ~ unif(0.001, 100) starting_value

Reflecting the fact that the f[X] are known constants for a Gen Script, but are unknown values to be estimated in a Fit Script, with lower and upper limits of [0.001, 100]. Note in PoPy you can also use ‘P’ meaning positive, as a shortcut for ‘~unif(0.0,+inf)’.

The GEN_EFFECTS->POP level has this extra line:-

c[AMT] = 100.0

This sets the dose amount to be 100.0 units for all individuals.

The GEN_EFFECTS->ID level also contains these extra lines:-

c[ID] = sequential(20)
t[DOSE] = 1.0
t[OBS] ~ unif(1.0, 50.0; 5)

These lines are passed to the Gen Script and generate 20 individuals all with a dose at time 1.0 and 5 observations uniformally sampled in the time interval [1.0, 50.0]. See EFFECTS with two levels from a gen_script for more information on the Gen Script syntax within a EFFECTS section.

Summary of Tut Results

See Simple Tut Example for example HTML outputs generated by the PoPy developers.

On your local machine, the Tut Script generates an output folder containing four new scripts:-

simple_tut_example.pyml_output/
    simple_tut_example_gen.pyml
    simple_tut_example_fit.pyml
    simple_tut_example_comp.pyml
    simple_tut_example_tutsum.pyml

See Files Generated by Tut Script for more info. The purpose of each of theses scripts is as follows:-

Scripts output by a tutorial script

Script

Purpose

Documentation

*_gen.pyml

Generate synthetic data set from model

Gen Script

*_fit.pyml

Fit model to synthetic data set

Fit Script

*_comp.pyml

Compare gen model and fit model to synthetic data set

Comp Script

*_tutsum.pyml

Summary of generating and fitting and comparison results

TutSum Script

These four scripts are run in order.

The Gen Script uses a EFFECTS structure similar to a Fit Script, but with some extra commands to generate new data rows, see Syntax of Tut Script above. Alternatively see builtin_gen_example, for a longer explanation of how a Gen Script works.

The Fit Script here is very similar to the PK/PD model described in Fitting a Simple PopPK Model using PoPy. Therefore here we will focus on the Comp Script outputs. To generate the comp output, you need this entry in your Tut Script OUTPUT_SCRIPTS section:-

OUTPUT_SCRIPTS:
    COMP: {output_mode: run}

Otherwise the TutSum Script will have no comp output to summarise. The comp outputs are PK curves from the fitted and generated f[X] parameters and the associated objective function values. The simplest Comp Script output is a visual comparison of the true and fitted f[X] PK curves and the synthetic generated data, see table_true_vs_fit_fx_plots_simple.

Fitted model PK curves vs true model PK curves for first three individuals

The solid blue lines in table_true_vs_fit_fx_plots_simple show the predicted PK curves for the fitted model f[X] values. The dotted blue lines show the PK curves for the true f[X] values that were used to generated the data set (in the Gen Script). The blue dots are the target c[DV_CENTRAL] values from the data file.

The target c[DV_CENTRAL] values have measurement noise added, so blue dot data points do not lie exactly on the true f[X] curves. The graphs show that the PK curves for the fitted f[X] are almost identical to the true f[X] curves, this is to be expected as the model only contains a single model parameter m[KE] and we have 5 observations per individual.

If the Comp Script has been run, the TutSum Script outputs convenient tables to compare the initial, fitted and true f[X] values, see table_true_vs_fit_fx_main_values_simple, table_true_vs_fit_fx_var_values_simple and table_true_vs_fit_fx_noise_values_simple.

Comparison of initial, fitted and true f[KE] values

Name

Initial

Fitted

True

Abs. Error

Prop. Error

f[KE]

0.05

0.0999

0.1

1.30e-04

0.13%

Comparison of initial, fitted and true f[KE_isv] values

Name

Initial

Fitted

True

Abs. Error

Prop. Error

f[KE_isv]

0.1

0.0183

0.03

1.17e-02

39.00%

Comparison of initial, fitted and true f[PNOISE] values

Name

Initial

Fitted

True

Abs. Error

Prop. Error

f[PNOISE]

0.1

0.0503

0.05

3.36e-04

0.67%

table_true_vs_fit_fx_main_values_simple shows that the f[KE] parameter is recovered reasonably well, in the sense that the fitted value 0.106 is close to the true generating value 0.1 starting from an initial value of 0.05. Similarly the fitted f[KE_isv] and f[PNOISE] parameters are close to the true generating values.

The objective function Comp Script computes the objective function given the synthetic data and the true generating f[X] parameters (the r[X] are re-optimised). In this case the true f[X] ObjV is:-

-44.20

The Comp Script also computes he ObjV for the fitted f[X] and optimised r[X], which is as follows:-

-48.43

The lower objective value for the fitted f[X] is quite common, because the fitted f[X] can take advantage of noise in the generated synthetic data set. If the size of the synthetic data set is increased, then it is likely that the f[KE], f[KE_isv] and f[PNOISE] parameters will move closer to the true generating values and the ObjVs will also converge.

In this simple example the parameters are very easy to identify. For a more challenging example see Running Your First tut Script.