7 Design Object

7.1 Design Object overview

The Design Object is intended to provide information for creating simulation or evaluation of trial designs, and design space information required for optimal design. For trial simulation or design evaluation, the trial design is fixed and should be completely defined. For optimal design the user should specify a design space to optimise over in the DESIGN_SPACES block.

The user should specify all required interventions (drug administrations), sampling (or observation) schedules, populations, covariate distributions, and design parameters. These are then combined in the STUDY_DESIGN block to completely define study design(s). For simulation and evaluation only one design should be specified. For optimal design, many study designs can be considered and the DESIGN_SPACES block will determine what attributes the optimisation algorithm will search over.

An elementary design is given by the combination of INTERVENTION + SAMPLING, and can describe the design for groups of subjects e.g. treatment arms, or can define a unique design for an individual. In optimal design the combination of treatment arms and numbers of subjects in each is called the population design.

7.2 INTERVENTION

The INTERVENTION block contains details of administration schedules and types and how these are combined to form treatment interventions. Note here that we distinguish between treatment interventions (including placebo treatment, non-medical treatments, drug-free periods) and treatment arms, since an arm of a study may be purely observational i.e. with no treatment intervention. For the optimisation task of optimal design, the INTERVENTION block defines the treatment definitions for the starting design (if required by the algorithm).

The syntax for this block is:

<name> : { type is bolus,
  input = <Model Object dosingTarget>,
  amount = <real value or vector of real values>,
  doseTime = <vector of real values>,
  ssInterval = <real value>,
  timeLastSSDose = <real value>,
  doseIntervalVar = <dosing interval variable reference>,
  lastDoseTimeVar = <time of last dose variable reference>
  }

In the above, ssInterval and timeLastSSDose, doseIntervalVar, lastDoseTimeVar are optional.

<name> : { type is infusion,
  input = <Model Object dosingTarget>,
  amount = <real value>,
  rate = <vector of real values >,
  doseTime = <vector of real values>,
  duration = < vector of real values >,
  ssInterval = <real value>,
  timeLastSSDose = <real value>,
  timeStopSSInfusion = <real value>,
  doseIntervalVar = <dosing interval variable reference>,
  lastDoseTimeVar = <time of last dose variable reference>
}

In the above, one of duration or rate must be present. If doseTime is not present, then timeLastSSDose or timeStopSSInfusion must be present.

<name> : { type is combi,
  combination = <vector of previously defined interventions>,
  start = <vector of start times>,
  end = <vector of end times>
  }

The combi type is used to combine existing (already defined) intervention schedules to form more complex dosing regimens.

<name> : {type is reset,
  reset = { variable = <Model Object dosingTarget variable>,
  resetTime = <real value>,
  value = <real value>}
}

The reset type is used to reset the dosing variable in the Model Object at a given time.

<name> : {type is resetAll}

The resetAll type is used to reset all dosing variables.

For example, defining a single oral administration to the GUT at time 0 for use with the warfarin example (/Design/UseCase1_design1_eval):

INTERVENTION{
  admin1 : {type is bolus, input = GUT, amount = 100, doseTime = [0] }
}

Another example showing single dose administration with an oral dose to the GUT and an infusion to the CENTRAL compartment (UseCase4_design1_eval):

INTERVENTION{
  admin1 : {type is infusion, input = CENTRAL, amount = 100, 
          doseTime = 0, duration = 100 }

  admin2 : {type is bolus, input = GUT, amount = 150, doseTime = [0] }
}

A more complex example showing how interventions can be combined to define sequences of interventions and actions.

INTERVENTION{

  ivbolus : {type is bolus, input = CENTRAL, amount = 100, doseTime = 0 }

  oral4 : {type is bolus, input = GUT, amount = 150, doseTime = [0,24,48,72] }

  ivinf : {type is infusion, input = CENTRAL, amount = 100, doseTime = 0, 
  duration = 1 }

  wash1 : {type is resetAll}

  ivoral : {type is combi, combination = [ivbolus, wash1, oral4], 
  start = [0, 24, 48]}

  oralinf : {type is combi, combination = [oral4, wash1, ivinf], 
  start = [0, 96, 120]}

}

The above example describes three different drug administrations – an IV bolus dose, four doses of oral drug separated by 24 hours, and an IV infusion over the space of 1 hour. It also describes a washout “event” which resets the amount in all dosing variables in the model. We can then combine these four interventions and actions into a treatment arm definition. So the ivoral arm receives the ivbolus dose at time zero, then a washout / reset at 24 hours followed by the four oral doses starting at 48 hours. Note that the doseTime argument in each intervention definition defines the dosing time relative to the respective value in the start argument of the combination definition. Similarly, the oralinf arm receives the four doses of oral drug, followed by a washout / reset event at 96 hours then the ivinf treatment starting at 120 hours.

