Working with arrays of Compartments

COPASI allows working with arrays of compartments, that is taking a model that is set up, and multiplying it either in a linear chain, or in an rectangular array. This example shows how to do that. We start with the usual imports:

[1]:
import sys
if not '../..' in sys.path:  # make sure basico can be found
    sys.path.append('../..')
from basico import *      # then import
%matplotlib inline

now we import the brusselator example model

[2]:
dm = load_example('brusselator')

and we see, that we can run time courses just as usual:

[3]:
data = run_time_course()
data.plot();
../_images/notebooks_Arrays_of_Compartments_5_0.png

i added basic functionality, for adding events to the model. The parameters are:

  • name

  • trigger expression

  • array of arrays for assignments, with the inner array containing a target, and an expression what to assign.

for example the following would add an event e2 that triggers at time 10, and assigns 10 to X

[4]:
add_event('e0', 'Time > 30', [['X', '10']]);

to display what events we have use get_events()

[5]:
get_events()
[5]:
trigger delay assignments key
name
e0 Time > 30 [{'target': '[X]', 'expression': '10'}] Event_0

so if we run the time course again, we do see that at time 30, we now have the event triggered:

[6]:
run_time_course().plot();
../_images/notebooks_Arrays_of_Compartments_11_0.png

Linear arrays of compartments

now lets run this model in a linear chain of 15 cells, allowing the species X and Y to diffuse linearly between them, with diffusion coefficients 0.16 and 0.08 respectively. We also remove the existing compartment afterwards, as it will not be part of the linear chain:

[7]:
create_linear_array(15, ['X', 'Y'], [0.16, 0.8], delete_template=True)

now we have many more species, compartments, and reactions, all parameterized exactly as the template model was

[8]:
print(overview())
get_species().head()
Name:           The Brusselator
# Compartments: 15
# Species:      90# Parameters:   2# Reactions:    88# Events:       1
[8]:
compartment type unit initial_concentration initial_particle_number initial_expression expression concentration particle_number rate particle_number_rate key
name
X compartment[1] reactions mmol/ml 2.999996 1.806640e+21 NaN NaN 0.0 0.0 Metabolite_16
X compartment[3] reactions mmol/ml 2.999996 1.806640e+21 NaN NaN 0.0 0.0 Metabolite_28
X compartment[5] reactions mmol/ml 2.999996 1.806640e+21 NaN NaN 0.0 0.0 Metabolite_40
X compartment[7] reactions mmol/ml 2.999996 1.806640e+21 NaN NaN 0.0 0.0 Metabolite_52
X compartment[9] reactions mmol/ml 2.999996 1.806640e+21 NaN NaN 0.0 0.0 Metabolite_64

lets simulate again:

[9]:
data = run_time_course()
data.plot();
../_images/notebooks_Arrays_of_Compartments_17_0.png

Seeing all these lines plotted over each other might not be too helpful, so we can also plot this as a clor mesh, with the time on the x axis, and the individal created compartments along the y axis.

[10]:
plot_linear_time_course(data, 'compartment');
../_images/notebooks_Arrays_of_Compartments_19_0.png
../_images/notebooks_Arrays_of_Compartments_19_1.png

Creating 2D array of compartments

the same can be done by createing a rectangular array of compartments. Note that this results in quickly getting large amounts of model variables, so it might prove prohibitive to be used in numbers. So i’ll start over, loading the model again (as i don’t want the linear chain anymore)

[11]:
dm = load_example('brusselator')
create_rectangular_array(15, 15, ['X', 'Y'], [0.16, 0.8], delete_template=True)
print(overview())
Name:           The Brusselator
# Compartments: 225
# Species:      1350# Parameters:   2# Reactions:    1740

Lots of variables indeed. So simulation will take a bit longer. But before we come to that, i would like to change the concentration of X at time 10 of the simulation, just so that we don’t just use uniform values (that would be boring to look at. So i add the events as before:

[12]:
add_event('change_x', 'Time > 10', [['X{compartment[2,2]}', '10'],
                                    ['X{compartment[2,3]}', '10'],
                                    ['X{compartment[3,2]}', '10'],
                                    ['X{compartment[3,3]}', '10']
                                   ])
[12]:
<CEvent "change_x">
[13]:
data = run_time_course(duration=100, start_time=0)

plotting all times of the time course might not be too interesting, so instead i select plots only at specific times. I also override the min / max scaling of the plots, to the range between 0 and 10, if those are not given the data will be scaled to each min / max value.

[14]:
plot_rectangular_time_course(data, times=[10.5, 30 , 60, 90], min_range=0, max_range=10);
../_images/notebooks_Arrays_of_Compartments_26_0.png
../_images/notebooks_Arrays_of_Compartments_26_1.png
../_images/notebooks_Arrays_of_Compartments_26_2.png
../_images/notebooks_Arrays_of_Compartments_26_3.png
../_images/notebooks_Arrays_of_Compartments_26_4.png
../_images/notebooks_Arrays_of_Compartments_26_5.png
../_images/notebooks_Arrays_of_Compartments_26_6.png
../_images/notebooks_Arrays_of_Compartments_26_7.png

To display it as animation we’ll need an extra import, and you’ll need to have ffmpeg installed

[15]:
from IPython.display import HTML
HTML(animate_rectangular_time_course(data, metab='Y', min_range=0, max_range=10).to_html5_video())
[15]:
../_images/notebooks_Arrays_of_Compartments_28_1.png