.. _variable_types:
        
Variable Types
###################

:numref:`table_variable_types` shows the different type of script variables that are available in the :term:`verbatim` sections of |popy| scripts:-

.. _table_variable_types:

.. list-table:: |popy| Variable Types
    :header-rows: 1
    
    * - Type
      - Description
      - Defined
      - Used
      
    * - |cx| (fit script)
      - |covariates| (fit)
      - |data_file|/|preprocess|
      - main sections
      
    * - |cx| (gen script)
      - |covariates| (gen)
      - |effects|
      - main sections
    
    * - |cx| 
      - |obss| 
      - |predictions| (fit)
      - |predictions| (gen)
      
    * - |fx|
      - |fes|
      - |effects|
      - |model_params|
      
    * - |rx|
      - |res|
      - |effects|
      - |model_params|
     
    * - |mx|
      - Model parameters
      - |model_params|
      - main sections
      
    * - |wx|
      - Workspace Variables
      - |model_params|
      - |model_params|
      
    * - |xnewind|
      - First row for individual
      - |na|
      - |model_params|

    * - |dx|
      - Derivatives |wrt| time
      - |derivatives|
      - |na|
            
    * - |sx|
      - States
      - |derivatives|/|states|
      - |derivatives|/|predictions|
      
    * - |xtime|
      - Continuous time 
      - |na|
      - |derivatives|
      
    * - |px|
      - Predictions
      - |predictions|
      - |predictions|
    
      
In :numref:`table_variable_types`, the 'Defined' column shows where a variable of particular type is first declared, typically on the |lhs| of an '=' or '~' operator. The 'Used' column shows where a variable may be used, typically on the |rhs| of an '=' or '~' operator.

Note the entry 'main sections' in table :numref:`table_variable_types` above means the following sections - |model_params|/|states|/|derivatives|/|predictions|.

..  comment

    It might be a good idea to make a section for each variable type and link from the table?
    probably not 100% required at mo
    
Parameterized Variables
==========================

There are circumstances where many compartments in the model follow the same basic structure. When using delay compartments, for example, there is typically only a flow in from the previous compartment and a flow out to the next one:

.. code-block:: pyml

    DERIVATIVES: |
        d[DEPOT]   = @bolus{amt:c[AMT]} - m[K]*s[DEPOT]
        d[DELAY1]  = m[K]*s[DEPOT]      - m[K]*s[DELAY1]
        d[DELAY2]  = m[K]*s[DELAY1]     - m[K]*s[DELAY2]
        d[DELAY3]  = m[K]*s[DELAY2]     - m[K]*s[DELAY3]
        d[DELAY4]  = m[K]*s[DELAY3]     - m[K]*s[DELAY4]
        d[CENTRAL] = m[K]*s[DELAY4]     - m[KE]*s[CENTRAL]
        
Expressing these models can be time-consuming and error-prone, so |popy| provides a means to define multiple compartments with parameters in the definitions. 

To define a sequence of numbered compartments (DELAY1, DELAY2, DELAY3, and so on) use braces on the left hand side to define the index variable (e.g., "i") and the range of numbers it should take on (e.g., "1..4" to denote 1, 2, 3 and 4). This line will be replicated for every value of the index, i, in the specified range, and the braces (along with their contents) will be replaced with the corresponding value of i.

On the right hand side, you may use expressions with simple functions of the index variable (also within braces) to refer to a parameterised compartment. When i=2, for example, c[DELAY{i-1}] refers to c[DELAY1] and so on. The model above then becomes:

.. code-block:: pyml

    DERIVATIVES: |
        d[DEPOT]         = @bolus{amt:c[AMT]} - m[K]*s[DEPOT]
        d[DELAY1]        = m[K]*s[DEPOT]      - m[K]*s[DELAY1]
        
        # this line...
        d[DELAY{i:2..4}] = m[K]*s[DELAY{i-1}] - m[K]*s[DELAY{i}]
        
        # ...expands to, and is therefore equivalent to, these lines:
        # d[DELAY2]      = m[K]*s[DELAY1]     - m[K]*s[DELAY2]  # i = 2
        # d[DELAY3]      = m[K]*s[DELAY2]     - m[K]*s[DELAY3]  # i = 3
        # d[DELAY4]      = m[K]*s[DELAY3]     - m[K]*s[DELAY4]  # i = 4
        
        d[CENTRAL]       = m[K]*s[DELAY4]     - m[KE]*s[CENTRAL]
        
It is also possible to use parameterized variables in the same way within a sum() function for the sake of simplicity:

.. code-block:: pyml

    PREDICTIONS: |
        p[TOTAL_CONC] = sum(s[CMT{i:1..4}])
        ...
