Introduction to LAPM

LAPM is a python package for the analysis of linear autonomous pool (compartmental) models. It can be used to obtain a large set of different system-level diagnostics of compartmental models. This can be done either in symbolic or numeric form. In this notebook, we will introduce the basics of the package.

We assume that you have already installed the package following the instructions provided in the download page. After the package is installed, you can import it following the commands:


In [1]:
from sympy import *
from LAPM import *
from LAPM.linear_autonomous_pool_model import LinearAutonomousPoolModel

In the second line above, we imported also the linear_autonomous_pool_model module which contains most of the functions required for the examples in this notebook. We will create now a simple two-compartment model with the following syntax


In [2]:
lambda_1, lambda_2, alpha, u_1, u_2 = symbols('lambda_1 lambda_2 alpha u_1 u_2', positive=True)
A = Matrix([[     -lambda_1,        0],
            [alpha*lambda_1, -lambda_2]])
u = Matrix(2, 1, [u_1, u_2])

Notice that we created a symblic version of the model with no assignment of values to the parameters. This is useful because we can make computations in symbolic form only, or we can assign parameter values later. With the compartmental matrix and the input vector created above, we can now create a compartmental model as


In [3]:
M=LinearAutonomousPoolModel(u, A)

Symbolic computations

We can use now the set of functions available in LAPM with this model. For example, we can compute the mean system age as


In [4]:
M.A_expected_value


Out[4]:
(alpha*u_1/lambda_2 + u_2/lambda_2)/(lambda_2*(alpha*u_1/lambda_2 + u_2/lambda_2 + u_1/lambda_1)) + u_1*(alpha/lambda_2 + 1/lambda_1)/(lambda_1*(alpha*u_1/lambda_2 + u_2/lambda_2 + u_1/lambda_1))

For an output easier to read on the screen


In [5]:
pprint(M.A_expected_value)


     α⋅u₁   u₂               ⎛α    1 ⎞   
     ──── + ──            u₁⋅⎜── + ──⎟   
      λ₂    λ₂               ⎝λ₂   λ₁⎠   
─────────────────── + ───────────────────
   ⎛α⋅u₁   u₂   u₁⎞      ⎛α⋅u₁   u₂   u₁⎞
λ₂⋅⎜──── + ── + ──⎟   λ₁⋅⎜──── + ── + ──⎟
   ⎝ λ₂    λ₂   λ₁⎠      ⎝ λ₂    λ₂   λ₁⎠

Latex output can be obtained as


In [6]:
print(latex(M.A_expected_value))


\frac{\frac{\alpha u_{1}}{\lambda_{2}} + \frac{u_{2}}{\lambda_{2}}}{\lambda_{2} \left(\frac{\alpha u_{1}}{\lambda_{2}} + \frac{u_{2}}{\lambda_{2}} + \frac{u_{1}}{\lambda_{1}}\right)} + \frac{u_{1} \left(\frac{\alpha}{\lambda_{2}} + \frac{1}{\lambda_{1}}\right)}{\lambda_{1} \left(\frac{\alpha u_{1}}{\lambda_{2}} + \frac{u_{2}}{\lambda_{2}} + \frac{u_{1}}{\lambda_{1}}\right)}

You can copy and paste this Latex ouput to a markdown or latex document $$ \frac{\frac{\alpha u_{1}}{\lambda_{2}} + \frac{u_{2}}{\lambda_{2}}}{\lambda_{2} \left(\frac{\alpha u_{1}}{\lambda_{2}} + \frac{u_{2}}{\lambda_{2}} + \frac{u_{1}}{\lambda_{1}}\right)} + \frac{u_{1} \left(\frac{\alpha}{\lambda_{2}} + \frac{1}{\lambda_{1}}\right)}{\lambda_{1} \left(\frac{\alpha u_{1}}{\lambda_{2}} + \frac{u_{2}}{\lambda_{2}} + \frac{u_{1}}{\lambda_{1}}\right)} $$

Numerical calculations

In most cases, we actually want to perform numerical computations of system-level diagnostics. In this case, we need first to assign values to the elements of the compartmental system. For instance, we can use the subs function to assign numerical values to existing matrices and vectors:


In [7]:
u1=u.subs({u_1: 2, u_2: 4})
A1=A.subs({lambda_1: 0.8, lambda_2: 0.01, alpha: 0.13})

We take now these numerical arguments and create a new compartmental system and compute the mean system age as above


In [8]:
M1=LinearAutonomousPoolModel(u1, A1)
M1.A_expected_value


Out[8]:
99.4997082847141

Other useful system diagnostics are:


In [9]:
M1.A_standard_deviation # standard deviation of the system age distribution


Out[9]:
99.99249461290282

In [10]:
M1.A_quantile(0.5) # Median (50% quantile) of the system age distribution


Out[10]:
68.80680584095865

In [11]:
M1.T_expected_value #Mean transit time


Out[11]:
71.4166666666667

In [12]:
M1.T_standard_deviation # standard deviation of the transit time distribution


Out[12]:
95.45435936730298

In [13]:
M1.T_quantile(0.5) # Median (50% quantile) of the transit time distribution


Out[13]:
35.14291412333978

In [14]:
M1.a_expected_value # Mean age vector of individual pools


Out[14]:
Matrix([
[            1.25],
[100.076291079812]])

In [15]:
M1.a_quantile(0.5) # Median age of individual pools


Out[15]:
array([ 0.86643398, 69.39194502])

In [16]:
M1.T_laplace


Out[16]:
0.232/(s + 0.8) + 0.00666666666666667/(s + 0.01) + 0.000346666666666667/((s + 0.01)*(s + 0.8))

In [17]:
M1.A_laplace


Out[17]:
0.00406067677946324/(s + 0.8) + 0.0099416569428238/(s + 0.01) + 6.06767794632439e-6/((s + 0.01)*(s + 0.8))

In [68]:
M1.r_compartments # release flux of individual compartments


Out[68]:
Matrix([
[1.74],
[4.26]])

In [69]:
M1.r_total # Total release flux


Out[69]:
6.00000000000000

In [74]:
M1.entropy_per_jump


Out[74]:
-0.32626427406199*log(2) + 0.489396411092985*log(3) + 2.21020273307626

In [55]:
M1.entropy_per_cycle


Out[55]:
-0.666666666666667*log(2) + 1.0*log(3) + 2.95715004792764

In [56]:
M1.entropy_rate


Out[56]:
-0.0865384615384615*log(2) + 0.129807692307692*log(3) + 0.383860823529068

In [ ]: