.. _predictions:

PREDICTIONS
#############

A required :term:`verbatim` section that defines model |px| prediction variables, but also compares |px| variables to |cx| data and evaluates likelihoods or samples new |cx| data. 

The |predictions| section takes as input |cx|, |mx| and |sx| variables and outputs |px| data. The |predictions| section is required in the following scripts:-

* :ref:`tut_script`
* :ref:`gen_script`
* :ref:`fit_script`
* :ref:`sim_script`
* :ref:`mtut_script`
* :ref:`mgen_script`
* :ref:`mfit_script`
* :ref:`msim_script`

|ie| Any :ref:`gen_script`/:ref:`sim_script` that samples new data points or any :ref:`fit_script` that evaluates likelihoods requires a |predictions| section.


.. _example_predictions_pk:

Example PREDICTIONS for PK Model
===========================================

The example below is used in :ref:`builtin_fit_example`.

.. literalinclude:: 
    /_autogen/quick_start/builtin_fit_example/fit_sections/PREDICTIONS.pyml
    :language: pyml

In a :ref:`fit_script` the |predictions| section above computes a likelihood by comparing the :pyml:`p[DV_CENTRAL]` predictions computed by the model and the :pyml:`c[DV_CENTRAL]` values found in the |data_file|. 

The noise model is a combined additive and proportional noise model. See :ref:`error_models` for more details on types of noise model.

Note that in :ref:`builtin_gen_example`, the |predictions| section is exactly the same as above, however the interpretation of this line is different:-

.. code-block:: pyml

    c[DV_CENTRAL] ~ norm(p[DV_CENTRAL], var)
    
In a :ref:`gen_script` this line is now used to sample new values of :pyml:`c[DV_CENTRAL]` when creating a new data set.

The dual nature of the '~' symbol allows the same |predictions| section to be re-used throughout multiple scripts.
    
.. _example_predictions_pd:

Example PREDICTIONS for PD Model
===========================================
    
See :ref:`sum_link_direct_pd_tut` for an example :ref:`tut_script`, using the following |predictions| section for a |pd| model:-

.. literalinclude:: 
    /_autogen/indiv_examples/pd_models/direct_pd/fit_sections/PREDICTIONS.pyml
    :language: pyml
    
In the above example the structure of the |predictions| section is the same as the :ref:`example_predictions_pk`, however this time the likelihood/sampling is between the :pyml:`c[MARKER]` data and :pyml:`p[MARKER]` predictions, using an additive noise model.

A more complex |predictions| section is shown below. See :ref:`sum_link_direct_pd_simul_tut`:-
   
.. literalinclude:: 
    /_autogen/indiv_examples/pd_models/direct_pd_simul/fit_sections/PREDICTIONS.pyml
    :language: pyml
   
If the |predictions| block occurs in a :ref:`gen_script` then both the :pyml:`c[CENTRAL]` and :pyml:`c[MARKER]` fields are sampled. If this |predictions| section is included in a :ref:`fit_script` then there are two different data fields that contribute to the likelihood, namely 'CENTRAL' and 'MARKER'. 

In the :ref:`fit_script` case the likelihood is evaluated for a particular '~' expression for every |obs| row in the data set. The contribution to the likelihood of a particular |cx| variable can also be controlled by the |cxflag| field, if present in the |data_file|. This mechanism avoids erroneously computing likelihoods against null values. This is similar to |nonmem|'s MDV flag, but each |popy| |cx| variable is allowed to have it's own |cxflag|.

Note that |nonmem| is restricted to a single DV field. The only way to perform a simultaneous fit within |nonmem| is to mangle the data set by concatenating different fields into one column, because you can only have one likelihood per data row. This is unpleasant and error prone. The |popy| syntax above avoids this nightmare and handles any number of fields elegantly without changing the natural |data_file| structure.

.. _example_predictions_blq_observations:

Example PREDICTIONS for BLQ Observations
===========================================

.. comment
    should create a working tut example then link to the PREDICTIONS.pyml file here,
    like the sections above, have not created a blq sumdoc example yet though.

If your |data_file| contains some observations which are recorded as |blq|, |ie| they are below the |llq| of the assay used to measure drug concentrations. Then to include these data points in your analysis you can use a |rectnorm_dist|, see below:-

.. code-block:: pyml
    
    PREDICTIONS: 
        p[DV_CENTRAL] = s[CENTRAL]/m[V1]
        var = m[ANOISE]**2 + m[PNOISE]**2 * p[DV_CENTRAL]**2
        c[DV_CENTRAL] ~ rectnorm(p[DV_CENTRAL], var, LLQ=2.0)

This formulation will model observations |cdvcen| below |llq| as the likelihood of being in the range [-inf,LLQ] and observations greater than |llq| using a standard |norm_dist| likelihood. See |rectnorm_dist| for more information on this topic.


.. _rules_predictions:
    
Rules for PREDICTIONS section
=======================================

Like all :term:`verbatim` sections, the |predictions| section of the configuration file accepts free form |python| :term:`pseudocode`, but there are some rules regarding which variables are allowed in a |predictions| section as follows:- 

* **Only** |px| and local variables can be defined on the |lhs| using '=' 
* **Only** |cx| can be defined on the |lhs| using '~'
* |mx| and |sx| are only allowed on the |rhs| of expressions
* |cx| must be in the |data_file| or defined in the |preprocess| section in a :ref:`fit_script` 
* |cx| must be defined within the |effects| in a :ref:`gen_script` or |gen_effects| in a :ref:`tut_script`.
* |mx| must be defined in the |model_params| section
* |sx| must be defined in the |derivatives| section

You can |not| use |fx|, |rx| or |tx| |etc| variables at all in this section. 

Like all :term:`verbatim` sections it is possible to introduce syntax errors by writing malformed |python|. Such errors will be reported when |popy| attempts to compile or run the |predictions| function as a temporary .py file.
    
    
.. comment
    This section defines the final model predictions to be output from the compartment model system.

    This section defines the predictions from the model.

    First, define what the predictive compartment is eg::

        predlabel[DV_CENTRAL] = 'Drug conc'

    Then define how the prediction is calculated. Here, the amount in the central compartment scaled by the volume of the compartment::

        pred[DV_CENTRAL] = s[CENTRAL]/m[V]
        
    Define the error model eg::

        var = (pred[DV_CENTRAL]*m[PNOISE])**2 + m[ANOISE]**2
        
    Finally define the concentration of the central compartment eg::
        
        c[DV_CENTRAL] ~ norm(pred[DV_CENTRAL], var)

