Development

The following documentation is intended for people that want to use cameo to develop new methods and/or that would like to contribute to its development.

cameo vs. cobrapy

While cameo uses and extends the same data structures as cobrapy, there exist a few notable differences. The following provides a comprehensive side-by-side comparison of cobrapy and cameo aiming to make it easier for users who are already familiar with cobrapy to get started with cameo.

Solver interface

Cameo deviates from cobrapy in the way optimization problems are solved by using a separate solver interface provided by the optlang package (see optlang_interface), which has the following benefits:

  • Methods that require solving a model multiple times will run faster since previously found solutions will be automatically re-used by the solvers to warm-start the next optimization.
  • Implementation of novel or published methods becomes easier since optlang (based on the popular symbolic math library sympy) facilitates the formulation of constraints and objectives using equations (similar to GAMS) instead of matrix formalism.
  • Adding additional constraints (even non-metabolic) is straight forwards and eliminates the problem in cobrapy of having to define dummy metabolites etc.

Importing a model

cobrapy (load a model in SBML format):

from cobra.io import read_sbml_model
model = read_sbml_model('path/to/model.xml')

cameo (load models from different formats):

from cameo import load_model
# read SBML model
model = load_model('path/to/model.xml')
# ... or read a pickled model
model = load_model('path/to/model.pickle')
# ... or just import a model by ID from http://darwin.di.uminho.pt/models
iAF1260 = load_model('iAF1260')

Furthermore, cameo provides direct access to a number of other models through cameo.models.

from cameo import models
models.e_coli_core.solve().f

Solving models

When models are optimized with cobrapy, model.optimize() returns the status code of the solver and leaves it to the user to determine if the problem was successfully solved.

solution = model.optimize()
if solution.status == 'optimal':
    # proceed

In order to avoid users accidentally working with non-optimal solutions, cameo will raise an exception instead.

try:
    solution = model.solve()
except cameo.exceptions.SolverError:
    print "A non-optimal solution was returned by the solver"
else:
    # proceed

It is important to note that cameo models still provide the optimize method to maintain backwards compatibility with cobrapy but we discourage its use.

optlang copy_vs_time_machine

The optlang solver interface

For efficiency reasons, cameo does not utilize cobrapy’s interfaces to LP and MILP solvers. Instead it utilizes optlang, which is a generic interface to a number of free and commercial optimization solvers. It is based on the popular symbolic math library sympy and thus enables the formulation of optimization problems using equations instead of matrix formalism.

Changing the solver

The LP/MILP solver can be changed in the following way.

model.solver = 'cplex'

Currently cplex, glpk, and gurobi are supported.

Manipulating the solver object

The solver object in cameo is always accessible through solver. For example, one can inspect the optimization problem in CPLEX LP format by printing the solver object.

print(model.solver)

Having access to the optlang solver object provides for a very convenient way for manipulating the optimization problem. For example, it is straightforward to add additional constraints, for example, a flux ratio constraint.

reaction1 = model.reactions.PGI
reaction2 = model.reactions.G6PDH2r
ratio = 5
flux_ratio_constraint = model.solver.interface.Constraint(
    reaction1.flux_expression - ratio * reaction2.flux_expression,
    lb=0,
    ub=0)
model.solver.add(flux_ratio_constraint)

This will constrain the flux split between glycolysis and pentose phosphate patwhay to 20. model.solver.interface hereby provides access to

Good coding practices

Cameo developers and users are encouraged to avoid making copies of models and other data structures. Instead, we put
forward a design pattern based on transactions.
from cameo.util import TimeMachine
with TimeMachine() as tm:
    model.reactions.knock_out(time_machine=tm)