That is:

Time 0 24 48 72 96 120
ivoral ivbolus wash1 oral4[1] oral4[2] oral4[3] oral4[4]
oralinf oral4[1] oral4[2] oral4[3] oral4[4] wash1 ivinf

Note that for vectors of times, the seq(…) function can be used to specify a sequence of times with starting time, stopping time and interval size (MDL_Reference Guide section 5.80).

7.3 SAMPLING

Similar to the INTERVENTION block, the SAMPLING block provides a means to describe observation schedules which can then be used for individuals, for treatment arms or in combination to define complex patterns of observation. For the optimisation task in optimal design, the SAMPLING block defines the starting design sample times (if required by the algorithm).

The syntax for this block is:

<name> : {type is simple, 
  outcome = <Model Object OBSERVATION block variable>,
  sampleTime = <vector of real values>,
  numberTimes = <integer>,
  deltaTime = <real value>,
  blq = <real value>,
  ulq = <real value>,
  }

In the above definition, the outcome argument is mandatory, all other arguments are optional. numberTimes defaults to the length of the sampleTime vector. Either numberTimes or sampleTime should be used, not both. Note that numberTimes should only be used in the context of Optimal Design optimisation tasks and not for design evaluation or simulation. deltaTime is the minimum time between two samples (for use in optimal design).

To combine a number of sampling definitions, the user can use the following syntax:

