.. _inter_subject_variation:

Inter-Subject Variation (ISV)
###############################

One way to model random variability between individuals is to use a :term:`mixed effect model`. With this approach, we assign a set of one or more :term:`random effects` to every individual such that their model parameters (|eg| the clearance, :pyml:`m[CL]`) can deviate from the population values.

The random effect, :pyml:`r[CL_isv]` for example, is a realization of a random variable drawn from a probability distribution. Typically, this is a normal distribution with the mean fixed at zero and a variance that is estimated from the data, though other distributions are possible.

This is then combined with the population value to give an individualized value for the PK parameter. For example, we can use an additive model such that an individual's pharmacokinetic parameters deviate from the population mean:

.. code-block:: pyml

    m[CL] = f[CL] + r[CL_isv]

Additive models can also be used for parameters such as lag times when the exact time of a dose event is not known, or when a measurement has no meaningful zero reference point (like temperature). 

Most physiological quantities, however, are constrained to be positive (|eg| clearances, volumes) such that an additive model can cause problems if :pyml:`m[CL]` becomes negative. It is therefore common instead to impose a log-normal distribution over :pyml:`m[CL]` by applying the additive model in a log-transformed space:
    
.. code-block:: pyml

    m[LOG_CL] = log(f[CL]) + r[CL_isv]
    ...
    CL = exp(m[LOG_CL])

or, equivalently,
    
.. code-block:: pyml

    m[CL] = f[CL] * exp(r[CL_isv])

    
.. _data_synthesis_isv:

Data Synthesis with ISV
==========================
.. note:: See :ref:`sum_link_d1cmp_cl_isv_tut`, :ref:`sum_link_d1cmp_cl_isv_01_tut` and :ref:`sum_link_d1cmp_cl_isv_05_tut` for the :ref:`tut_script` used to generate results in this section. 

We illustrate Inter Subject Variability (sometimes referred to as "Between Subject Variability") using an example based on the one compartment model with absorption that was introduced earlier (:ref:`dep_one_cmp_cl`).
   
Because we now want several individuals, we make three changes to the |effects| section of the script:

#. move values that vary between individuals (:pyml:`c[ID]`, :pyml:`c[AMT]` and time points :pyml:`t[RESET]`, :pyml:`t[DOSE]` and :pyml:`t[OBS]`) from the |pop| level into a new level, |id|. 
#. add to the |id| level an individual-specific random effect, :pyml:`r[CL_isv]`, that is responsible for inter-subject variation in the model parameter *CL*.
#. add to the |pop| level a population-specific fixed effect, :pyml:`f[CL_isv]`, that specifies the :term:`variance` (|ie| the spread) of the random effects, :pyml:`r[CL_isv]`. 

.. literalinclude:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv/gen_sections/EFFECTS.pyml
    :language: pyml
    
.. note:: The |id| level sits below |pop| to indicate that there should be a branch of the hierarchy created for every individual in the population.

During data synthesis, |popy| adds random variation between individuals by sampling realizations of :pyml:`r[CL_isv]` from the probability distribution. These realizations of :pyml:`r[CL_isv]` are then used in the |model_params| section to add inter-subject variability to the model parameter, :pyml:`m[CL]`.

.. literalinclude:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv/gen_sections/MODEL_PARAMS.pyml
    :language: pyml

The rest of the script (|eg| |derivatives| and |predictions|) are the same as for a single individual.

This variation changes the shape of the predicted curves over the set of individuals in the population (:numref:`fig_isv_examples`).

.. list-table:: Population graphs with increasing ISV: (left) CL_isv=0.01; (centre) CL_isv=0.2; (right) CL_isv=0.5
    :class: image_table
    :name: fig_isv_examples

    * - .. thumbnail:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv_01/images/gen_sim_grph_outputs/allOBS_vs_TIME/comb_spag.*
      - .. thumbnail:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv/images/gen_sim_grph_outputs/allOBS_vs_TIME/comb_spag.*
      - .. thumbnail:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv_05/images/gen_sim_grph_outputs/allOBS_vs_TIME/comb_spag.*


Naïve ISV Fit
==========================
.. note:: See the :ref:`sum_link_d1cmp_cl_isv_naive_tut` for the :ref:`tut_script` used to generate results in this section. 

Given a dataset where there are 30 subjects with ISV, we first investigate the effect of excluding ISV from the model we fit.

We can do this without changing the data synthesis code (|eg| the |model_params| section) by fixing :pyml:`f[CL_isv]` at zero such that all deviations from the population prediction are accounted for under the residual error model. 

.. literalinclude:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv_naive/fit_sections/EFFECTS.pyml
    :language: pyml

After the fit, we see that the population parameters (|ie| the fixed effects) are poorly estimated. In particular, the noise levels :pyml:`f[PNOISE_STD]` and :pyml:`f[ANOISE_STD]` are far higher than the true values because they are responsible for capturing the variation that, in reality, is ISV rather than noise.

.. literalinclude:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv_naive/final_fx_params.txt
    :language: pyml

As a reference point, the final objective function value is

.. literalinclude:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv_naive/d1cmp_cl_isv_naive_fit.pyml_output/solN/final_obj_value.txt

    
Mixed Effect ISV Fit
================================
.. note:: See the :ref:`sum_link_d1cmp_cl_isv_tut` for the :ref:`tut_script` used to generate results in this section. 

We now look at a mixed effects model that allows model parameters (and predictions) to be tailored to each individual by making the ISV variance, :pyml:`f[CL_isv]`, a parameter to be optimized:

.. literalinclude:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv/fit_sections/EFFECTS.pyml
    :language: pyml

As a result, the population parameters are now much closer to the values used for data synthesis (shown above). In particular, we see that the noise parameters are much more accurate since the ISV can be accounted for using :pyml:`f[CL_isv]` rather than the residual noise model.
    
.. literalinclude:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv/final_fx_params.txt
    :language: pyml

For comparison, we can also see that the final objective function value is also far lower than that obtained without modelling ISV:

.. literalinclude:: /_autogen/pop_examples/compartment_models/d1cmp_cl_isv/d1cmp_cl_isv_fit.pyml_output/solN/final_obj_value.txt

Variation between subjects is just one of many sources of randomness in population data. The next source we will look at is variation within a subject from one visit to another - :ref:`inter_occasion_variation`.
