Source code for cameo.flux_analysis.util

# -*- coding: utf-8 -*-
# Copyright 2014 Novo Nordisk Foundation Center for Biosustainability, DTU.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.

from cobra.exceptions import OptimizationError

import sympy
from sympy import Add, Mul
from cobra.flux_analysis.parsimonious import add_pfba

import logging

__all__ = ['remove_infeasible_cycles', 'fix_pfba_as_constraint']

FloatOne = sympy.Float(1)
logger = logging.getLogger(__name__)

[docs]def remove_infeasible_cycles(model, fluxes, fix=()): """Remove thermodynamically infeasible cycles from a flux distribution. Parameters --------- model : cobra.Model The model that generated the flux distribution. fluxes : dict The flux distribution containing infeasible loops. Returns ------- dict A cycle free flux distribution. References ---------- .. [1] A. A. Desouki, F. Jarre, G. Gelius-Dietrich, and M. J. Lercher, “CycleFreeFlux: efficient removal of thermodynamically infeasible loops from flux distributions.” """ with model: # make sure the original object is restored exchange_reactions = model.boundary exchange_ids = [ for exchange in exchange_reactions] internal_reactions = [reaction for reaction in model.reactions if not in exchange_ids] for exchange in exchange_reactions: exchange_flux = fluxes[] exchange.bounds = (exchange_flux, exchange_flux) cycle_free_objective_list = [] for internal_reaction in internal_reactions: internal_flux = fluxes[] if internal_flux >= 0: cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.forward_variable))) internal_reaction.bounds = (0, internal_flux) else: # internal_flux < 0: cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.reverse_variable))) internal_reaction.bounds = (internal_flux, 0) cycle_free_objective = model.solver.interface.Objective( Add._from_args(cycle_free_objective_list), direction="min", sloppy=True ) model.objective = cycle_free_objective for reaction_id in fix: reaction_to_fix = model.reactions.get_by_id(reaction_id) reaction_to_fix.bounds = (fluxes[reaction_id], fluxes[reaction_id]) try: solution = model.optimize(raise_error=True) except OptimizationError as e: logger.warning("Couldn't remove cycles from reference flux distribution.") raise e result = solution.fluxes return result
[docs]def fix_pfba_as_constraint(model, multiplier=1, fraction_of_optimum=1): """Fix the pFBA optimum as a constraint Useful when setting other objectives, like the maximum flux through given reaction may be more realistic if all other fluxes are not allowed to reach their full upper bounds, but collectively constrained to max sum. Parameters ---------- model : cobra.Model The model to add the pfba constraint to multiplier : float The multiplier of the minimal sum of all reaction fluxes to use as the constraint. fraction_of_optimum : float The fraction of the objective value's optimum to use as constraint when getting the pFBA objective's minimum """ fix_constraint_name = '_fixed_pfba_constraint' if fix_constraint_name in model.solver.constraints: model.solver.remove(fix_constraint_name) with model: add_pfba(model, fraction_of_optimum=fraction_of_optimum) pfba_objective_value = model.slim_optimize(error_value=None) * multiplier constraint = model.solver.interface.Constraint(model.objective.expression, name=fix_constraint_name, ub=pfba_objective_value) model.add_cons_vars(constraint, sloppy=True)