R - Introduction
R - Introduction
The ospsuite R-package provides the functionality of loading, manipulating, and simulating the simulations created in the software tools PK-Sim and MoBi. This document gives an overview of the general workflow and the most important methods.
Installing the R-Toolbox
Installation instructions are provided here: https://github.com/Open-Systems-Pharmacology/OSPSuite-R/blob/develop/README.md#installation
General information
In order to load a simulation in R, it must be present in the *.pkml file format. Every simulation in PK-Sim or MoBi can be exported to the *.pkml file. The examples shown are based on the Aciclovir example model, until stated otherwise. The model can be found in the PK-Sim examples folder of the OSPS installation.
The general workflow with the ospsuite package can be summarized in following steps:
Loading a simulation from .pkml file.
Accessing entities of the simulation, such as molecules, parameters, or containers, and reading information about them.
Changing simulation settings, parameter values, and molecules start values.
Retrieving the results and processing them.
The workflow steps are described in the following sections:
Some aspects of the ospsuite package may appear uncommon for the users not familiar with the object-oriented approach. It is recommended to read the following section to better understand some semantics and to get the most of the flexibility and efficiency of the package.
Object-oriented approach
The ospsuite R-package utilizes the concept of object oriented (OO) programming based on the R6 system. While the philosophy of the package is to offer a functional programming workflow more common for the R users, it is important to understand some basic concepts of the OO programming. Most of the functions implemented in ospsuite return an instance (or an object) of a class. These objects can be used as inputs for another functions. Additionally, each object offers a set of properties (which can be another objects) and functions, accessible by the $
sign:
object1 <- ClassName$new()
aProperty <- object1$property1
resultOfAFunction <- object1$multiply(1,2)
Important information about the object can be printed out by calling print(object)
.
The most important classes are:
Simulation
Representation of the simulation loaded from the *.pkml file.
SimulationRunOptions
An object defining the options of a simulation run. The options are:
numberOfCores
the maximal number of (logical) cores that can be used by the (population) simulationcheckForNegativeValues
a boolean defining if an error if thrown if some variables become negative for which the “negativeValuesAllowed”-flag is set to FALSE (can be used to ignore numerical noise)showProgress
a boolean if a “progress bar” is shown in the console representing the progress of the simulation.
SolverSettings
Object defining the settings of the solver. Stored in SimulationSettings
of a Simulation
(accessibly by field $settings
).
OutputSchema
Definition of the output intervals of the simulation. The OutputSchema
defines the total simulation time and the time points at which results are generated. Can be accessed as property of a Simulation
-object.
OutputSelections
List of quantities (parameters and molecules) for which the outputs will be generated. Can be accessed as property of a Simulation
-object.
SimulationResults
Results of a simulation, either individual or population. Holds the simulated values for all quantities defined in the OutputSelections
. See Running a simulation for more information.
Entity
Every accessible distinct part of the model. Most prominent entities are Molecule
, Parameter
, Container
. Every Entity
has properties $path
representing the path within the model structure and $parentContainer
being the container this entity is located in.
Container
A Container
is an element of model structure that contains other entities (e.g., spatial containers, molecules, parameters). The most prominent containers are organs and compartments. A loaded Simulation
is also a container.
Quantity
An Entity
in the simulation that has a value - namely Molecule
and Parameter
. Every Quantity
has a $value
and a dimension
. Further important fields are $unit
, which is the base unit of the dimension. See Dimensions and Units for more information.
Molecule
A molecule located in a Container
. The $value
-property refers to the initial value in the simulation. Inherits from Quantity
.
Parameter
A parameter. The $value
-property refers to the initial value in the simulation. Inherits from Quantity
.
Formula
The value of each Quantity
is described by a Formula
. There are different types of formulae, see Changing parameter and molecule start values for more information.
IndividualCharacteristics
An object used for creating of individual parameter sets with the createIndividual
-method. See Creating individuals for more information.
Population
An object describing a virtual population. Can be either loaded from a *.csv-file created by PK-Sim or created with the createPopulation
-method. See Creating populations for more information.
PopulationCharacteristics
An object used for creating of population parameter sets with thecreatePopulation
-method. See Creating populations for more information.
SimulationPKAnalyses
PK analyses for a simulations result.
QuantityPKParameter
A certain PK parameter for an output quantity. Has the fields $name
which is the name of the PK parameter (e.g. “C_max”), $quantityPath
the path of the output the parameter has been calculated for, and $values
the value (or list of values for a population simulation).
SensitivityAnalysis
A class defining the analysis of which input parameters have most impact on the output curves of a simulation. See Sensitivity analysis for more information.
SensitivityAnalysisResults
Results of running the SensitivityAnalysis
PKParameterSensitivity
The sensitivity (field $value
) of a PK-Parameter ($pkParameterName
) for the output $outputPath
calculated for the varied parameter $parameterName
. See Sensitivity analysis for more information.
Loading a simulation and accessing entities
Loading a simulation
In general, every workflow starts with loading a simulation by calling the loadSimulation()
function. The function receives the full path to the PKML file (with extension *.pkml) exported from PK-Sim or MoBi and returns the corresponding simulation object.
library(ospsuite)
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
print(simFilePath)
#> [1] "C:/Users/appveyor/AppData/Local/Temp/1/RtmpY9evoZ/Rbuildce052b82d20/ospsuite/vignettes/../tests/data/Aciclovir.pkml"
sim <- loadSimulation(simFilePath)
print(sim)
#> Simulation:
#> Name: Vergin 1995 IV
#> Source file: C:/Users/appveyor/AppData/Local/Temp/1/RtmpY9evoZ/Rbuildce052b82d20/ospsuite/vignettes/../tests/data/Aciclovir.pkml
Accessing entities of the model and their properties - the path concept
Once the simulation is loaded, it is possible to retrieve various entities of the model. The most important entities are containers, molecules, and parameters. The methods getContainer
, getMolecule
, and getParameter
search for the respective entity with the given path
located under a container
. path
is a string where the elements of the path (i.e., containers in the hierarchy of the simulation) are separated by |
. container
is an instance of the Container
-class within the model structure the path is relative to. In most cases, container
is the Simulation
object created by calling loadSimulation(pkmlSimulationFile)
.
#Get the container "Liver"
livContainer <- getContainer("Organism|Liver", sim)
print(livContainer)
#> Container:
#> Container type: Organ
#> Path: Organism|Liver
#Get the molecule Aciclovir located in kindey intracellular space
moleculeInKid <- getMolecule("Organism|Kidney|Intracellular|Aciclovir", sim)
print(moleculeInKid)
#> Molecule:
#> Path: Organism|Kidney|Intracellular|Aciclovir
#> Initial Value: 0.00 [µmol]
#Get the parameter volume of the liver interstitial space.
# Note that the path used is relative to the liver container
livParam <- getParameter("Interstitial|Volume", livContainer)
print(livParam)
#> Parameter:
#> Path: Organism|Liver|Interstitial|Volume
#> Value: 0.3533 [l]
#> isFormula: TRUE
#> formula: f_int*V
#> Value overrides formula: FALSE
#> isStateVariable: FALSE
The functions getAllContainersMatching
, getAllMoleculesMatching
, and getAllParametersMatching
return a list of objects representing all entities whose paths match the generic paths provided in the list paths
located under container
. Generic paths are constructed by using the wildcard symbols *
(exactly one occurrence of any element) or **
(zero or more occurrences of any element).
# Get the parameter `Volume` of the intracellular space of all organs,
# with exactly one path element before `Intracellular`
volumeParams <- getAllParametersMatching("Organism|*|Intracellular|Volume", sim)
length(volumeParams)
#> [1] 15
#The PBPK model has 15 organs with an "Intracellular" sub-compartment
# Get the parameter `Volume` of the intracellular space of all organs,
# no matter how many sub-containers the organ has
volumeParams <- getAllParametersMatching("Organism|**|Intracellular|Volume", sim)
length(volumeParams)
#> [1] 28
# The list also includes parameters of organs like "Liver|Periportal",
# or the mucosal compartments of the intestine.
Note that the path "Organism|Kidney|*|Intracellular|Volume"
will return no parameters in the standard models, as there are no sub-containers between Kidney
and Intracellular
. In contrast, "Organism|Kidney|**|Intracellular|Volume"
is a valid path.
The functions getAllXXXMatching
can also be used to retrieve entities from multiple paths:
#Get the molecule Aciclovir located in `Liver|Periportal|Intracellular` and `VenousBlood|Plasma`
molecules <- getAllMoleculesMatching(c("Organism|Liver|Periportal|Intracellular|Aciclovir",
"Organism|VenousBlood|Plasma|Aciclovir"), sim)
print(molecules)
#> [[1]]
#> Molecule:
#> Path: Organism|VenousBlood|Plasma|Aciclovir
#> Initial Value: 0.00 [µmol]
#>
#> [[2]]
#> Molecule:
#> Path: Organism|Liver|Periportal|Intracellular|Aciclovir
#> Initial Value: 0.00 [µmol]
The entities possess various properties that can be accessed through their objects. The most important properties for a container are:
# Path of the container
livContainer$path
#> [1] "Organism|Liver"
# Parent container
livContainer$parentContainer
#> Container:
#> Container type: Organism
#> Path: Organism
The most important properties for a molecule are:
#Initial value of the molecule
moleculeInKid$value
#> [1] 0
# Dimension of the molecule. See section "Unit conversion" for more information.
moleculeInKid$dimension
#> [1] "Amount"
# Is the initial value defined by a formula?
moleculeInKid$isFormula
#> [1] FALSE
# Type of the formula. CONSTANT if the value is defined by a constant.
moleculeInKid$formula
#> Formula:
#> isConstant: TRUE
The most important properties for a parameter are:
#Initial value of the parameter
livParam$value
#> [1] 0.3533005
# Dimension of the parameter. See section "Unit conversion" for more information.
livParam$dimension
#> [1] "Volume"
# Base unit of the parameter. See section "Unit conversion" for more information.
livParam$unit
#> [1] "l"
# Is the initial value defined by a formula?
livParam$isFormula
#> [1] TRUE
# Type of the formula. CONSTANT if the value is defined by a constant.
livParam$formula
#> Formula:
#> isFormula: TRUE
#> formula: f_int*V
Loading simulation tree
A convenient way to traverse the simulation structure is given by the method . The method generates a tree-like list of all paths within the simulation. Each element of the tree contains all the sub-containers of the element. The final elements are strings representing the path to the entity.
# Load simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
# Create simulation tree
simTree <- getSimulationTree(sim)
# Calling simTree would list all entities within the simulation
# Accessing the parameter "Organism|Weight"
simTree$Organism$Weight
#> $path
#> [1] "Organism|Weight"
#
# Getting all entities located under "Organism|Liver|Periportal|Intracellular"
entitiesList <- simTree$Organism$Liver$Periportal$Intracellular
Changing parameter and molecule start values
Changing initial values
It is possible to change the initial values of all parameters and molecules in a simulation. It is important to differentiate between the constant values and the values that are defined by a formula.
Formula types
Every (initial) value is described either by a constant or by a formula. If the value is defined by a simple constant, the field isConstant
of the respective parameter or molecule has the value TRUE
.
library(ospsuite)
# Load simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
#Get the parameter "Age" of the Organism
ageParam <- getParameter("Organism|Age", sim)
print(ageParam)
#> Parameter:
#> Path: Organism|Age
#> Value: 25.70 [year(s)]
#> isConstant: TRUE
#> isStateVariable: FALSE
ageParam$isConstant
#> [1] TRUE
If the value is not constant, it is described by one of the formula types:
Distributed: Distributed parameters describe a variation around a constant value or between two numerical limits. In the simulation, the behavior equals that of constant values. See Working with Constant and Distributed Parameters for more information.
#Get the parameter "Volume" of the Liver
liverVolume <- getParameter("Organism|Liver|Volume", sim)
print(liverVolume)
#> Parameter:
#> Path: Organism|Liver|Volume
#> Value: 2.1675 [l]
#> isDistributed: TRUE
#> isStateVariable: FALSE
liverVolume$isDistributed
#> [1] TRUE
Explicit formula: The value of the parameter is given by an explicit formula. The value of an explicit formula can change during the simulation. The string of the formula can be accessed via parameter$formulaString
.
#Get the parameter "Volume" of the Liver interstital
liverIntVolume <- getParameter("Organism|Liver|Interstitial|Volume", sim)
print(liverIntVolume)
#> Parameter:
#> Path: Organism|Liver|Interstitial|Volume
#> Value: 0.3533 [l]
#> isFormula: TRUE
#> formula: f_int*V
#> Value overrides formula: FALSE
#> isStateVariable: FALSE
liverIntVolume$formulaString
#> [1] "f_int*V"
Table formula: The value of the parameter is given by a table with x-y value pairs. X values usually refer to the simulation time. See Table parameters for additional information on how to retrieve or change the table values.
#Get the parameter defined by a table.
tableParam <- getParameter("Organism|TableParameter", sim)
print(tableParam)
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 0.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 0, y= 0, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: FALSE
#> isStateVariable: FALSE
Additionally, some parameters are modeled as state variables. In this case, the parameter has an initial value and a right hand side (RHS) formula, both of which can be any formula type.
#Get the parameter defined by a state variable.
stateVariableParam <- getParameter("Organism|StateVariable_Parameter", sim)
print(stateVariableParam)
#> Parameter:
#> Path: Organism|StateVariable_Parameter
#> Value: 0.00
#> isConstant: TRUE
#> isStateVariable: TRUE
#> RHSFormula
#> isFormula: TRUE
#> formula: Time * 2
# `value` refers to the initial value of the parameter
stateVariableParam$value
#> [1] 0
# `rhsFormula` is the right hand side of the parameter
stateVariableParam$rhsFormula
#> Formula:
#> isFormula: TRUE
#> formula: Time * 2
Changing parameters and molecules initial values
The user can change initial values of parameters and molecules with the methods setParameterValues
and setMoleculeInitialValues
, respectively.
# Get the parameter Dose
doseParamPath <- "Applications|IV 250mg 10min|Application_1|ProtocolSchemaItem|Dose"
doseParam <- getParameter(doseParamPath, sim)
print(doseParam)
#> Parameter:
#> Path: Applications|IV 250mg 10min|Application_1|ProtocolSchemaItem|Dose
#> Value: 0.00025 [kg]
#> isConstant: TRUE
#> isStateVariable: FALSE
# Change the dose to 350mg. The value has to be converted to base unit, first
newValue <- toBaseUnit(quantity = doseParam, values = 350, unit = "mg")
setParameterValues(parameters = doseParam, values = newValue)
print(doseParam)
#> Parameter:
#> Path: Applications|IV 250mg 10min|Application_1|ProtocolSchemaItem|Dose
#> Value: 0.00035 [kg]
#> isConstant: TRUE
#> isStateVariable: FALSE
Another way to change parameter values is to scale them. The scaling is always performed relative to the current value:
doseParamPath <- "Applications|IV 250mg 10min|Application_1|ProtocolSchemaItem|Dose"
doseParam <- getParameter(doseParamPath, sim)
print(doseParam)
#> Parameter:
#> Path: Applications|IV 250mg 10min|Application_1|ProtocolSchemaItem|Dose
#> Value: 0.00035 [kg]
#> isConstant: TRUE
#> isStateVariable: FALSE
# Double the dose
scaleParameterValues(doseParam, factor = 2)
print(doseParam)
#> Parameter:
#> Path: Applications|IV 250mg 10min|Application_1|ProtocolSchemaItem|Dose
#> Value: 7e-04 [kg]
#> isConstant: TRUE
#> isStateVariable: FALSE
# Half the dose
scaleParameterValues(doseParam, factor = 0.5)
print(doseParam)
#> Parameter:
#> Path: Applications|IV 250mg 10min|Application_1|ProtocolSchemaItem|Dose
#> Value: 0.00035 [kg]
#> isConstant: TRUE
#> isStateVariable: FALSE
Only constant values can be set. If the parameters value is defined by a formula (explicit or table), the newly assigned value will override the formula. This will be reflected by the field isFixedValue
. Changing values of formula parameters should be done with caution, as the potential dependency on another simulation parameters will be destroyed.
#Get the parameter "Volume" of the Liver interstital
liverIntVolume <- getParameter("Organism|Liver|Interstitial|Volume", sim)
print(liverIntVolume)
#> Parameter:
#> Path: Organism|Liver|Interstitial|Volume
#> Value: 0.3533 [l]
#> isFormula: TRUE
#> formula: f_int*V
#> Value overrides formula: FALSE
#> isStateVariable: FALSE
# isFixedValue is FALSE as the parameter is defined by its formula
liverIntVolume$isFixedValue
#> [1] FALSE
setParameterValues(liverIntVolume, 1)
print(liverIntVolume)
#> Parameter:
#> Path: Organism|Liver|Interstitial|Volume
#> Value: 1.00 [l]
#> isFormula: TRUE
#> formula: f_int*V
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
# isFixedValue is TRUE as the value of parameter is overridden by the constant value
liverIntVolume$isFixedValue
#> [1] TRUE
The parameter value can be reset to its formula after assigning a constant value:
print(liverIntVolume)
#> Parameter:
#> Path: Organism|Liver|Interstitial|Volume
#> Value: 1.00 [l]
#> isFormula: TRUE
#> formula: f_int*V
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
# isFixedValue is TRUE as the value of parameter is overridden by the constant value
liverIntVolume$isFixedValue
#> [1] TRUE
liverIntVolume$reset()
print(liverIntVolume)
#> Parameter:
#> Path: Organism|Liver|Interstitial|Volume
#> Value: 0.3533 [l]
#> isFormula: TRUE
#> formula: f_int*V
#> Value overrides formula: FALSE
#> isStateVariable: FALSE
liverIntVolume$isFixedValue
#> [1] FALSE
Changing the value of a state variable parameter will only change its initial value, but not the right hand side (i.e., the value in the simulation will still change according to the rhs formula). To switch to RHS formula off and, by that, make the parameter be only dependent on its initial value, the field isStateVariable
can be set to FALSE
. This function is one-way only! It is not possible to re-activate the RHS formula after switching it off.
#Get the parameter defined by a state variable.
stateVariableParam <- getParameter("Organism|StateVariable_Parameter", sim)
print(stateVariableParam)
#> Parameter:
#> Path: Organism|StateVariable_Parameter
#> Value: 0.00
#> isConstant: TRUE
#> isStateVariable: TRUE
#> RHSFormula
#> isFormula: TRUE
#> formula: Time * 2
# Setting its value only changes the initial value
setParameterValues(stateVariableParam, 10)
print(stateVariableParam)
#> Parameter:
#> Path: Organism|StateVariable_Parameter
#> Value: 10.00
#> isConstant: TRUE
#> isStateVariable: TRUE
#> RHSFormula
#> isFormula: TRUE
#> formula: Time * 2
# Switching the RHS formula off
stateVariableParam$isStateVariable <- FALSE
print(stateVariableParam)
#> Parameter:
#> Path: Organism|StateVariable_Parameter
#> Value: 10.00
#> isConstant: TRUE
#> isStateVariable: FALSE
# Switching it on is not supported
stateVariableParam$isStateVariable <- TRUE
#> Error: Creating a RHS Formula is not supported at the moment. This should be done in MoBi.
An example how to set the initial values of molecules in all containers to a certain value:
# Get objects representing the molecule Aciclovir in all containers
allAciclovirMolecules <- getAllMoleculesMatching("Organism|**|Aciclovir",sim)
#Set initial values to 10 µmol in all containers
setMoleculeInitialValues(allAciclovirMolecules, rep(10, length(allAciclovirMolecules)))
Running a simulation
Running individual simulation and retrieving the results
Once the simulation is loaded (see Loading a simulation and accessing entities), it can be run to produce an object of the class SimulationResults
.
library(ospsuite)
# Load the simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
simulationResults <- runSimulation(simulation = sim)
print(simulationResults)
#> SimulationResults:
#> Number of individuals: 1
The advantage of storing the results in a object is the option to keep different results of the same simulation produced with different settings (e.g., model parameters).
Simulated time-value pairs for a specific output from the SimulationResults
-object can be accessed with the method getOutputValues
. The user can provide either the path(s) of the output (which can be a molecule, a parameter, or an observer), or the object(s) of the type Molecule
, Parameter
, or Quantity
(for observers) with the argument quantitiesOrPaths
. If no output is specified, all outputs available in the simulation results are returned.
The paths of all available outputs can be accessed via
simulationResults$allQuantityPaths
#> [1] "Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)"
getOutputValues
returns a list with two entries: data
and metadata
:
data
is a dataframe with two predefined columns (IndividualId and Time) as well as one column for each requested outputIndividualId
(not relevant for an individual simulation)Time
a vector with simulated time values (in minutes, equalfor all outputs)
a vector with simulated entries for each output requested.
metaData
is a list containing one entry for each requested output. Each entry contains information pertinent to the output such as its dimension or the unit.
Get simulated results by path
resultsPath <- simulationResults$allQuantityPaths[[1]]
print(resultsPath)
#> [1] "Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)"
resultsData <- getOutputValues(simulationResults, quantitiesOrPaths = resultsPath)
resultsTime <- resultsData$data$Time resultsValues <- resultsData$data$Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)
plot(resultsTime, resultsValues, type = "l")