<name> { type is combi,
combination = [<vector of previously defined sampling schedules>,
  numberTimes = <integer>,
  start = <vector of real values>,
  relative = < Boolean>
}

The combination argument is mandatory, other arguments are optional.

For an example of definition of “simple” sampling scheme (UseCase1_design1_eval):

SAMPLING{
  window1 : {type is simple, outcome = Y,
  sampleTime = [0.0001, 24, 36, 48, 72, 96, 120] }
  }

For an example of combining sampling schedules (UseCase3_design1_eval):

SAMPLING{
  winPK : {type is simple, outcome = CC,
  sampleTime = [0.0001, 24, 36, 48, 72, 96, 120] }

  winPD : { type is simple, outcome = PCA,
  sampleTime = [0.0001, 24, 36, 48, 72, 96, 120] }

  # implies concurrent start, both start 0 unless define times
  sampPKPD : {type is combi, combination = [winPK,winPD] }
}

In the above, the sampling schedules for winPK and winPD start concurrently (at time 0) – there is no vector of start times to offset winPK and winPD.

7.4 POPULATION

The POPULATION block initialises and defines population characteristics or distributions for use in defining covariate distributions within the Model Object COVARIATES block. The POPULATION block acts like a COVARIATES block for the Design Object, where the user defines covariate distributions and how these may differ for each study arm. The COVARIATES block in the Model Object defines how (observed) covariates are used in the model.

The syntax for the POPULATION block is:

<population_name> : { type is template,
  covariate = [<list of covariate definitions>] }

Each covariate definition should have the following syntax. For continuous covariates:

{cov = <covariate name>, rv ~ <ProbOnto distribution>}

For discrete covariates:

{catCov = <covariate name>, discreteRv ~ <ProbOnto distribution>}

It is possible to define an arm to contain only one level of a categorical covariate (defined in the POPULATION block) by using the following syntax:

{catCovValue = <categorical covariate category>}

Note that covariates defined in the POPULATION block should be declared in a DECLARED_VARIABLES block within the Design Object.

For example, for the Design Object to be used with UseCase5 which uses WT, SEX and AGE as covariates (UseCase5_design2_opt.mdl):

DECLARED_VARIABLES{
  …
  SEX withCategories{female, male}
  }

POPULATION{
  default : { type is template, 
    covariate = { catCov = SEX, discreteRv ~ Bernoulli1( probability = 0.5) } 
      }

  arm2Pop : { type is template, covariate = { catCovValue = SEX.female } }
  }

In the above example, a default distribution is defined for the SEX covariate which has categories female and male and defines that 50% of subjects should be male. (The Bernoulli distribution defines probability of the second category). arm2Pop is defined as having ONLY female subjects.

Another example for the same model:

POPULATION{
  default : { type is template,
  covariate = [
    { catCov = SEX, discreteRv ~ Bernoulli1(probability = 0.5) },
    { cov = WT, rv ~ Normal1(
        mean =  piecewise{{ 70 when SEX == SEX.male; otherwise 60 }},
        stdev = 10)
      }
    ]
  }

arm2Pop : { type is template, 
  covariate = [
    { catCovValue = SEX.female }, 
    { cov = WT, rv ~ Normal1(mean = 55, stdev = 5) }
      ]
    }
    
  }

In the above example, SEX is defined as having 50% probability of being male, and WT is defined as having a Normal1 distribution where the mean depends on the value of SEX. If SEX is male then the mean is 70, whereas if female then the mean is 60. Both populations have a standard deviation of 10 for WT. arm2Pop is exclusively female and WT is defined separately for this group.

The populations defined in the POPULATION block are used in definition of the study arms within the STUDY_DESIGN block. For example:

STUDY_DESIGN{
  arm1 : {
    armSize = 16,
    interventionSequence = [{ admin = admin1, start = 0 }],
    
    samplingSequence = [{ sample = window1, start = 0 }],
    
    population = default
    }

  arm2 : {
    armSize = 17,
    interventionSequence = [{ admin = admin1, start = 0 }],
    
    samplingSequence = [{ sample = window1, start = 0 }],
    
    population = arm2Pop
    }

  }

7.5 STUDY_DESIGN

The STUDY_DESIGN block defines how the SAMPLING, INTERVENTION and POPULATION blocks are used to define arms in a study design. For the optimisation task of optimal design, it defines the starting design (if required by the algorithm). For evaluation and simulation tasks it defines the study design to be evaluated or simulated.

The syntax for defining each arm is as follows:

<name> : {armSize = <integer value>, 
  sameTimes = <Boolean>,
  occasionSequence = [{occasion=<vector>, 
    level=<reference varLevel>, 
    start=<vector>}],

  interventionSequence=[{admin = <INTERVENTION block list name>, 
    start = <real value> }],

  samplingSequence = [{sample = <SAMPLING block list name>,
    start = <real value> }],

  population = <POPULATION block list name> 

  totalSize = <integer value>

  numberSamples = <vector of integer>

  totalCost = <real value>

  numberArms = <vector of integer>

  sameTimes = <Boolean>
  }

Recall that the intervention (doseTime argument) and sampling times (sampleTime argument) specified are relative. Within the STUDY_DESIGN block definitions we can specify start times for these that define in study time, when each starts. Using this construct it is possible to define interventions and samples that happen concurrently, and also those that happen sequentially. If the start argument is not given in interventionSequence or samplingSequence then it is assumed to be zero and the start times are taken from the relevant INTERVENTION and SAMPLING block definitions.

armSize defines the size of each arm.

If multiple outcomes are defined, then sameTimes (if true) denotes that the same observation times are to be used for all outcomes.

Additionally and optionally, arguments may be given pertaining to the study design as a whole. These are defined using the set keyword and are comma separated:

totalSize defines the overall size of the study. This defaults to the sum of the individual armSize arguments.

numberSamples defines the constrain on the number of samples for one subject. If one value is given, the number of samples should be equal to that value for all designs. If several values are given then this defines the set of number of samples allowable in designs (primarily used in optimal design).

totalCost defines the total cost for the entire population design.

numberArms defines the constraint on the number of arms in the study. If a single value is given then the final design will have exactly the required number of arms. If several values are given then this defines the set of number of arms allowable in designs (primarily used in optimal design).

sameTimes defines whether the sample sampling times are to be used for all observed outcomes.

As an example of the STUDY_DESIGN block (UseCase5_design2_opt.mdl):

STUDY_DESIGN{
  arm1 : {
    armSize = 16,
    interventionSequence = [{ admin = admin1, start = 0 }],
    samplingSequence = [{ sample = window1, start = 0 }],
    population = default 
    }

  arm2 : {
    armSize = 17,
    interventionSequence = [{ admin = admin1, start = 0 }],
    samplingSequence = [{ sample = window1, start = 0 }],
    population = arm2Pop
    }
  }

Another example showing how arguments like totalSize and numberSamples should be used (when optimising a study design):

STUDY_DESIGN{
  set totalSize = 40,
  numberSamples = 4

  arm1 : {
    interventionSequence = [{ admin = admin1, start = 0 }],
    samplingSequence = [{ sample = window1, start = 0 }],
    population = default
    }

  …

  }

7.6 DESIGN_SPACES

The DESIGN_SPACES block defines which design elements should be optimised in finding the optimal design. A design space defines the possible values of the design variables specified in SAMPLING, INTERVENTION, POPULATION blocks. It should not be used with design evaluation (EVALUATE task in the Task Properties object) or simulation. If no design space is defined for a variable e.g. amount or sampling schedule then it is assumed fixed for the optimisation process.

The syntax for DESIGN_SPACES definitions is as follows:

<name> : {objRef = <named object in INTERVENTION, SAMPLING or POPULATION>,
  element is <variable from named object above>,
  discrete = <vector of values, with type dependent on original argument >,
  range = <vector of values defining upper and lower range of values to be 
    explored, with type dependent on original argument>
}

Valid choices for element depend on the object type (SAMPLING, INTERVENTION, POPULATION) that is being referenced: bolusAmt, infAmt, duration, sampleTime, numberTimes, covariate, numberArms, armSize, parameter, doseTime.

For example (UseCase1_design2_optFW.mdl):

warfarin_PK_ODE_design = designObj{
  …
  SAMPLING{
    window1 : {type is simple, sampleTime = [0.0001, 36, 96, 120], outcome = Y }
    }

  DESIGN_SPACES{
    DS1 : { objRef = [window1], element is sampleTime,
      discrete = [0.0001,24, 36,48,72,96, 120] }

    DS2 : { objRef = [window1], element is numberTimes, 
      discrete = [4,5] }
    }
  …
  }

In the above example the DESIGN_SPACES defines how the optimisation algorithm will investigate the optimal design based on the window1 defined within the SAMPLING block, examining designs with 4 or 5 sample points chosen from the sample times defined in DS1 i.e. [0.0001, 24, 36, 48, 72, 96, 120]. The sample times defined in window1 of the SAMPLING block are used as the starting design for optimisation.

Another example:

warfarin_PK_SEX_design = designObj{
  …

  INTERVENTION{
    admin1 : {type is bolus, input = INPUT_KA, amount = 100, doseTime = [0] }
    }

  SAMPLING{
    window1 : {type is simple, 
      sampleTime = [0.0001, 24, 36, 48, 72, 96, 120], 
      outcome = Y }
    }

  STUDY_DESIGN{
    arm1 : {
    armSize = 16,
    interventionSequence = [{ admin = admin1, start = 0 }],
    samplingSequence = [{ sample = window1, start = 0 }],
      }
    
    arm2 : {
    armSize = 17,
    interventionSequence = [{ admin = admin1, start = 0 }],
    samplingSequence = [{ sample = window1, start = 0 }],
      }
    }

  DESIGN_SPACES{
    DS1 : { objRef = [window1], element is sampleTime,
      discrete = [0.0001, 24, 36, 48,72,96, 120] }
      
    DS2 : { objRef = [window1], element is numberTimes,
      discrete = [4,5] }
      
    DS3 : { objRef = [admin1], element is bolusAmt,
      discrete = seq(100,300,100) }
      
    DS4 : { objRef = [arm1, arm2], element is armSize, 
      range = [0,30] }
    }
    
  }

In the above example several design space elements are defined. DS1 defines possible sampling times for window1, while DS2 defines that designs of 4 or 5 samples are to be considered. DS3 specifies that the amount to be dosed should vary between 100 and 300 with steps of 100. Finally DS4 specifies how the number of subjects in each arm should be in the range [0,30] (inclusive) for both arms.

7.7 DESIGN_PARAMETERS

This block defines parameter values (constants) required for use in defining the design or to pass as constants to the model. Values are defined by assignment = or by equation =

.

Variables defined in DESIGN_PARAMETERS can be used in definition of covariate distributions defined in Design Object blocks.

Recall the example above where the distribution of covariates was defined in the POPULATION block:

POPULATION{
  default : { type is template,
    covariate = [
    { catCov = SEX, discreteRv ~ Bernoulli1(probability = 0.5) },
    { cov = WT, rv ~ Normal1(
      mean = piecewise{{ 70 when SEX == SEX.male; otherwise 60 }},
      stdev = 10)  
      }
    ]
  }

  arm2Pop : { type is template, 
    covariate = [
      { catCovValue = SEX.female },
      { cov = WT, rv ~ Normal1(mean = 55, stdev = 5) }
      ]
    }
  }

We can define the population means for weight in each population in the DESIGN_PARAMETERS block and pass these values into the POPULATION block definitions.

DESIGN_PARAMETERS{
  maleMeanWT = 70
  femaleMeanWT = 60
  femaleMeanWTArm2 = 55
  stdevWT = 10
  }

POPULATION{
  default : { type is template,
  covariate = [
  { catCov = SEX, discreteRv ~ Bernoulli1(probability = 0.5) },
  { cov = WT, rv ~ Normal1(
      mean = piecewise{{ maleMeanWT when SEX == SEX.male; 
        otherwise femaleMeanWT }},
      stdev = stdevWT) 
        }
      ] 
    }

  arm2Pop : { type is template,
    covariate = [
      { catCovValue = SEX.female },
      { cov = WT, rv ~ Normal1(mean = femaleMeanWTArm2, stdev = stdevWT) }
      ]
    }
  }