Dosage Regimens, Subjects, and Populations
In Pumas, subjects are represented by the Subject
type and collections of subjects are represented as Vector
s of Subject
s aliased Population
. Subjects are defined by their identifier, observations, covariates, and events. In this section we will specify the methods used for defining Subject
s programmatically or using the read_pumas
function that reads in data that follows the Pumas NLME Data Format (PumasNDF) data format. Before we look at Subject
s, we will take a look at how to define events as represented by the DosageRegimen
type.
Dosage Regimen Terminology
When subjects are subjected to treatment it is represented by an event in Pumas. Administration of a drug is represented by a DosageRegimen
that describes the amount, type, frequency and route. DosageRegimen
s can either be constructed programmatically using the DosageRegimen
constructor or from a data source in the PumasNDF format using read_pumas
. The names of the inputs are the same independent of how the DosageRegimen
is constructed. The definition of the values are as follows:
amt
: the amount of the dose. This is the only required value.time
: the time at which the dose is given. Defaults to0
.evid
: the event id.1
specifies a normal event.3
means it's a reset event, meaning that the value of the dynamical variable is reset to theamt
at the dosing event. If4
, then the dynamical value and time are reset, and then a final dose is given. Defaults to1
.ii
: the inter-dose interval. For steady state events, this is the length of time between successive doses. Whenaddl
is specified, this is the length of time to the next dose. Defaults to0
.addl
: the number of additional events of the same types, spaced byii
. Defaults to 0.rate
: the rate of administration. If0
, then the dose is instantaneous. Otherwise the dose is administrated at a constant rate for a duration equal toamt/rate
.ss
: an indicator for whether the dose is a steady state dose. A steady state dose is defined as the result of having applied the dose with the intervalii
infinitely many successive times.0
indicates that the dose is not a steady state dose.1
indicates that the dose is a steady state dose.2
indicates that it is a steady state dose that is added to the previous amount. The default is0
.route
: route of administration to be used in NCA analysis if it is carried out with the integrated interface inside@model
. Defaults toNullRoute
which is basically no route specified.
This specification leads to the following default constructor for the DosageRegimen
type:
Pumas.DosageRegimen
— TypeDosageRegimen
Lazy representation of a series of Events.
Fields
data::DataFrame
: The tabular representation of a series ofEvent
s.Signature
evts = DosageRegimen(amt::Numeric;
time::Numeric = 0,
cmt::Union{Numeric,Symbol} = 1,
evid::Numeric = 1,
ii::Numeric = zero.(time),
addl::Numeric = 0,
rate::Numeric = zero.(amt)./oneunit.(time),
duration::Numeric = zero(amt)./oneunit.(time),
ss::Numeric = 0,
route::NCA.Route)
- Examples
julia> DosageRegimen(100, ii = 24, addl = 6)
DosageRegimen
Row │ time cmt amt evid ii addl rate duration ss route
│ Float64 Int64 Float64 Int8 Float64 Int64 Float64 Float64 Int8 NCA.Route
─────┼───────────────────────────────────────────────────────────────────────────────────
1 │ 0.0 1 100.0 1 24.0 6 0.0 0.0 0 NullRoute
julia> DosageRegimen(50, ii = 12, addl = 13)
DosageRegimen
Row │ time cmt amt evid ii addl rate duration ss route
│ Float64 Int64 Float64 Int8 Float64 Int64 Float64 Float64 Int8 NCA.Route
─────┼───────────────────────────────────────────────────────────────────────────────────
1 │ 0.0 1 50.0 1 12.0 13 0.0 0.0 0 NullRoute
julia> DosageRegimen(200, ii = 24, addl = 2)
DosageRegimen
Row │ time cmt amt evid ii addl rate duration ss route
│ Float64 Int64 Float64 Int8 Float64 Int64 Float64 Float64 Int8 NCA.Route
─────┼───────────────────────────────────────────────────────────────────────────────────
1 │ 0.0 1 200.0 1 24.0 2 0.0 0.0 0 NullRoute
julia> DosageRegimen(200, ii = 24, addl = 2, route = NCA.IVBolus)
DosageRegimen
Row │ time cmt amt evid ii addl rate duration ss route
│ Float64 Int64 Float64 Int8 Float64 Int64 Float64 Float64 Int8 NCA.Route
─────┼───────────────────────────────────────────────────────────────────────────────────
1 │ 0.0 1 200.0 1 24.0 2 0.0 0.0 0 IVBolus
From various DosageRegimen
s
- Signature
evs = DosageRegimen(regimen1::DosageRegimen, regimen2::DosageRegimen; offset = nothing)
offset
specifies if regimen2
should start after an offset following the end of the last event in regimen1
.
- Examples
julia> e1 = DosageRegimen(100, ii = 24, addl = 6)
DosageRegimen
Row │ time cmt amt evid ii addl rate duration ss route
│ Float64 Int64 Float64 Int8 Float64 Int64 Float64 Float64 Int8 NCA.Route
─────┼───────────────────────────────────────────────────────────────────────────────────
1 │ 0.0 1 100.0 1 24.0 6 0.0 0.0 0 NullRoute
julia> e2 = DosageRegimen(50, ii = 12, addl = 13)
DosageRegimen
Row │ time cmt amt evid ii addl rate duration ss route
│ Float64 Int64 Float64 Int8 Float64 Int64 Float64 Float64 Int8 NCA.Route
─────┼───────────────────────────────────────────────────────────────────────────────────
1 │ 0.0 1 50.0 1 12.0 13 0.0 0.0 0 NullRoute
julia> evs = DosageRegimen(e1, e2)
DosageRegimen
Row │ time cmt amt evid ii addl rate duration ss route
│ Float64 Int64 Float64 Int8 Float64 Int64 Float64 Float64 Int8 NCA.Route
─────┼───────────────────────────────────────────────────────────────────────────────────
1 │ 0.0 1 100.0 1 24.0 6 0.0 0.0 0 NullRoute
2 │ 0.0 1 50.0 1 12.0 13 0.0 0.0 0 NullRoute
julia> DosageRegimen(e1, e2, offset = 10)
DosageRegimen
Row │ time cmt amt evid ii addl rate duration ss route
│ Float64 Int64 Float64 Int8 Float64 Int64 Float64 Float64 Int8 NCA.Route
─────┼───────────────────────────────────────────────────────────────────────────────────
1 │ 0.0 1 100.0 1 24.0 6 0.0 0.0 0 NullRoute
2 │ 178.0 1 50.0 1 12.0 13 0.0 0.0 0 NullRoute
The Subject
Constructor
The dosage regimen is only a subset of what we need to fully specify a subject. As mentioned above, we use the Subject
type to represent individuals in Pumas. They can be constructed using the Subject
constructor programmatically:
Pumas.Subject
— TypeSubject
The data corresponding to a single subject:
Fields:
id
: identifierobservations
: a named tuple of the dependent variablescovariates
: a named tuple containing the covariates, ornothing
.events
: a vector ofEvent
s.time
: a vector of time stamps for the observations
When there are time varying covariates, each covariate is interpolated with a common covariate time support. The interpolated values are then used to build a multi-valued interpolant for the complete time support.
From the multi-valued interpolant, certain discontinuities are flagged in order to use that information for the differential equation solvers and to correctly apply the analytical solution per region as applicable.
Constructor
Subject(;id = "1",
observations = NamedTuple(),
events = Event[],
time = observations isa AbstractDataFrame ? observations.time : nothing,
event_data = true,
covariates::Union{Nothing, NamedTuple} = nothing,
covariates_time = observations isa AbstractDataFrame ? observations.time : nothing,
covariates_direction = :left)
Subject
may be constructed from an <:AbstractDataFrame
with the appropriate schema or by providing the arguments directly through separate DataFrames
/ structures.
Examples:
julia> Subject()
Subject
ID: 1
julia> Subject(id = 20, events = DosageRegimen(200, ii = 24, addl = 2), covariates = (WT = 14.2, HT = 5.2))
Subject
ID: 20
Events: 3
Covariates: WT, HT
julia> Subject(covariates = (WT = [14.2, 14.7], HT = fill(5.2, 2)), covariates_time = [0, 3])
Subject
ID: 1
Covariates: WT, HT
or using read_pumas
from tabular data:
Pumas.read_pumas
— Functionread_pumas(filepath::String; missingstring = ["", ".", "NA"], kwargs...)
read_pumas(
df::AbstractDataFrame;
observations=Symbol[:dv],
covariates=Symbol[],
id::Symbol=:id,
time::Symbol=:time,
evid::Union{Nothing,Symbol}=nothing,
amt::Symbol=:amt,
addl::Symbol=:addl,
ii::Symbol=:ii,
cmt::Symbol=:cmt,
rate::Symbol=:rate,
ss::Symbol=:ss,
route::Symbol=:route,
mdv::Symbol=nothing,
event_data::Bool=true,
covariates_direction::Symbol=:left,
check::Bool=event_data,
adjust_evid34::Bool=true
)
Import NMTRAN-formatted data. You can either pass a CSV file path as a String
or a DataFrame
as the first and only positional argument.
df
:DataFrame
contaning the data to be converted to aVector{<:Subject}
.observations
: dependent variables specified by a vector of column names.covariates
: covariates specified by a vector of column names.id
: specifies the ID column of theDataFrame
.time
: specifies the time column of theDataFrame
.evid
: specifies the event ID column of theDataFrame
. See?Pumas.Event
for more details.amt
: specifies the dose amount column of theDataFrame
. See?Pumas.Event
for more details.addl
: specifies the column of theDataFrame
that indicated the number of repeated dose events. If not specified then the value is zero.ii
: specifies the dose interval column of theDataFrame
. See?Pumas.Event
for more details.cmt
: specifies the compartment column of theDataFrame
. See?Pumas.Event
for more details.rate
: specifies the infusion rate column of theDataFrame
. See?Pumas.Event
for more details.ss
: specifies the steady state column of theDataFrame
. See?Pumas.Event
for more details.route
: specifies the route of administration column of theDataFrame
. See?Pumas.Event
for more details.mdv
: specifies the the column of theDataFrame
indicating if observations aremissing
.event_data
: toggles assertions applicable to event data. More specifically, checks if the following columns are present in theDataFrame
, either as the default values or as user-defined values::id
,:time
, and:amt
. If no:evid
column is present, then a warning will be thrown, and:evid
is set to1
when:amt
values are>0
or notmissing
, or:evid
is set to0
when:amt
values aremissing
and observations are notmissing
. Otherwise,read_pumas
will throw an error.covariates_direction
: specifies direction of covariate interpolation. Either:left
(Last Observation Carried Forward, LOCF) (default), or:right
(Next Observation Carried Backward, NOCB). Notice, that for model with occasion variables it is important to use:left
for the correct behavior of the interpolation.check
: toggles NMTRAN compliance check of the input data. More specifically, checks if the following columns are present in theDataFrame
, either as the default values or as user-defined values::id
,:time
,:amt
,:cmt
,:evid
,:addl
,:ii
,:ss
, and:route
. Additional checks are:- all variables in
observations
are numeric, i.e.Integer
orAbstractFloat
. :amt
column is numeric, i.e.Integer
orAbstractFloat
.:cmt
column is either a positiveInteger
, anAbstractString
, or aSymbol
.:amt
values must bemissing
or0
whenevid = 0
; or>=0
otherwise.- all variables in
observation
aremissing
whenevid = 1
. :ii
column must be present if:ss
is specified or present.:ii
values must bemissing
or0
whenevid = 0
.:ii
column must be>0
if:addl
values are>0
, and vice-versa.:addl
column, if present, must be>=0
whenevid = 1
.:evid
values must be!=0
when:amt
values are>0
, or:addl
and:ii
values are>0
.
- all variables in
adjust_evid34
: toggles adjustment of time vector for reset events (evid = 3
andevid = 4
). Iftrue
(the default) then the time of the previous event is added to the time on record to ensure that the time vector is monotonically increasing.
You can also create Subject
s from an existing Subject
:
Pumas.Subject
— MethodSubject(subject::Subject; id::AbstractString, events)
Construct a Subject
from an existing subject
while replacing information according to the keyword arguments. The possible keyword arguments are
id
, sets the subject identifier to the stringid
. Defaults to the identifier already insubject
.events
, sets the subject events to the inputDosageRegimen
. Defaults to the events already present insubject
.covariates
andcovariates_times
, used as input to add covariate information
Examples:
```jldoctest julia> s1 = Subject(; id = "AKJ491", events = DosageRegimen(1.0; time = 1.0), ) Subject ID: AKJ491 Events: 1
julia> Subject( s1; id = "AKJ492", ) Subject ID: AKJ492 Events: 1
The simulated output of a PumasModel
as a result of simobs
is Pumas.SimulatedObservations
. Passing this simobs
output into a vectorized Subject
will result in a Population
that is equivalent to the output of read_pumas
. This is a convenient feature that allows one to simulate data and turn it back into a Population
that can then be passed into a fit
function:
Pumas.Subject
— MethodSubject
Constructor
Subject(simsubject::SimulatedObservations)
Roundtrip the result of simobs
, i.e. SimulatedObservations to a Subject
/Population
Example:
sims = simobs(model, pop, params)
To convert sims
to a Population
, broadcast as below
Subject.(sims)
PumasNDF
The PumasNDF is a specification for building a Population
(an alias for a vector of Subject
's') from tabular data. Generally this tabular data is given by a database like a CSV. The CSV has columns described as follows:
id
: the ID of the individual. Each individual should have a unique integer, or string.time
: the time corresponding to the row. Should be unique per id, i.e. no duplicate time values for a given subject.evid
: the event id.1
specifies a normal event.3
means it's a reset event, meaning that the value of the dynamical variable is reset to theamt
at the dosing event. If4
, then the dynamical value and time are reset, and then a final dose is given. Defaults to0
if amt is0
or missing, and 1 otherwise.amt
: the amount of the dose. If theevid
column exists and is non-zero, this value should be non-zero. Defaults to0
.ii
: the inter-dose interval. Whenaddl
is specified, this is the length of time to the next dose. For steady state events, this is the length of time between successive doses. Defaults to0
, and is required to be non-zero on rows where a steady-state event is specified.addl
: the number of additional doses of the same time to give. Defaults to0
.rate
: the rate of administration. If0
, then the dose is instantaneous. Otherwise, the dose is administrated at a constant rate for a duration equal toamt/rate
. Arate=-2
allows therate
to be determined by Dose Control Parameters (DCP). Defaults to0
.ss
: an indicator for whether the dose is a steady state dose. A steady state dose is defined as the result of having applied the dose with the intervalii
infinitely many successive times.0
indicates that the dose is not a steady state dose.1
indicates that the dose is a steady state dose.2
indicates that it is a steady state dose that is added to the previous amount. The default is0
.cmt
: the compartment being dosed. Defaults to1
.duration
: the duration of administration. If0
, then the dose is instantaneous. Otherwise, the dose is administered at a constant rate equal toamt/duration
. Defaults to0
.- Observation and covariate columns should be given as a time series of values of matching type. Constant covariates should be constant through the full column. Time points without a measurement should be denoted by a dot (
.
).
If a column does not exist, its values are imputed to be the defaults. Special notes:
- If
rate
andduration
exist, then it is enforced thatamt=rate*duration
. - All values and header names are interpreted as lower case.
Given the information above, it is important to understand how to read a dataset using the CSV
package. We recommend that all blanks (""
), .
's, NA
's and any other character elements in your dataset be passed to the missingstring
keyword argument when reading the file as below:
using CSV
data = CSV.read(
joinpath("pathtomyfile", "mydata.csv"),
DataFrame;
missingstring = ["", ".", "NA", "BQL"],
)
For more information check out the CSV
documentation.