---
title: "Dimensions and Units"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Dimensions and Units}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
# Evaluate the runtime chunks only when the OSPSuite .NET runtime initialised
# successfully (native libraries + .NET). On machines without a working runtime
# the code is shown but not executed, so the vignette still renders.
.ospRuntimeAvailable <- isTRUE(tryCatch(
  requireNamespace("ospsuite", quietly = TRUE) &&
    ospsuite::getOSPSuiteSetting("initialized"),
  error = function(e) FALSE
))
knitr::opts_chunk$set(
  eval = .ospRuntimeAvailable,
  collapse = TRUE,
  comment = "#>",
  fig.showtext = TRUE
)
```

## 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:

```{r dimension}
library(ospsuite)

# Load a simulation
simFilePath <- system.file("extdata", "Aciclovir.pkml", package = "ospsuite")
sim <- loadSimulation(simFilePath)

# Get the parameter volume of the liver.
livParam <- getParameter("Organism|Liver|Volume", sim)
print(livParam)

# Dimension of the parameter
livParam$dimension
```

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 for an entity can be obtained using `allUnits()` method:

```{r allUnits}
# Dimension of the parameter
livParam$dimension

# Units of the parameter
livParam$allUnits
```

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](https://docs.open-systems-pharmacology.org/appendix/appendix).

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}` 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!

```{r unitConversion}
# Get the BMI parameter
heightParam <- getParameter("Organism|Height", sim)
print(heightParam)

# Print the base and the default display units
heightParam$unit
heightParam$displayUnit

# Convert the value from the base into the default display unit
toDisplayUnit(quantity = heightParam, values = heightParam$value)

# Convert the value to the base unit, that can be used. e.g. for setting new parameter value
toBaseUnit(quantity = heightParam, values = 180, unit = "cm")

liverVolume <- getParameter("Organism|Liver|Volume", sim)
print(liverVolume)

liverVolume$allUnits

# Convert from base volume unit to µl
toUnit(quantity = liverVolume, values = c(1, 2, 3, 4), targetUnit = "ml")
```