The results can be stored in and imported from a *.csv file with the methods exportResultsToCSV
and importResultsFromCSV
.
# Load and run the simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
simulationResults <- runSimulation(simulation = sim)
# Export to csv
csvResultsPath <- file.path(getwd(), "..", "tests", "data", "SimResults.csv", fsep = .Platform$file.sep)
exportResultsToCSV(results = simulationResults, filePath = csvResultsPath)
# Load from csv
resultsLoaded <- importResultsFromCSV(filePath = csvResultsPath, simulation = sim)
print(resultsLoaded)
#> SimulationResults:
#> Number of individuals: 1
Adding new outputs
By default, only outputs that were selected in PK-Sim or MoBi prior to the export of the simulation to pkml
are generated. The user can add new outputs to the simulation with the method addOutputs
. The outputs can be provided either as objects of the type(s) Molecule
, Parameter, or
Quantity, or as path strings. The output list is a property of the
simulation`. After adding or removing outputs, the corresponding simulation needs to be re-run in order to generate updated results.
# Clear the list of generated outputs
clearOutputs(sim)
# Add new outputs as objects
molecule <- getMolecule("Organism|Kidney|Intracellular|Aciclovir", sim)
observer <- getQuantity("Organism|Lumen|Aciclovir|Fraction dissolved", sim)
addOutputs(c(molecule, observer), simulation = sim)
# Add new outputs as path strings
addOutputs(c("Organism|Lumen|Stomach|Aciclovir",
"Organism|PeripheralVenousBlood|Aciclovir|Whole Blood (Peripheral Venous Blood)"),
simulation = sim)
# Run simulation
simulationResults <- runSimulation(simulation = sim)
# Retrieve all generated outputs (e.g. omitting the quantitiesOrPaths property
# will return all available values)
resultsData <- getOutputValues(simulationResults)
# Note that "Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)"
# is not in the list of generated results any more
names(resultsData$data)
#> [1] "IndividualId"
#> [2] "Time"
#> [3] "Organism|Kidney|Intracellular|Aciclovir"
#> [4] "Organism|Lumen|Stomach|Aciclovir"
#> [5] "Organism|PeripheralVenousBlood|Aciclovir|Whole Blood (Peripheral Venous Blood)"
#> [6] "Organism|Lumen|Aciclovir|Fraction dissolved"
Changing simulation intervals
The simulation interval (i.e., the simulation times at which results are stored) can are stored as the property outputSchema
of a Simulation
object.
print(sim$outputSchema)
#> OutputSchema:
#> Interval:
#> Name: Simulation interval high resolution
#> Start time: 0.00 [min]
#> End time: 15.00 [min]
#> Resolution: 1.00 [pts/min]
#> Interval:
#> Name: Simulation Interval 1
#> Start time: 15.00 [min]
#> End time: 1440.00 [min]
#> Resolution: 0.33333 [pts/min]
#> Interval:
#> Name: Simulation Interval 2
#> Start time: 120.00 [min]
#> End time: 1440.00 [min]
#> Resolution: 0.066667 [pts/min]
To change the simulation interval, the user can use one of the functions clearOutputIntervals
, addOutputInterval
, and setOutputInterval
.
# Remove all output intervals - simulation not possible!
clearOutputIntervals(simulation = sim)
runSimulation(simulation = sim)
#> Error in rClr::clrCall(simulationRunner, "Run", simulation$ref, options$ref): Type: OSPSuite.Utility.Exceptions.OSPSuiteException
#> Message: Time points output schema is empty
#> Method: Void RunSimulation()
#> Stack trace:
#> at OSPSuite.SimModel.Simulation.RunSimulation()
#> at OSPSuite.Core.Domain.Services.SimModelManager.simulate()
#> at OSPSuite.Core.Domain.Services.SimModelManager.doIfNotCanceled(Action actionToExecute)
#> at OSPSuite.Core.Domain.Services.SimModelManager.RunSimulation(IModelCoreSimulation simulation, SimulationRunOptions simulationRunOptions)
#> at OSPSuite.R.Services.SimulationRunner.<>c__DisplayClass15_0.<RunAsync>b__0()
#> at System.Threading.Tasks.Task`1.InnerInvoke()
#> at System.Threading.Tasks.Task.Execute()
# Add an interval
addOutputInterval(simulation = sim, startTime = 0, endTime = 20, resolution = 60, intervalName = "highRes")
print(sim$outputSchema)
#> OutputSchema:
#> Interval:
#> Name: highRes
#> Start time: 0.00 [min]
#> End time: 20.00 [min]
#> Resolution: 60.00 [pts/min]
# Add a second interval
addOutputInterval(simulation = sim, startTime = 30, endTime = 2000, resolution = 4, intervalName = "lowRes")
print(sim$outputSchema)
#> OutputSchema:
#> Interval:
#> Name: highRes
#> Start time: 0.00 [min]
#> End time: 20.00 [min]
#> Resolution: 60.00 [pts/min]
#> Interval:
#> Name: lowRes
#> Start time: 30.00 [min]
#> End time: 2000.00 [min]
#> Resolution: 4.00 [pts/min]
# Replace the existing interval(s) with a new one
setOutputInterval(simulation = sim, startTime = 0, endTime = 2000, resolution = 4)
print(sim$outputSchema)
#> OutputSchema:
#> Interval:
#> Name: Output interval
#> Start time: 0.00 [min]
#> End time: 2000.00 [min]
#> Resolution: 4.00 [pts/min]
Working with individuals
The ospsuite-R package provides an interface to the PK-Sim physiology database to create parameter sets describing a certain individual. By applying these parameter values to a simulation, it is possible to simulate different individuals based on one exported *.pkml simulation. This functionality is only available when PK-Sim is installed on the system.
The easier way to get started is to install the OSPSuite Setup. This will link PK-Sim to your ospsuite-R installation automatically. If the portable version of PK-Sim is used installed, one must specify the path to the PK-Sim folder by calling the function initPKSim
.
Creating individuals
The physiology of an individual is defined by the values of the simulation parameters. To simulate a specific individual, one has to generate a set of parameter values and apply these values to the model. NOTE: Currently, only individuals of the same species as in the original *.pkml simulation can be applied. I.e., if the simulation exported from PK-Sim represents a human individual, it is possible to simulate another human individual of different race, gender, etc., but it is not possible to simulate a rat. Though it is technically possible, and the simulation will produce some results, these will not valid.
The first step is creating an object describing individual characteristics. To see the list of available values for the arguments species
, population
(only for human), and gender
(only for human), use the enums Species
, HumanPopulation
, and Gender
, respectively. This object is then passed to the function createIndividual
to generate a set of parameter values. The algorithm behind is the same used in PK-Sim when creating an Individual-Building Block.
library(ospsuite)
#If no unit is specified, the default units are used. For "weight" it is "kg", for "age" it is "year(s)".
individualCharacterstics <- createIndividualCharacteristics(species = Species$Human,
population = HumanPopulation$Japanese_Population,
gender = Gender$Female,
weight = 75,
height = 1.75,
heightUnit = "m",
age = 43)
print(individualCharacterstics)
#> IndividualCharacteristics:
#> Species: Human
#> Population: Japanese_Population
#> Gender: FEMALE
#> Age: 43.00 [year(s)]
#> Gestational age: 40.00 [week(s)]
#> Weight: 75.00 [kg]
#> Height: 1.75 [m]
individual <- createIndividual(individualCharacteristics = individualCharacterstics)
The output contains two lists of parameters - distributedParameters
and derivedParameters
. The first list contains parameters that differ between the individuals of the selected species, while the second list mostly consists of values of parameters defined by formulas in the simulation. When applying the generated individual parameter set to a simulation in R, only parameters from the distributedParameters
should be overwritten, otherwise formula dependencies may be destroyed. Generated parameter values can be conveniently applied using the setParameterValuesByPath
method:
library(ospsuite)
# Load simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
# Apply individual parameters
setParameterValuesByPath(parameterPaths = individual$distributedParameters$paths,
values = individual$distributedParameters$values,
simulation = sim)
Adding enzyme ontogenies
The PK-Sim database includes ontogeny information for some proteins (see PK-Sim Ontogeny Database). For a protein molecule present in the simulation, it is possible to add the ontogeny information on one of the pre-defined proteins. For example, it is possible to set the ontogeny of the protein MyProtein
to the value of the ontogeny of a CYP3A4 enzyme for the specified individual. The list of supported ontogenies is stored in the StandardOntogeny
-list.
library(ospsuite)
# All supported ontogenies
print(StandardOntogeny)
#> $CYP1A2
#> [1] "CYP1A2"
#>
#> $CYP2C18
#> [1] "CYP2C18"
#>
#> $CYP2C19
#> [1] "CYP2C19"
#>
#> $CYP2C8
#> [1] "CYP2C8"
#>
#> $CYP2C9
#> [1] "CYP2C9"
#>
#> $CYP2D6
#> [1] "CYP2D6"
#>
#> $CYP2E1
#> [1] "CYP2E1"
#>
#> $CYP3A4
#> [1] "CYP3A4"
#>
#> $CYP3A5
#> [1] "CYP3A5"
#>
#> $CYP3A7
#> [1] "CYP3A7"
#>
#> $UGT1A1
#> [1] "UGT1A1"
#>
#> $UGT1A4
#> [1] "UGT1A4"
#>
#> $UGT1A6
#> [1] "UGT1A6"
#>
#> $UGT1A9
#> [1] "UGT1A9"
#>
#> $UGT2B4
#> [1] "UGT2B4"
#>
#> $UGT2B7
#> [1] "UGT2B7"
#Create the ontogeny for the protein "MyProtein" based on ontology of CYP3A4
myProteinOntogeny <- MoleculeOntogeny$new(molecule = "MyProtein", ontogeny = StandardOntogeny$CYP3A4)
print(myProteinOntogeny)
#> MoleculeOntogeny:
#> Molecule: MyProtein
#> Ontogeny: CYP3A4
# Add this ontogeny to the individual characteristics used to create the individual parameters set
individualCharacterstics <- createIndividualCharacteristics(species = Species$Human,
population = HumanPopulation$Japanese_Population,
gender = Gender$Female,
weight = 75,
height = 1.75,
heightUnit = "m",
age = 43,
moleculeOntogenies = myProteinOntogeny)
print(individualCharacterstics)
#> IndividualCharacteristics:
#> Species: Human
#> Population: Japanese_Population
#> Gender: FEMALE
#> Age: 43.00 [year(s)]
#> Gestational age: 40.00 [week(s)]
#> Weight: 75.00 [kg]
#> Height: 1.75 [m]
#> Molecule MyProtein with ontogeny CYP3A4
individual <- createIndividual(individualCharacteristics = individualCharacterstics)
Working with population simulations
Population simulations
Population simulations can be easily performed in R by combining the simulation loaded from a *.pkml file with the population information created in PK-Sim and exported to CSV format (for details, please refer to Creating Populations) or created directly in R (see Creating populations).
Loading population file
The method loadPopulation
creates an object of the Population
class that can be passed to the runSimulation
method (see Running simulations and retrieving the results).
library(ospsuite)
# Load population information from csv
popFilePath <- file.path(getwd(), "..", "tests", "data", "pop_10.csv", fsep = .Platform$file.sep)
myPopulation <- loadPopulation(csvPopulationFile = popFilePath)
print(myPopulation)
#> Population:
#> Number of Individuals: 10
Creating populations
Similar to creating individual parameter sets (see Creating individuals), a population is created from population characteristics created by calling the method createPopulationCharacteristics
. To see the list of available values for the arguments species
and population
(only for human), use the enums Species
and HumanPopulation
, respectively. The returned object of type PopulationCharacteristics
is then passed to the function createPopulation
to generate a set of parameter values. The algorithm behind is the same used in PK-Sim when creating an population. Molecule ontogenies can be added as described in Creating individuals.
library(ospsuite)
#If no unit is specified, the default units are used. For "height" it is "dm", for "weight" it is "kg", for "age" it is "year(s)".
populationCharacteristics <- createPopulationCharacteristics(
species = Species$Human,
population = HumanPopulation$Asian_Tanaka_1996,
numberOfIndividuals = 50,
proportionOfFemales = 50,
weightMin = 30,
weightMax = 98,
weightUnit = "kg",
heightMin = NULL,
heightMax = NULL,
ageMin = 0,
ageMax = 80,
ageUnit = "year(s)")
print(populationCharacteristics)
#> PopulationCharacteristics:
#> Species: Human
#> Population: Asian_Tanaka_1996
#> Number of individuals: 50
#> Proportion of females: 50
#> Age: [0.00 year(s)..80.00 year(s)]
#> Gestational age: ]-Inf..+Inf[
#> Weight: [30.00 kg..98.00 kg]
#> Height: ]-Inf..+Inf[
#> BMI: ]-Inf..+Inf[
# Create population from population characteristics
myPopulation <- createPopulation(populationCharacteristics = populationCharacteristics)
print(myPopulation)
#> Population:
#> Number of Individuals: 50
Running population simulation
To run a population simulation, the Population
object created by the createPopulation
method must be passed to the runSimulation
method:
library(ospsuite)
# Load simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
# Run population simulation
simulationResults <- runSimulation(simulation = sim, population = myPopulation)
print(simulationResults)
#> SimulationResults:
#> Number of individuals: 50
Population simulations are run in parallel on multi-core machines - one core simulates a subset of all individuals defined in the population. By default, the number of cores used equals the maximal number of logical cores available minus one. The user can change the default behavior by providing custom SimulationRunOptions
.
# Load simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
# Create a SimulationRunOptions object
simRunOptions <- SimulationRunOptions$new()
print(simRunOptions)
#> SimulationRunOptions:
#> numberOfCores: 1
#> checkForNegativeValues: TRUE
#> showProgress: FALSE
# Change the maximal number of cores to use and show a progress bar during simulation
simRunOptions$numberOfCores <- 3
simRunOptions$showProgress <- TRUE
# Run population simulation with custom options
populationResults <- runSimulation(simulation = sim, population = myPopulation, simulationRunOptions = simRunOptions)
print(populationResults)
#> SimulationResults:
#> Number of individuals: 50
Simulated time-value pairs for a specific output from the SimulationResults
-object returned by the runSimulation
method can be accessed with the method getOutputValues
. The user can provide either the path(s) of the output (which can be a molecule, a parameter, or an observer), or the object(s) of the type Molecule
, Parameter
, or Quantity
(for observers) with the argument quantitiesOrPaths
. If no output is specified, all outputs available in the simulation results are returned. The paths of all available outputs can be accessed via
populationResults$allQuantityPaths
#> [1] "Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)"
getOutputValues
returns a list with two entries: data
and metadata
:
data
is a dataframe with two predefined columns (IndividualId andTime) as well as one column for each requested output
IndividualId
Time
a vector with simulated time values (in minutes, equalfor all outputs)
a vector with simulated entries for each output requested.
The values of IndividualId
, Time
, and the simulated outputs, are appended for each simulated individual. Note that this results in non-monotonously increasing column Time
.
# Get simulated results by path
resultsPath <- populationResults$allQuantityPaths[[1]]
print(resultsPath)
#> [1] "Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)"
resultsData <- getOutputValues(populationResults, quantitiesOrPaths = resultsPath)
resultsTime <- resultsData$data$Time
resultsValues <- resultsData$data$`Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)`
plot(resultsTime, resultsValues, type = "l")

