KarrLab/wc_lang

View on GitHub
wc_lang/transform/set_finite_dfba_flux_bounds.py

Summary

Maintainability
C
1 day
Test Coverage
A
100%
""" Clip the flux bounds for the reactions in dFBA submodels

:Author: Arthur Goldberg <Arthur.Goldberg@mssm.edu>
:Author: Jonathan Karr <jonrkarr@gmail.com>
:Date: 2018-11-28
:Copyright: 2017-2018, Karr Lab
:License: MIT
"""

from .core import Transform
from math import isnan
from wc_onto import onto
from wc_utils.util.ontology import are_terms_equivalent
from wc_utils.util.units import unit_registry
import wc_lang.config.core
import wc_lang.core


class SetFiniteDfbaFluxBoundsTransform(Transform):
    """ Clip the flux bounds for the reactions in dFBA submodels to the default flux range

    Bounds need to be clipped because some linear programming solvers require
    finite minimum and maximum flux bounds.
    The default bounds are provided in the wc_lang configuration.

    Specifically, the default minimum and maximum flux bounds are applied as follows:

        * reversible reactions:

          * flux_min = max(flux_min, flux_min_bound_reversible)
          * flux_max = min(flux_max, flux_max_bound)

        * irreversible reactions:

          * flux_min = max(flux_min, flux_min_bound_irreversible)
          * flux_max = min(flux_max, flux_max_bound)
    """

    class Meta(object):
        id = 'SetFiniteDfbaFluxBoundsTransform'
        label = ('Clip the flux bounds for the reactions in dFBA submodels'
                 ' to the default flux range')

    def run(self, model):
        """ Transform model

        Args:
            model (:obj:`Model`): model

        Returns:
            :obj:`Model`: same model, but transformed
        """
        config = wc_lang.config.core.get_config()['wc_lang']
        flux_min_bound_reversible = config['dfba']['flux_bounds']['min_reversible']
        flux_min_bound_irreversible = config['dfba']['flux_bounds']['min_irreversible']
        flux_max_bound = config['dfba']['flux_bounds']['max']

        for submodel in model.submodels:
            if are_terms_equivalent(submodel.framework, onto['WC:dynamic_flux_balance_analysis']):
                for rxn in submodel.reactions:
                    if rxn.reversible:
                        flux_min = flux_min_bound_reversible
                    else:
                        flux_min = flux_min_bound_irreversible
                    flux_max = flux_max_bound

                    if rxn.flux_bounds is None:
                        rxn.flux_bounds = wc_lang.core.FluxBounds()

                    if rxn.flux_bounds.min is None or isnan(rxn.flux_bounds.min):
                        rxn.flux_bounds.min = flux_min
                    else:
                        rxn.flux_bounds.min = max(rxn.flux_bounds.min, flux_min)

                    if rxn.flux_bounds.max is None or isnan(rxn.flux_bounds.max):
                        rxn.flux_bounds.max = flux_max
                    else:
                        rxn.flux_bounds.max = min(rxn.flux_bounds.max, flux_max)

                    rxn.flux_bounds.units = unit_registry.parse_units('M s^-1')
        return model