To get the results for a specific individual or a set of individuals, the argument individualIds
of the method getOutputValues
can be specified:
# Get simulated results by path
resultsPath <- populationResults$allQuantityPaths[[1]]
print(resultsPath)
#> [1] "Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)"
#Get only the results for individuals with IDs 1 and 2
resultsData <- getOutputValues(populationResults, quantitiesOrPaths = resultsPath, individualIds = c(1, 2))
resultsTime <- resultsData$data$Time
resultsValues <- resultsData$data$`Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)`
plot(resultsTime, resultsValues, type = "l")

For more information about running simulations, please refer to Running simulations and retrieving the results.
Calculating PK parameters of simulation outputs
PK parameters such as AUC, C_max, etc., can be calculated for all outputs of a simulation. First, simulation results must be calculated, and the SimulationResults
object is then passed to the method calculatePKAnalyses
. For the list of calculated PK parameters and their description, please refer to PK-Analysis view.
library(ospsuite)
# Load the simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
# Run the simulation
simulationResults <- runSimulation(simulation = sim)
# Calculate PK-analyses
pkAnalysis <- calculatePKAnalyses(results = simulationResults)
# Get the path of the simulated output
outputPath <- simulationResults$allQuantityPaths[[1]]
print(outputPath)
#> [1] "Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)"
# Get all calculated PK parameters for the output path
allPkParams <- pkAnalysis$allPKParametersFor(outputPath)
print(allPkParams)
#> [[1]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): C_max
#> Dimension: Concentration (molar)
#> Unit: µmol/l
#>
#> [[2]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): C_max_norm
#> Dimension: Concentration (mass)
#> Unit: kg/l
#>
#> [[3]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): t_max
#> Dimension: Time
#> Unit: min
#>
#> [[4]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): C_tEnd
#> Dimension: Concentration (molar)
#> Unit: µmol/l
#>
#> [[5]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): AUC_tEnd
#> Dimension: AUC (molar)
#> Unit: µmol*min/l
#>
#> [[6]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): AUC_tEnd_norm
#> Dimension: AUC (mass)
#> Unit: kg*min/l
#>
#> [[7]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): AUC_inf
#> Dimension: AUC (molar)
#> Unit: µmol*min/l
#>
#> [[8]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): AUC_inf_norm
#> Dimension: AUC (mass)
#> Unit: kg*min/l
#>
#> [[9]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): MRT
#> Dimension: Time
#> Unit: min
#>
#> [[10]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): Thalf
#> Dimension: Time
#> Unit: min
#>
#> [[11]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): FractionAucLastToInf
#> Dimension: Fraction
#> Unit:
#>
#> [[12]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): CL
#> Dimension: Flow per weight
#> Unit: l/min/kg
#>
#> [[13]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): Vss
#> Dimension: Volume per body weight
#> Unit: l/kg
#>
#> [[14]]
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): Vd
#> Dimension: Volume per body weight
#> Unit: l/kg
# Get C_max parameter
c_max <- pkAnalysis$pKParameterFor(quantityPath = outputPath, pkParameter = "C_max")
The function calculatePKAnalyses
returns an object of the class SimulationPKAnalyses
, which allows to retrieve either a certain PK parameter for an output path, or all calculated PK parameters for an output path.
The methods $allPKParametersFor
and $pKParameterFor
return a object (or a list of objects) of the class QuantityPKParameter
, with the fields $name
which is the name of the pk-parameter (e.g. “C_max”), $quantityPath
the path of the output the parameter has been calculated for, and $values
the value (or list of values for a population simulation).
# Get C_max parameter
c_max <- pkAnalysis$pKParameterFor(quantityPath = outputPath, pkParameter = "C_max")
print(c_max)
#> Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood): C_max
#> Dimension: Concentration (molar)
#> Unit: µmol/l
c_max$name
#> [1] "C_max"
c_max$quantityPath
#> [1] "Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)"
c_max$values
#> [1] 50.25272
In case of a population simulation, $values
return a list of values calculated for each individual.
Import and export of PK-analyses
Population analysis calculated in R can be exported to a *.csv file and loaded in PK-Sim, and vice versa.
# Load and run the simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
simulationResults <- runSimulation(simulation = sim)
# Calculate PK-analysis
pkAnalysis <- calculatePKAnalyses(results = simulationResults)
# Export to csv
csvPKAnalysisPath <- file.path(getwd(), "..", "tests", "data", "PKAnalyses.csv", fsep = .Platform$file.sep)
exportPKAnalysesToCSV(pkAnalyses = pkAnalysis, filePath = csvPKAnalysisPath)
# Load from csv
pkAnalysisLoaded <- importPKAnalysesFromCSV(filePath = csvPKAnalysisPath, simulation = sim)
Sensitivity analysis
The models built with OSPS depend on a lot of input parameters which are based on literature values, measurements, databases, assumptions. For a given set of input parameters a number of output curves is computed in a simulation. To assess which input parameters have most impact on the output curves, a sensitivity analysis of the simulation can be performed. For more information about theoretical background, see Sensitivity Analysis.
In brief, the values of the chosen parameters are changed by a certain percentage and the impact of these changes on PK parameters of model outputs is assessed.
Performing a sensitivity analysis
The first step of performing a sensitivity analysis is creating an object of the class SensitivityAnalysis
. At this step, the user can define which parameters should be considered for the sensitivity analysis, in which range the values are varied, and how may steps are performed in one direction (plus and minus). If no parameters are specified, all constant and suitable for sensitivity calculations parameters of the simulation will be variated. The list of such parameters paths for a simulation can be accessed with the method potentialVariableParameterPathsFor(simulation)
.
library(ospsuite)
# Load simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "simple.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
# Get the paths of parameters that will be considered by default.
potentialSAParameters <- potentialVariableParameterPathsFor(sim)
print(potentialSAParameters)
#> [1] "Organism|Volume" "Organism|Q" "R1|k1"
# Create a default `SensitivityAnalysis` for the simulation
sa <- SensitivityAnalysis$new(simulation = sim)
print(sa)
#> SensitivityAnalysis:
#> Number of steps: 2
#> Variation range: 0.1
#> Number of parameters to vary: Will be estimated at run time
# Create a `SensitivityAnalysis` with specified parameters
sa <- SensitivityAnalysis$new(simulation = sim, parameterPaths = c("Organism|Q",
"Organism|Volume"))
print(sa)
#> SensitivityAnalysis:
#> Number of steps: 2
#> Variation range: 0.1
#> Number of parameters to vary: 2
# Show which parameters will be varied
sa$parameterPaths
#> [1] "Organism|Q" "Organism|Volume"
New parameters can be added to an existing SensitivityAnalysis
by calling the method addParameterPaths
. WARNING: If no parameters were specified during the creation of a SensitivityAnalysis
(all constant and suitable for sensitivity calculation parameters are considered), calling addParameterPaths
will only vary the newly added parameters.
library(ospsuite)
# Load simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "simple.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
# Create a `SensitivityAnalysis` with specified parameters
sa <- SensitivityAnalysis$new(simulation = sim, parameterPaths = c("Organism|Q",
"Organism|Volume"))
# Add new parameter
sa$addParameterPaths("R1|k1")
# Show which parameters will be varied
sa$parameterPaths
#> [1] "Organism|Q" "Organism|Volume" "R1|k1"
To run the specified SensitivityAnalysis
, call the method runSensitivityAnalysis
. The method returns an object of the class SensitivityAnalysisResults
. The impact of the defined parameters is calculated for PK-Parameters (see PK Analysis for more information) of all model outputs.
# Load simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "simple.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
# Create a `SensitivityAnalysis` with all constant and suitable for sensitivity calculations parameters and suitable for sensitivity calculations parameters
sa <- SensitivityAnalysis$new(simulation = sim)
# Run the sensitivity analysis
saResult <- runSensitivityAnalysis(sa)
print(saResult)
#> SensitivityAnalysisResults:
#> Number of calculated sensitivities: 72
#> Available PK parameters: C_maxt_maxC_tEndAUC_tEndThalfAUC_infMRTFractionAucLastToInf
The method allPKParameterSensitivitiesFor
returns a list of PKParameterSensitivity
objects. PKParameterSensitivity
describes the sensitivity (field $value
) of a PK-Parameter ($pkParameterName
) for the output $outputPath
calculated for the varied parameter $parameterPath
. The argument totalSensitivityThreshold
of the method allPKParameterSensitivitiesFor
is used to filter out the most impactful parameters. A threshold of 0.9 means that only parameters participating to a total of 90 percent of the sensitivity would be returned. A value of 1 would return the sensitivity for all parameters. If no value is provided, a default value is used.
# Load simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
# Default value of the threshold
getOSPSuiteSetting("sensitivityAnalysisConfig")$totalSensitivityThreshold
#> [1] 0.9
# Create a `SensitivityAnalysis` with all constant parameters and run it
sa <- SensitivityAnalysis$new(simulation = sim, parameterPaths = c("Aciclovir|Lipophilicity",
"Aciclovir|Fraction unbound (plasma)",
"Organism|Age"))
saResult <- runSensitivityAnalysis(sa)
print(saResult)
#> SensitivityAnalysisResults:
#> Number of calculated sensitivities: 11
#> Available PK parameters: C_maxt_maxC_tEndAUC_tEndAUC_infMRTThalfFractionAucLastToInfCLVssVd
# Get sensitivities for the parameter "AUC_inf" of the simulated output with a threshold of 0.8
outputPath <- sim$outputSelections$allOutputs[[1]]$path
sensitivities <- saResult$allPKParameterSensitivitiesFor(pkParameterName = "AUC_inf", outputPath = outputPath, totalSensitivityThreshold = 0.8)
print(sensitivities)
#> [[1]]
#> PKParameterSensitivity:
#> Parameter name: Aciclovir-Lipophilicity
#> PK-Parameter: AUC_inf
#> Output path: Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)
#> Value: 0.00470882781612934
The value -1
for the sensitivity of “AUC_inf” of the output Organism|PeripheralVenousBlood|Aciclovir|Plasma (Peripheral Venous Blood)
for the parameter Organism-Kidney-Volume
means that increasing Organism-Kidney-Volume
by 10% will decrease “AUC_inf” by 10%. Note that the list of sensitivities is ordered from largest to smallest with respect to magnitude.
Import and export of sensitivity analysis results
Sensitivity analysis calculated in R can be exported to a *.csv file, which can be loaded in another instance.
# Load and run the simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "simple.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
simulationResults <- runSimulation(simulation = sim)
# Create a `SensitivityAnalysis` with all constant parameters and run it
sa <- SensitivityAnalysis$new(simulation = sim)
saResult <- runSensitivityAnalysis(sa)
# Export to csv
saResultPath <- file.path(getwd(), "..", "tests", "data", "SAResult.csv", fsep = .Platform$file.sep)
exportSensitivityAnalysisResultsToCSV(results = saResult, filePath = saResultPath)
# Load from csv
saResultLoaded <- importSensitivityAnalysisResultsFromCSV(filePaths = saResultPath, simulation = sim)
Table parameters
Parameters defined by a table formula have special syntax of retrieving and changing the values. The value of a table parameter is given by a list of ValuePoint
objects, each ValuePoint
being an x-y value pair. X values usually refer to the simulation time.
library(ospsuite)
# Load a simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
#Get the parameter defined by a table.
tableParam <- getParameter("Organism|TableParameter", sim)
print(tableParam)
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 0.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 0, y= 0, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: FALSE
#> isStateVariable: FALSE
Direct access to the value points is possible through the TableFormula
of the table parameter. All x- or y-values stored in the table can be conveniently retrieved using the lapply
method:
library(ospsuite)
#Get the parameter defined by a table.
tableParam <- getParameter("Organism|TableParameter", sim)
print(tableParam)
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 0.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 0, y= 0, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: FALSE
#> isStateVariable: FALSE
# Get all value points
tableParam$formula$allPoints
#> [[1]]
#> x= 0, y= 0, restartSolver= FALSE
#>
#> [[2]]
#> x= 60, y= 1, restartSolver= FALSE
#>
#> [[3]]
#> x= 120, y= 2, restartSolver= FALSE
#>
#> [[4]]
#> x= 180, y= 3, restartSolver= FALSE
# Get all x-values
xValues <- lapply(tableParam$formula$allPoints, function(point){point$x})
print(xValues)
#> [[1]]
#> [1] 0
#>
#> [[2]]
#> [1] 60
#>
#> [[3]]
#> [1] 120
#>
#> [[4]]
#> [1] 180
# Get all y-values
yValues <- lapply(tableParam$formula$allPoints, function(point){point$y})
print(yValues)
#> [[1]]
#> [1] 0
#>
#> [[2]]
#> [1] 1
#>
#> [[3]]
#> [1] 2
#>
#> [[4]]
#> [1] 3
The method valueAt
of the TableFormula
returns the value of y
for the given x
. If no entry exists for the x
, the value y
is linearly interpolated between the two closest x
values.
library(ospsuite)
#Get the parameter defined by a table.
tableParam <- getParameter("Organism|TableParameter", sim)
# Value at x = 60 is stored in the table
tableParam$formula$valueAt(60)
#> [1] 1
# Value at x = 90 is not in the table
tableParam$formula$valueAt(90)
#> [1] 1.5
Changing table parameter values
Simply setting the value of a table-defined parameter using setParameterValues
will override the formula and make the parameter constant.
library(ospsuite)
#Get the parameter defined by a table.
tableParam <- getParameter("Organism|TableParameter", sim)
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 0.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 0, y= 0, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: FALSE
#> isStateVariable: FALSE
# Set value to a constant. tableParam$isFixedValue is now TRUE
setParameterValues(tableParam, 10)
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 10.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 0, y= 0, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
To change the values of the table, a set of methods of the TableFormula
is available. The method addPoints
adds a set of x-y values to the existing table. If trying to add a point with the x-value already present in the table, an error is thrown:
library(ospsuite)
tableParam <- getParameter("Organism|TableParameter", sim)
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 10.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 0, y= 0, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
# Add new points
tableParam$formula$addPoints(c(1, 2, 3), c(5, 6, 7))
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 10.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 0, y= 0, restartSolver= FALSE
#> x= 1, y= 5, restartSolver= FALSE
#> x= 2, y= 6, restartSolver= FALSE
#> x= 3, y= 7, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
#Try to add points with existing x-values
tableParam$formula$addPoints(0, 1)
#> Error in rClr::clrCall(self$ref, "AddPoint", xValues[i], yValues[i]): Type: OSPSuite.Core.Domain.ValuePointAlreadyExistsForPointException
#> Message: A point for x=0 was already added with y=1
#> Method: Int32 AddPoint(OSPSuite.Core.Domain.Formulas.ValuePoint)
#> Stack trace:
#> at OSPSuite.Core.Domain.Formulas.TableFormula.AddPoint(ValuePoint point)
#> at OSPSuite.Core.Domain.Formulas.TableFormula.AddPoint(Double x, Double y)
To remove a point from the table, use the method removePoint
. It remove a point if the x value is present in the table and has the provided y.
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 10.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 0, y= 0, restartSolver= FALSE
#> x= 1, y= 5, restartSolver= FALSE
#> x= 2, y= 6, restartSolver= FALSE
#> x= 3, y= 7, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
# Remove the point (0, 0)
tableParam$formula$removePoint(0, 0)
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 10.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 1, y= 5, restartSolver= FALSE
#> x= 2, y= 6, restartSolver= FALSE
#> x= 3, y= 7, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
# Try to remove the point (1, 1). Note that the value for x = 1 is x = 5 in the original table,
# and no point is removed.
tableParam$formula$removePoint(1, 1)
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 10.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 1, y= 5, restartSolver= FALSE
#> x= 2, y= 6, restartSolver= FALSE
#> x= 3, y= 7, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
# Try to remove a non-existing point (0, 1). No point is removed.
tableParam$formula$removePoint(1, 1)
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 10.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 1, y= 5, restartSolver= FALSE
#> x= 2, y= 6, restartSolver= FALSE
#> x= 3, y= 7, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
The method clearPoints
removes all points from the table. setPoints
is a combination of clearing the table and adding new points:
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 10.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 1, y= 5, restartSolver= FALSE
#> x= 2, y= 6, restartSolver= FALSE
#> x= 3, y= 7, restartSolver= FALSE
#> x= 60, y= 1, restartSolver= FALSE
#> x= 120, y= 2, restartSolver= FALSE
#> x= 180, y= 3, restartSolver= FALSE
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
tableParam$formula$setPoints(c(1, 2, 3, 4), c(5, 6, 7, 8))
tableParam
#> Parameter:
#> Path: Organism|TableParameter
#> Value: 10.00
#> isTable: TRUE
#> XDimension: Time
#> UseDerivedValues: FALSE
#> x= 1, y= 5, restartSolver= FALSE
#> x= 2, y= 6, restartSolver= FALSE
#> x= 3, y= 7, restartSolver= FALSE
#> x= 4, y= 8, restartSolver= FALSE
#> Value overrides formula: TRUE
#> isStateVariable: FALSE
Dimensions and Units
Unit conversion
Every entity - a molecule, a parameter, or an observer - has a certain dimension, like Amount, Concentration, or Volume. The dimension is a property of an entity:
library(ospsuite)
# Load a simulation
simFilePath <- file.path(getwd(), "..", "tests", "data", "Aciclovir.pkml", fsep = .Platform$file.sep)
sim <- loadSimulation(simFilePath)
print(sim)
#> Simulation:
#> Name: Vergin 1995 IV
#> Source file: C:/Users/appveyor/AppData/Local/Temp/1/RtmpY9evoZ/Rbuildce052b82d20/ospsuite/vignettes/../tests/data/Aciclovir.pkml
#Get the parameter volume of the liver.
livParam <- getParameter("Organism|Liver|Volume", sim)
print(livParam)
#> Parameter:
#> Path: Organism|Liver|Volume
#> Value: 2.1675 [l]
#> isDistributed: TRUE
#> isStateVariable: FALSE
# Dimension of the parameter
livParam$dimension
#> [1] "Volume"
The values of a certain dimension can be presented in different units - for example, l or ml for the dimension Volume, or mol and µmol for the dimension Amount. The list of all available units is a method of an entity:
# Dimension of the parameter
livParam$dimension
#> [1] "Volume"
# Units of the parameter
livParam$allUnits
#> [1] "l" "ml" "µl"
Internally, OSPS
works with the base units, and all the values that are shown or passed to functions are in base units by default. These base units are often different from the units that are displayed by default in PK-Sim (and MoBi). The list of base and default display units can be found in the documentation.
As an example, the parameter BMI is given in the default unit kg/dm²
, while the default display unit is the more convenient kg/m²
. The ospuite-R
package provides a set of methods for conversion between different units. The methods toUnit
, toBaseUnit
, and toDisplayUnit
require the quantity to get the correct dimension and units; however, it does not change the value of the quantity!
# Get the BMI parameter
bmiParam <- getParameter("Organism|BMI", sim)
print(bmiParam)
#> Parameter:
#> Path: Organism|BMI
#> Value: 0.23436 [kg/dm²]
#> isFormula: TRUE
#> formula: Height>0 ? BW / (Height)^2 : 0
#> Value overrides formula: FALSE
#> isStateVariable: FALSE
# Print the base and the default display units
bmiParam$unit
#> [1] "kg/dm²"
bmiParam$displayUnit
#> [1] "kg/m²"
# Convert the value from the base into the default display unit
toDisplayUnit(quantity = bmiParam, values = bmiParam$value)
#> [1] 23.43633
# Convert the value to the base unit, that can be used e.g. for setting new parameter value
toBaseUnit(quantity = bmiParam, values = 30, unit = "kg/m²")
#> [1] 0.3
liverVolume <- getParameter("Organism|Liver|Volume",sim)
print(liverVolume)
#> Parameter:
#> Path: Organism|Liver|Volume
#> Value: 2.1675 [l]
#> isDistributed: TRUE
#> isStateVariable: FALSE
liverVolume$allUnits
#> [1] "l" "ml" "µl"
# Convert from base volume unit to µl
toUnit(quantity = liverVolume, values = c(1,2,3,4), targetUnit = "ml")
#> [1] 1000 2000 3000 4000
Last updated