def update_costs(self):
        """Update the coefficients for the indicator variables in the objective.

        Done incrementally so that second time the function is called,
        active indicators in the current solutions gets higher cost than the
        unused indicators.
        """
        for var in self.indicators:
            if var not in self.costs:
                self.costs[var] = var.cost
            else:
                if var._get_primal() > self.integer_threshold:
                    self.costs[var] += var.cost
        self.model.objective.set_linear_coefficients(self.costs)

def update_costs ( self ) : for var in self . indicators : if var not in self . costs : self . costs [ var ] = var . cost else : if var . _get_primal ( ) > self . integer_threshold : self . costs [ var ] += var . cost self . model . objective . set_linear_coefficients ( self . costs )

Update the coefficients for the indicator variables in the objective .


def add_switches_and_objective(self):
        """ Update gapfilling model with switches and the indicator objective.
        """
        constraints = list()
        big_m = max(max(abs(b) for b in r.bounds)
                    for r in self.model.reactions)
        prob = self.model.problem
        for rxn in self.model.reactions:
            if not hasattr(rxn, 'gapfilling_type'):
                continue
            indicator = prob.Variable(
                name='indicator_{}'.format(rxn.id), lb=0, ub=1, type='binary')
            if rxn.id in self.penalties:
                indicator.cost = self.penalties[rxn.id]
            else:
                indicator.cost = self.penalties[rxn.gapfilling_type]
            indicator.rxn_id = rxn.id
            self.indicators.append(indicator)

            # if z = 1 v_i is allowed non-zero
            # v_i - Mz <= 0   and   v_i + Mz >= 0
            constraint_lb = prob.Constraint(
                rxn.flux_expression - big_m * indicator, ub=0,
                name='constraint_lb_{}'.format(rxn.id), sloppy=True)
            constraint_ub = prob.Constraint(
                rxn.flux_expression + big_m * indicator, lb=0,
                name='constraint_ub_{}'.format(rxn.id), sloppy=True)

            constraints.extend([constraint_lb, constraint_ub])

        self.model.add_cons_vars(self.indicators)
        self.model.add_cons_vars(constraints, sloppy=True)
        self.model.objective = prob.Objective(
            Zero, direction='min', sloppy=True)
        self.model.objective.set_linear_coefficients({
            i: 1 for i in self.indicators})
        self.update_costs()

def
add_switches_and_objective
(
self
)
:
constraints
=
list
(
)
big_m
=
max
(
max
(
abs
(
b
)
for
b
in
r
.
bounds
)
for
r
in
self
.
model
.
reactions
)
prob
=
self
.
model
.
problem
for
rxn
in
self
.
model
.
reactions
:
if
not
hasattr
(
rxn
,
'gapfilling_type'
)
:
continue
indicator
=
prob
.
Variable
(
name
=
'indicator_{}'
.
format
(
rxn
.
id
)
,
lb
=
0
,
ub
=
1
,
type
=
'binary'
)
if
rxn
.
id
in
self
.
penalties
:
indicator
.
cost
=
self
.
penalties
[
rxn
.
id
]
else
:
indicator
.
cost
=
self
.
penalties
[
rxn
.
gapfilling_type
]
indicator
.
rxn_id
=
rxn
.
id
self
.
indicators
.
append
(
indicator
)
# if z = 1 v_i is allowed non-zero
# v_i - Mz <= 0   and   v_i + Mz >= 0
constraint_lb
=
prob
.
Constraint
(
rxn
.
flux_expression
big_m
*
indicator
,
ub
=
0
,
name
=
'constraint_lb_{}'
.
format
(
rxn
.
id
)
,
sloppy
=
True
)
constraint_ub
=
prob
.
Constraint
(
rxn
.
flux_expression
+
big_m
*
indicator
,
lb
=
0
,
name
=
'constraint_ub_{}'
.
format
(
rxn
.
id
)
,
sloppy
=
True
)
constraints
.
extend
(
[
constraint_lb
,
constraint_ub
]
)
self
.
model
.
add_cons_vars
(
self
.
indicators
)
self
.
model
.
add_cons_vars
(
constraints
,
sloppy
=
True
)
self
.
model
.
objective
=
prob
.
Objective
(
Zero
,
direction
=
'min'
,
sloppy
=
True
)
self
.
model
.
objective
.
set_linear_coefficients
(
{
i
:
1
for
i
in
self
.
indicators
}
)
self
.
update_costs
(
)

Update gapfilling model with switches and the indicator objective .


def fill(self, iterations=1):
        """Perform the gapfilling by iteratively solving the model, updating
        the costs and recording the used reactions.

        Parameters
        ----------
        iterations : int
            The number of rounds of gapfilling to perform. For every
            iteration, the penalty for every used reaction increases
            linearly. This way, the algorithm is encouraged to search for
            alternative solutions which may include previously used
            reactions. I.e., with enough iterations pathways including 10
            steps will eventually be reported even if the shortest pathway
            is a single reaction.

        Returns
        -------
        iterable
            A list of lists where each element is a list reactions that were
            used to gapfill the model.

        Raises
        ------
        RuntimeError
            If the model fails to be validated (i.e. the original model with
            the proposed reactions added, still cannot get the required flux
            through the objective).
        """
        used_reactions = list()
        for i in range(iterations):
            self.model.slim_optimize(error_value=None,
                                     message='gapfilling optimization failed')
            solution = [self.model.reactions.get_by_id(ind.rxn_id)
                        for ind in self.indicators if
                        ind._get_primal() > self.integer_threshold]
            if not self.validate(solution):
                raise RuntimeError('failed to validate gapfilled model, '
                                   'try lowering the integer_threshold')
            used_reactions.append(solution)
            self.update_costs()
        return used_reactions

def
fill
(
self
,
iterations
=
1
)
:
used_reactions
=
list
(
)
for
i
in
range
(
iterations
)
:
self
.
model
.
slim_optimize
(
error_value
=
,
message
=
'gapfilling optimization failed'
)
solution
=
[
self
.
model
.
reactions
.
get_by_id
(
ind
.
rxn_id
)
for
ind
in
self
.
indicators
if
ind
.
_get_primal
(
)
>
self
.
integer_threshold
]
if
not
self
.
validate
(
solution
)
:
raise
RuntimeError
(
'failed to validate gapfilled model, '
'try lowering the integer_threshold'
)
used_reactions
.
append
(
solution
)
self
.
update_costs
(
)
return
used_reactions

Perform the gapfilling by iteratively solving the model updating the costs and recording the used reactions .


def find_external_compartment(model):
    """Find the external compartment in the model.

    Uses a simple heuristic where the external compartment should be the one
    with the most exchange reactions.

    Arguments
    ---------
    model : cobra.Model
        A cobra model.

    Returns
    -------
    str
        The putative external compartment.
    """
    if model.boundary:
        counts = pd.Series(tuple(r.compartments)[0] for r in model.boundary)
        most = counts.value_counts()
        most = most.index[most == most.max()].to_series()
    else:
        most = None
    like_external = compartment_shortlist["e"] + ["e"]
    matches = pd.Series([co in like_external for co in model.compartments],
                        index=model.compartments)

    if matches.sum() == 1:
        compartment = matches.index[matches][0]
        LOGGER.info("Compartment `%s` sounds like an external compartment. "
                    "Using this one without counting boundary reactions" %
                    compartment)
        return compartment
    elif most is not None and matches.sum() > 1 and matches[most].sum() == 1:
        compartment = most[matches[most]][0]
        LOGGER.warning("There are several compartments that look like an "
                       "external compartment but `%s` has the most boundary "
                       "reactions, so using that as the external "
                       "compartment." % compartment)
        return compartment
    elif matches.sum() > 1:
        raise RuntimeError("There are several compartments (%s) that look "
                           "like external compartments but we can't tell "
                           "which one to use. Consider renaming your "
                           "compartments please.")

    if most is not None:
        return most[0]
        LOGGER.warning("Could not identify an external compartment by name and"
                       " choosing one with the most boundary reactions. That "
                       "might be complete nonsense or change suddenly. "
                       "Consider renaming your compartments using "
                       "`Model.compartments` to fix this.")
    # No info in the model, so give up
    raise RuntimeError("The heuristic for discovering an external compartment "
                       "relies on names and boundary reactions. Yet, there "
                       "are neither compartments with recognized names nor "
                       "boundary reactions in the model.")

Find the external compartment in the model .


def is_boundary_type(reaction, boundary_type, external_compartment):
    """Check whether a reaction is an exchange reaction.

    Arguments
    ---------
    reaction : cobra.Reaction
        The reaction to check.
    boundary_type : str
        What boundary type to check for. Must be one of
        "exchange", "demand", or "sink".
    external_compartment : str
        The id for the external compartment.

    Returns
    -------
    boolean
        Whether the reaction looks like the requested type. Might be based
        on a heuristic.
    """
    # Check if the reaction has an annotation. Annotations dominate everything.
    sbo_term = reaction.annotation.get("sbo", "")
    if isinstance(sbo_term, list):
        sbo_term = sbo_term[0]
    sbo_term = sbo_term.upper()

    if sbo_term == sbo_terms[boundary_type]:
        return True
    if sbo_term in [sbo_terms[k] for k in sbo_terms if k != boundary_type]:
        return False

    # Check if the reaction is in the correct compartment (exterior or inside)
    correct_compartment = external_compartment in reaction.compartments
    if boundary_type != "exchange":
        correct_compartment = not correct_compartment

    # Check if the reaction has the correct reversibility
    rev_type = True
    if boundary_type == "demand":
        rev_type = not reaction.reversibility
    elif boundary_type == "sink":
        rev_type = reaction.reversibility

    return (reaction.boundary and not
            any(ex in reaction.id for ex in excludes[boundary_type]) and
            correct_compartment and rev_type)

Check whether a reaction is an exchange reaction .


def find_boundary_types(model, boundary_type, external_compartment=None):
    """Find specific boundary reactions.

    Arguments
    ---------
    model : cobra.Model
        A cobra model.
    boundary_type : str
        What boundary type to check for. Must be one of
        "exchange", "demand", or "sink".
    external_compartment : str or None
        The id for the external compartment. If None it will be detected
        automatically.

    Returns
    -------
    list of cobra.reaction
        A list of likely boundary reactions of a user defined type.
    """
    if not model.boundary:
        LOGGER.warning("There are no boundary reactions in this model. "
                       "Therefore specific types of boundary reactions such "
                       "as 'exchanges', 'demands' or 'sinks' cannot be "
                       "identified.")
        return []
    if external_compartment is None:
        external_compartment = find_external_compartment(model)
    return model.reactions.query(
        lambda r: is_boundary_type(r, boundary_type, external_compartment))


def normalize_cutoff(model, zero_cutoff=None):
    """Return a valid zero cutoff value."""
    if zero_cutoff is None:
        return model.tolerance
    else:
        if zero_cutoff < model.tolerance:
            raise ValueError(
                "The chosen zero cutoff cannot be less than the model's "
                "tolerance value."
            )
        else:
            return zero_cutoff


def _sample_chain(args):
    """Sample a single chain for OptGPSampler.

    center and n_samples are updated locally and forgotten afterwards.

    """

    n, idx = args       # has to be this way to work in Python 2.7
    center = sampler.center
    np.random.seed((sampler._seed + idx) % np.iinfo(np.int32).max)
    pi = np.random.randint(sampler.n_warmup)

    prev = sampler.warmup[pi, ]
    prev = step(sampler, center, prev - center, 0.95)

    n_samples = max(sampler.n_samples, 1)
    samples = np.zeros((n, center.shape[0]))

    for i in range(1, sampler.thinning * n + 1):
        pi = np.random.randint(sampler.n_warmup)
        delta = sampler.warmup[pi, ] - center

        prev = step(sampler, prev, delta)

        if sampler.problem.homogeneous and (
                n_samples * sampler.thinning % sampler.nproj == 0):
            prev = sampler._reproject(prev)
            center = sampler._reproject(center)

        if i % sampler.thinning == 0:
            samples[i//sampler.thinning - 1, ] = prev

        center = ((n_samples * center) / (n_samples + 1) +
                  prev / (n_samples + 1))
        n_samples += 1

    return (sampler.retries, samples)

Sample a single chain for OptGPSampler .


def ast2str(expr, level=0, names=None):
    """convert compiled ast to gene_reaction_rule str

    Parameters
    ----------
    expr : str
        string for a gene reaction rule, e.g "a and b"
    level : int
        internal use only
    names : dict
        Dict where each element id a gene identifier and the value is the
        gene name. Use this to get a rule str which uses names instead. This
        should be done for display purposes only. All gene_reaction_rule
        strings which are computed with should use the id.

    Returns
    ------
    string
        The gene reaction rule
    """
    if isinstance(expr, Expression):
        return ast2str(expr.body, 0, names) \
            if hasattr(expr, "body") else ""
    elif isinstance(expr, Name):
        return names.get(expr.id, expr.id) if names else expr.id
    elif isinstance(expr, BoolOp):
        op = expr.op
        if isinstance(op, Or):
            str_exp = " or ".join(ast2str(i, level + 1, names)
                                  for i in expr.values)
        elif isinstance(op, And):
            str_exp = " and ".join(ast2str(i, level + 1, names)
                                   for i in expr.values)
        else:
            raise TypeError("unsupported operation " + op.__class__.__name)
        return "(" + str_exp + ")" if level else str_exp
    elif expr is None:
        return ""
    else:
        raise TypeError("unsupported operation  " + repr(expr))

def
ast2str
(
expr
,
level
=
0
,
names
=
)
:
if
isinstance
(
expr
,
Expression
)
:
return
ast2str
(
expr
.
body
,
0
,
names
)
if
hasattr
(
expr
,
"body"
)
else
""
elif
isinstance
(
expr
,
Name
)
:
return
names
.
get
(
expr
.
id
,
expr
.
id
)
if
names
else
expr
.
id
elif
isinstance
(
expr
,
BoolOp
)
:
op
=
expr
.
op
if
isinstance
(
op
,
Or
)
:
str_exp
=
" or "
.
join
(
ast2str
(
i
,
level
+
1
,
names
)
for
i
in
expr
.
values
)
elif
isinstance
(
op
,
And
)
:
str_exp
=
" and "
.
join
(
ast2str
(
i
,
level
+
1
,
names
)
for
i
in
expr
.
values
)
else
:
raise
TypeError
(
"unsupported operation "
+
op
.
__class__
.
__name
)
return
"("
+
str_exp
+
")"
if
level
else
str_exp
elif
expr
is
:
return
""
else
:
raise
TypeError
(
"unsupported operation  "
+
repr
(
expr
)
)


def eval_gpr(expr, knockouts):
    """evaluate compiled ast of gene_reaction_rule with knockouts

    Parameters
    ----------
    expr : Expression
        The ast of the gene reaction rule
    knockouts : DictList, set
        Set of genes that are knocked out

    Returns
    -------
    bool
        True if the gene reaction rule is true with the given knockouts
        otherwise false
    """
    if isinstance(expr, Expression):
        return eval_gpr(expr.body, knockouts)
    elif isinstance(expr, Name):
        return expr.id not in knockouts
    elif isinstance(expr, BoolOp):
        op = expr.op
        if isinstance(op, Or):
            return any(eval_gpr(i, knockouts) for i in expr.values)
        elif isinstance(op, And):
            return all(eval_gpr(i, knockouts) for i in expr.values)
        else:
            raise TypeError("unsupported operation " + op.__class__.__name__)
    elif expr is None:
        return True
    else:
        raise TypeError("unsupported operation  " + repr(expr))

def
eval_gpr
(
expr
,
knockouts
)
:
if
isinstance
(
expr
,
Expression
)
:
return
eval_gpr
(
expr
.
body
,
knockouts
)
elif
isinstance
(
expr
,
Name
)
:
return
expr
.
id
not
in
knockouts
elif
isinstance
(
expr
,
BoolOp
)
:
op
=
expr
.
op
if
isinstance
(
op
,
Or
)
:
return
any
(
eval_gpr
(
i
,
knockouts
)
for
i
in
expr
.
values
)
elif
isinstance
(
op
,
And
)
:
return
all
(
eval_gpr
(
i
,
knockouts
)
for
i
in
expr
.
values
)
else
:
raise
TypeError
(
"unsupported operation "
+
op
.
__class__
.
__name__
)
elif
expr
is
:
return
True
else
:
raise
TypeError
(
"unsupported operation  "
+
repr
(
expr
)
)


def parse_gpr(str_expr):
    """parse gpr into AST

    Parameters
    ----------
    str_expr : string
        string with the gene reaction rule to parse

    Returns
    -------
    tuple
        elements ast_tree and gene_ids as a set
    """
    str_expr = str_expr.strip()
    if len(str_expr) == 0:
        return None, set()
    for char, escaped in replacements:
        if char in str_expr:
            str_expr = str_expr.replace(char, escaped)
    escaped_str = keyword_re.sub("__cobra_escape__", str_expr)
    escaped_str = number_start_re.sub("__cobra_escape__", escaped_str)
    tree = ast_parse(escaped_str, "<string>", "eval")
    cleaner = GPRCleaner()
    cleaner.visit(tree)
    eval_gpr(tree, set())  # ensure the rule can be evaluated
    return tree, cleaner.gene_set

def
parse_gpr
(
str_expr
)
:
str_expr
=
str_expr
.
strip
(
)
if
len
(
str_expr
)
==
0
:
return
,
set
(
)
for
char
,
escaped
in
replacements
:
if
char
in
str_expr
:
str_expr
=
str_expr
.
replace
(
char
,
escaped
)
escaped_str
=
keyword_re
.
sub
(
"__cobra_escape__"
,
str_expr
)
escaped_str
=
number_start_re
.
sub
(
"__cobra_escape__"
,
escaped_str
)
tree
=
ast_parse
(
escaped_str
,
"<string>"
,
"eval"
)
cleaner
=
GPRCleaner
(
)
cleaner
.
visit
(
tree
)
eval_gpr
(
tree
,
set
(
)
)
# ensure the rule can be evaluated
return
tree
,
cleaner
.
gene_set


def knock_out(self):
        """Knockout gene by marking it as non-functional and setting all
        associated reactions bounds to zero.

        The change is reverted upon exit if executed within the model as
        context.
        """
        self.functional = False
        for reaction in self.reactions:
            if not reaction.functional:
                reaction.bounds = (0, 0)

def knock_out ( self ) : self . functional = False for reaction in self . reactions : if not reaction . functional : reaction . bounds = ( 0 , 0 )

Knockout gene by marking it as non - functional and setting all associated reactions bounds to zero .


def remove_from_model(self, model=None,
                          make_dependent_reactions_nonfunctional=True):
        """Removes the association

        Parameters
        ----------
        model : cobra model
           The model to remove the gene from
        make_dependent_reactions_nonfunctional : bool
           If True then replace the gene with 'False' in the gene
           association, else replace the gene with 'True'

        .. deprecated :: 0.4
            Use cobra.manipulation.delete_model_genes to simulate knockouts
            and cobra.manipulation.remove_genes to remove genes from
            the model.

        """
        warn("Use cobra.manipulation.remove_genes instead")
        if model is not None:
            if model != self._model:
                raise Exception("%s is a member of %s, not %s" %
                                (repr(self), repr(self._model), repr(model)))
        if self._model is None:
            raise Exception('%s is not in a model' % repr(self))

        if make_dependent_reactions_nonfunctional:
            gene_state = 'False'
        else:
            gene_state = 'True'
        the_gene_re = re.compile('(^|(?<=( |\()))%s(?=( |\)|$))' %
                                 re.escape(self.id))

        # remove reference to the gene in all groups
        associated_groups = self._model.get_associated_groups(self)
        for group in associated_groups:
            group.remove_members(self)

        self._model.genes.remove(self)
        self._model = None

        for the_reaction in list(self._reaction):
            the_reaction._gene_reaction_rule = the_gene_re.sub(
                gene_state, the_reaction.gene_reaction_rule)
            the_reaction._genes.remove(self)
            # Now, deactivate the reaction if its gene association evaluates
            # to False
            the_gene_reaction_relation = the_reaction.gene_reaction_rule
            for other_gene in the_reaction._genes:
                other_gene_re = re.compile('(^|(?<=( |\()))%s(?=( |\)|$))' %
                                           re.escape(other_gene.id))
                the_gene_reaction_relation = other_gene_re.sub(
                    'True',
                    the_gene_reaction_relation)

            if not eval(the_gene_reaction_relation):
                the_reaction.lower_bound = 0
                the_reaction.upper_bound = 0
        self._reaction.clear()


def add_moma(model, solution=None, linear=True):
    r"""Add constraints and objective representing for MOMA.

    This adds variables and constraints for the minimization of metabolic
    adjustment (MOMA) to the model.

    Parameters
    ----------
    model : cobra.Model
        The model to add MOMA constraints and objective to.
    solution : cobra.Solution, optional
        A previous solution to use as a reference. If no solution is given,
        one will be computed using pFBA.
    linear : bool, optional
        Whether to use the linear MOMA formulation or not (default True).

    Notes
    -----
    In the original MOMA [1]_ specification one looks for the flux distribution
    of the deletion (v^d) closest to the fluxes without the deletion (v).
    In math this means:

    minimize \sum_i (v^d_i - v_i)^2
    s.t. Sv^d = 0
         lb_i <= v^d_i <= ub_i

    Here, we use a variable transformation v^t := v^d_i - v_i. Substituting
    and using the fact that Sv = 0 gives:

    minimize \sum_i (v^t_i)^2
    s.t. Sv^d = 0
         v^t = v^d_i - v_i
         lb_i <= v^d_i <= ub_i

    So basically we just re-center the flux space at the old solution and then
    find the flux distribution closest to the new zero (center). This is the
    same strategy as used in cameo.

    In the case of linear MOMA [2]_, we instead minimize \sum_i abs(v^t_i). The
    linear MOMA is typically significantly faster. Also quadratic MOMA tends
    to give flux distributions in which all fluxes deviate from the reference
    fluxes a little bit whereas linear MOMA tends to give flux distributions
    where the majority of fluxes are the same reference with few fluxes
    deviating a lot (typical effect of L2 norm vs L1 norm).

    The former objective function is saved in the optlang solver interface as
    ``"moma_old_objective"`` and this can be used to immediately extract the
    value of the former objective after MOMA optimization.

    See Also
    --------
    pfba : parsimonious FBA

    References
    ----------
    .. [1] Segrè, Daniel, Dennis Vitkup, and George M. Church. “Analysis of
           Optimality in Natural and Perturbed Metabolic Networks.”
           Proceedings of the National Academy of Sciences 99, no. 23
           (November 12, 2002): 15112. https://doi.org/10.1073/pnas.232349399.
    .. [2] Becker, Scott A, Adam M Feist, Monica L Mo, Gregory Hannum,
           Bernhard Ø Palsson, and Markus J Herrgard. “Quantitative
           Prediction of Cellular Metabolism with Constraint-Based Models:
           The COBRA Toolbox.” Nature Protocols 2 (March 29, 2007): 727.
    """
    if 'moma_old_objective' in model.solver.variables:
        raise ValueError('model is already adjusted for MOMA')

    # Fall back to default QP solver if current one has no QP capability
    if not linear:
        model.solver = sutil.choose_solver(model, qp=True)

    if solution is None:
        solution = pfba(model)
    prob = model.problem
    v = prob.Variable("moma_old_objective")
    c = prob.Constraint(model.solver.objective.expression - v,
                        lb=0.0, ub=0.0, name="moma_old_objective_constraint")
    to_add = [v, c]
    model.objective = prob.Objective(Zero, direction="min", sloppy=True)
    obj_vars = []
    for r in model.reactions:
        flux = solution.fluxes[r.id]
        if linear:
            components = sutil.add_absolute_expression(
                model, r.flux_expression, name="moma_dist_" + r.id,
                difference=flux, add=False)
            to_add.extend(components)
            obj_vars.append(components.variable)
        else:
            dist = prob.Variable("moma_dist_" + r.id)
            const = prob.Constraint(r.flux_expression - dist, lb=flux, ub=flux,
                                    name="moma_constraint_" + r.id)
            to_add.extend([dist, const])
            obj_vars.append(dist ** 2)
    model.add_cons_vars(to_add)
    if linear:
        model.objective.set_linear_coefficients({v: 1.0 for v in obj_vars})
    else:
        model.objective = prob.Objective(
            add(obj_vars), direction="min", sloppy=True)

r Add constraints and objective representing for MOMA .


def _fix_type(value):
    """convert possible types to str, float, and bool"""
    # Because numpy floats can not be pickled to json
    if isinstance(value, string_types):
        return str(value)
    if isinstance(value, float_):
        return float(value)
    if isinstance(value, bool_):
        return bool(value)
    if isinstance(value, set):
        return list(value)
    if isinstance(value, dict):
        return OrderedDict((key, value[key]) for key in sorted(value))
    # handle legacy Formula type
    if value.__class__.__name__ == "Formula":
        return str(value)
    if value is None:
        return ""
    return value

convert possible types to str float and bool


def _update_optional(cobra_object, new_dict, optional_attribute_dict,
                     ordered_keys):
    """update new_dict with optional attributes from cobra_object"""
    for key in ordered_keys:
        default = optional_attribute_dict[key]
        value = getattr(cobra_object, key)
        if value is None or value == default:
            continue
        new_dict[key] = _fix_type(value)

def _update_optional ( cobra_object , new_dict , optional_attribute_dict , ordered_keys ) : for key in ordered_keys : default = optional_attribute_dict [ key ] value = getattr ( cobra_object , key ) if value is None or value == default : continue new_dict [ key ] = _fix_type ( value )


def model_to_dict(model, sort=False):
    """Convert model to a dict.

    Parameters
    ----------
    model : cobra.Model
        The model to reformulate as a dict.
    sort : bool, optional
        Whether to sort the metabolites, reactions, and genes or maintain the
        order defined in the model.

    Returns
    -------
    OrderedDict
        A dictionary with elements, 'genes', 'compartments', 'id',
        'metabolites', 'notes' and 'reactions'; where 'metabolites', 'genes'
        and 'metabolites' are in turn lists with dictionaries holding all
        attributes to form the corresponding object.

    See Also
    --------
    cobra.io.model_from_dict
    """
    obj = OrderedDict()
    obj["metabolites"] = list(map(metabolite_to_dict, model.metabolites))
    obj["reactions"] = list(map(reaction_to_dict, model.reactions))
    obj["genes"] = list(map(gene_to_dict, model.genes))
    obj["id"] = model.id
    _update_optional(model, obj, _OPTIONAL_MODEL_ATTRIBUTES,
                     _ORDERED_OPTIONAL_MODEL_KEYS)
    if sort:
        get_id = itemgetter("id")
        obj["metabolites"].sort(key=get_id)
        obj["reactions"].sort(key=get_id)
        obj["genes"].sort(key=get_id)
    return obj

def model_to_dict ( model , sort = False ) : obj = OrderedDict ( ) obj [ "metabolites" ] = list ( map ( metabolite_to_dict , model . metabolites ) ) obj [ "reactions" ] = list ( map ( reaction_to_dict , model . reactions ) ) obj [ "genes" ] = list ( map ( gene_to_dict , model . genes ) ) obj [ "id" ] = model . id _update_optional ( model , obj , _OPTIONAL_MODEL_ATTRIBUTES , _ORDERED_OPTIONAL_MODEL_KEYS ) if sort : get_id = itemgetter ( "id" ) obj [ "metabolites" ] . sort ( key = get_id ) obj [ "reactions" ] . sort ( key = get_id ) obj [ "genes" ] . sort ( key = get_id ) return obj


def model_from_dict(obj):
    """Build a model from a dict.

    Models stored in json are first formulated as a dict that can be read to
    cobra model using this function.

    Parameters
    ----------
    obj : dict
        A dictionary with elements, 'genes', 'compartments', 'id',
        'metabolites', 'notes' and 'reactions'; where 'metabolites', 'genes'
        and 'metabolites' are in turn lists with dictionaries holding all
        attributes to form the corresponding object.

    Returns
    -------
    cora.core.Model
        The generated model.

    See Also
    --------
    cobra.io.model_to_dict
    """
    if 'reactions' not in obj:
        raise ValueError('Object has no reactions attribute. Cannot load.')
    model = Model()
    model.add_metabolites(
        [metabolite_from_dict(metabolite) for metabolite in obj['metabolites']]
    )
    model.genes.extend([gene_from_dict(gene) for gene in obj['genes']])
    model.add_reactions(
        [reaction_from_dict(reaction, model) for reaction in obj['reactions']]
    )
    objective_reactions = [rxn for rxn in obj['reactions'] if
                           rxn.get('objective_coefficient', 0) != 0]
    coefficients = {
        model.reactions.get_by_id(rxn['id']): rxn['objective_coefficient'] for
        rxn in objective_reactions}
    set_objective(model, coefficients)
    for k, v in iteritems(obj):
        if k in {'id', 'name', 'notes', 'compartments', 'annotation'}:
            setattr(model, k, v)
    return model


def _get_id_compartment(id):
    """extract the compartment from the id string"""
    bracket_search = _bracket_re.findall(id)
    if len(bracket_search) == 1:
        return bracket_search[0][1]
    underscore_search = _underscore_re.findall(id)
    if len(underscore_search) == 1:
        return underscore_search[0][1]
    return None

def _get_id_compartment ( id ) : bracket_search = _bracket_re . findall ( id ) if len ( bracket_search ) == 1 : return bracket_search [ 0 ] [ 1 ] underscore_search = _underscore_re . findall ( id ) if len ( underscore_search ) == 1 : return underscore_search [ 0 ] [ 1 ] return None


def _cell(x):
    """translate an array x into a MATLAB cell array"""
    x_no_none = [i if i is not None else "" for i in x]
    return array(x_no_none, dtype=np_object)

def _cell ( x ) : x_no_none = [ i if i is not None else "" for i in x ] return array ( x_no_none , dtype = np_object )


def load_matlab_model(infile_path, variable_name=None, inf=inf):
    """Load a cobra model stored as a .mat file

    Parameters
    ----------
    infile_path: str
        path to the file to to read
    variable_name: str, optional
        The variable name of the model in the .mat file. If this is not
        specified, then the first MATLAB variable which looks like a COBRA
        model will be used
    inf: value
        The value to use for infinite bounds. Some solvers do not handle
        infinite values so for using those, set this to a high numeric value.

    Returns
    -------
    cobra.core.Model.Model:
        The resulting cobra model

    """
    if not scipy_io:
        raise ImportError('load_matlab_model requires scipy')

    data = scipy_io.loadmat(infile_path)
    possible_names = []
    if variable_name is None:
        # skip meta variables
        meta_vars = {"__globals__", "__header__", "__version__"}
        possible_names = sorted(i for i in data if i not in meta_vars)
        if len(possible_names) == 1:
            variable_name = possible_names[0]
    if variable_name is not None:
        return from_mat_struct(data[variable_name], model_id=variable_name,
                               inf=inf)
    for possible_name in possible_names:
        try:
            return from_mat_struct(data[possible_name], model_id=possible_name,
                                   inf=inf)
        except ValueError:
            pass
    # If code here is executed, then no model was found.
    raise IOError("no COBRA model found")

Load a cobra model stored as a . mat file


def save_matlab_model(model, file_name, varname=None):
    """Save the cobra model as a .mat file.

    This .mat file can be used directly in the MATLAB version of COBRA.

    Parameters
    ----------
    model : cobra.core.Model.Model object
        The model to save
    file_name : str or file-like object
        The file to save to
    varname : string
       The name of the variable within the workspace
    """
    if not scipy_io:
        raise ImportError('load_matlab_model requires scipy')

    if varname is None:
        varname = str(model.id) \
            if model.id is not None and len(model.id) > 0 \
            else "exported_model"
    mat = create_mat_dict(model)
    scipy_io.savemat(file_name, {varname: mat},
                     appendmat=True, oned_as="column")

def
save_matlab_model
(
model
,
file_name
,
varname
=
)
:
if
not
scipy_io
:
raise
ImportError
(
'load_matlab_model requires scipy'
)
if
varname
is
:
varname
=
str
(
model
.
id
)
if
model
.
id
is
not
and
len
(
model
.
id
)
>
0
else
"exported_model"
mat
=
create_mat_dict
(
model
)
scipy_io
.
savemat
(
file_name
,
{
varname
:
mat
}
,
appendmat
=
True
,
oned_as
=
"column"
)


def create_mat_dict(model):
    """create a dict mapping model attributes to arrays"""
    rxns = model.reactions
    mets = model.metabolites
    mat = OrderedDict()
    mat["mets"] = _cell([met_id for met_id in create_mat_metabolite_id(model)])
    mat["metNames"] = _cell(mets.list_attr("name"))
    mat["metFormulas"] = _cell([str(m.formula) for m in mets])
    try:
        mat["metCharge"] = array(mets.list_attr("charge")) * 1.
    except TypeError:
        # can't have any None entries for charge, or this will fail
        pass
    mat["genes"] = _cell(model.genes.list_attr("id"))
    # make a matrix for rxnGeneMat
    # reactions are rows, genes are columns
    rxn_gene = scipy_sparse.dok_matrix((len(model.reactions),
                                        len(model.genes)))
    if min(rxn_gene.shape) > 0:
        for i, reaction in enumerate(model.reactions):
            for gene in reaction.genes:
                rxn_gene[i, model.genes.index(gene)] = 1
        mat["rxnGeneMat"] = rxn_gene
    mat["grRules"] = _cell(rxns.list_attr("gene_reaction_rule"))
    mat["rxns"] = _cell(rxns.list_attr("id"))
    mat["rxnNames"] = _cell(rxns.list_attr("name"))
    mat["subSystems"] = _cell(rxns.list_attr("subsystem"))
    stoich_mat = create_stoichiometric_matrix(model)
    mat["S"] = stoich_mat if stoich_mat is not None else [[]]
    # multiply by 1 to convert to float, working around scipy bug
    # https://github.com/scipy/scipy/issues/4537
    mat["lb"] = array(rxns.list_attr("lower_bound")) * 1.
    mat["ub"] = array(rxns.list_attr("upper_bound")) * 1.
    mat["b"] = array(mets.list_attr("_bound")) * 1.
    mat["c"] = array(rxns.list_attr("objective_coefficient")) * 1.
    mat["rev"] = array(rxns.list_attr("reversibility")) * 1
    mat["description"] = str(model.id)
    return mat


def model_to_pymatbridge(model, variable_name="model", matlab=None):
    """send the model to a MATLAB workspace through pymatbridge

    This model can then be manipulated through the COBRA toolbox

    Parameters
    ----------
    variable_name : str
        The variable name to which the model will be assigned in the
        MATLAB workspace

    matlab : None or pymatbridge.Matlab instance
        The MATLAB workspace to which the variable will be sent. If
        this is None, then this will be sent to the same environment
        used in IPython magics.

    """
    if scipy_sparse is None:
        raise ImportError("`model_to_pymatbridge` requires scipy!")
    if matlab is None:  # assumed to be running an IPython magic
        from IPython import get_ipython
        matlab = get_ipython().magics_manager.registry["MatlabMagics"].Matlab
    model_info = create_mat_dict(model)
    S = model_info["S"].todok()
    model_info["S"] = 0
    temp_S_name = "cobra_pymatbridge_temp_" + uuid4().hex
    _check(matlab.set_variable(variable_name, model_info))
    _check(matlab.set_variable(temp_S_name, S))
    _check(matlab.run_code("%s.S = %s;" % (variable_name, temp_S_name)))
    # all vectors need to be transposed
    for i in model_info.keys():
        if i == "S":
            continue
        _check(matlab.run_code("{0}.{1} = {0}.{1}';".format(variable_name, i)))
    _check(matlab.run_code("clear %s;" % temp_S_name))


def get_context(obj):
    """Search for a context manager"""
    try:
        return obj._contexts[-1]
    except (AttributeError, IndexError):
        pass

    try:
        return obj._model._contexts[-1]
    except (AttributeError, IndexError):
        pass

    return None

def get_context ( obj ) : try : return obj . _contexts [ - 1 ] except ( AttributeError , IndexError ) : pass try : return obj . _model . _contexts [ - 1 ] except ( AttributeError , IndexError ) : pass return None


def resettable(f):
    """A decorator to simplify the context management of simple object
    attributes. Gets the value of the attribute prior to setting it, and stores
    a function to set the value to the old value in the HistoryManager.
    """

    def wrapper(self, new_value):
        context = get_context(self)
        if context:
            old_value = getattr(self, f.__name__)
            # Don't clutter the context with unchanged variables
            if old_value == new_value:
                return
            context(partial(f, self, old_value))

        f(self, new_value)

    return wrapper

A decorator to simplify the context management of simple object attributes . Gets the value of the attribute prior to setting it and stores a function to set the value to the old value in the HistoryManager .


def get_solution(model, reactions=None, metabolites=None, raise_error=False):
    """
    Generate a solution representation of the current solver state.

    Parameters
    ---------
    model : cobra.Model
        The model whose reactions to retrieve values for.
    reactions : list, optional
        An iterable of `cobra.Reaction` objects. Uses `model.reactions` by
        default.
    metabolites : list, optional
        An iterable of `cobra.Metabolite` objects. Uses `model.metabolites` by
        default.
    raise_error : bool
        If true, raise an OptimizationError if solver status is not optimal.

    Returns
    -------
    cobra.Solution

    Note
    ----
    This is only intended for the `optlang` solver interfaces and not the
    legacy solvers.
    """
    check_solver_status(model.solver.status, raise_error=raise_error)
    if reactions is None:
        reactions = model.reactions
    if metabolites is None:
        metabolites = model.metabolites

    rxn_index = list()
    fluxes = empty(len(reactions))
    reduced = empty(len(reactions))
    var_primals = model.solver.primal_values
    shadow = empty(len(metabolites))
    if model.solver.is_integer:
        reduced.fill(nan)
        shadow.fill(nan)
        for (i, rxn) in enumerate(reactions):
            rxn_index.append(rxn.id)
            fluxes[i] = var_primals[rxn.id] - var_primals[rxn.reverse_id]
        met_index = [met.id for met in metabolites]
    else:
        var_duals = model.solver.reduced_costs
        for (i, rxn) in enumerate(reactions):
            forward = rxn.id
            reverse = rxn.reverse_id
            rxn_index.append(forward)
            fluxes[i] = var_primals[forward] - var_primals[reverse]
            reduced[i] = var_duals[forward] - var_duals[reverse]
        met_index = list()
        constr_duals = model.solver.shadow_prices
        for (i, met) in enumerate(metabolites):
            met_index.append(met.id)
            shadow[i] = constr_duals[met.id]
    return Solution(model.solver.objective.value, model.solver.status,
                    Series(index=rxn_index, data=fluxes, name="fluxes"),
                    Series(index=rxn_index, data=reduced,
                           name="reduced_costs"),
                    Series(index=met_index, data=shadow, name="shadow_prices"))

def get_solution ( model , reactions = None , metabolites = None , raise_error = False ) : check_solver_status ( model . solver . status , raise_error = raise_error ) if reactions is None : reactions = model . reactions if metabolites is None : metabolites = model . metabolites rxn_index = list ( ) fluxes = empty ( len ( reactions ) ) reduced = empty ( len ( reactions ) ) var_primals = model . solver . primal_values shadow = empty ( len ( metabolites ) ) if model . solver . is_integer : reduced . fill ( nan ) shadow . fill ( nan ) for ( i , rxn ) in enumerate ( reactions ) : rxn_index . append ( rxn . id ) fluxes [ i ] = var_primals [ rxn . id ] - var_primals [ rxn . reverse_id ] met_index = [ met . id for met in metabolites ] else : var_duals = model . solver . reduced_costs for ( i , rxn ) in enumerate ( reactions ) : forward = rxn . id reverse = rxn . reverse_id rxn_index . append ( forward ) fluxes [ i ] = var_primals [ forward ] - var_primals [ reverse ] reduced [ i ] = var_duals [ forward ] - var_duals [ reverse ] met_index = list ( ) constr_duals = model . solver . shadow_prices for ( i , met ) in enumerate ( metabolites ) : met_index . append ( met . id ) shadow [ i ] = constr_duals [ met . id ] return Solution ( model . solver . objective . value , model . solver . status , Series ( index = rxn_index , data = fluxes , name = "fluxes" ) , Series ( index = rxn_index , data = reduced , name = "reduced_costs" ) , Series ( index = met_index , data = shadow , name = "shadow_prices" ) )

Generate a solution representation of the current solver state .


def get_metabolite_compartments(self):
        """Return all metabolites' compartments."""
        warn('use Model.compartments instead', DeprecationWarning)
        return {met.compartment for met in self.metabolites
                if met.compartment is not None}

def
get_metabolite_compartments
(
self
)
:
warn
(
'use Model.compartments instead'
,
DeprecationWarning
)
return
{
met
.
compartment
for
met
in
self
.
metabolites
if
met
.
compartment
is
not
}


def medium(self, medium):
        """Get or set the constraints on the model exchanges.

        `model.medium` returns a dictionary of the bounds for each of the
        boundary reactions, in the form of `{rxn_id: bound}`, where `bound`
        specifies the absolute value of the bound in direction of metabolite
        creation (i.e., lower_bound for `met <--`, upper_bound for `met -->`)

        Parameters
        ----------
        medium: dictionary-like
            The medium to initialize. medium should be a dictionary defining
            `{rxn_id: bound}` pairs.

        """

        def set_active_bound(reaction, bound):
            if reaction.reactants:
                reaction.lower_bound = -bound
            elif reaction.products:
                reaction.upper_bound = bound

        # Set the given media bounds
        media_rxns = list()
        exchange_rxns = frozenset(self.exchanges)
        for rxn_id, bound in iteritems(medium):
            rxn = self.reactions.get_by_id(rxn_id)
            if rxn not in exchange_rxns:
                LOGGER.warn("%s does not seem to be an"
                            " an exchange reaction. Applying bounds anyway.",
                            rxn.id)
            media_rxns.append(rxn)
            set_active_bound(rxn, bound)

        media_rxns = frozenset(media_rxns)

        # Turn off reactions not present in media
        for rxn in (exchange_rxns - media_rxns):
            set_active_bound(rxn, 0)

Get or set the constraints on the model exchanges .


def add_metabolites(self, metabolite_list):
        """Will add a list of metabolites to the model object and add new
        constraints accordingly.

        The change is reverted upon exit when using the model as a context.

        Parameters
        ----------
        metabolite_list : A list of `cobra.core.Metabolite` objects

        """
        if not hasattr(metabolite_list, '__iter__'):
            metabolite_list = [metabolite_list]
        if len(metabolite_list) == 0:
            return None

        # First check whether the metabolites exist in the model
        metabolite_list = [x for x in metabolite_list
                           if x.id not in self.metabolites]

        bad_ids = [m for m in metabolite_list
                   if not isinstance(m.id, string_types) or len(m.id) < 1]
        if len(bad_ids) != 0:
            raise ValueError('invalid identifiers in {}'.format(repr(bad_ids)))

        for x in metabolite_list:
            x._model = self
        self.metabolites += metabolite_list

        # from cameo ...
        to_add = []
        for met in metabolite_list:
            if met.id not in self.constraints:
                constraint = self.problem.Constraint(
                    Zero, name=met.id, lb=0, ub=0)
                to_add += [constraint]

        self.add_cons_vars(to_add)

        context = get_context(self)
        if context:
            context(partial(self.metabolites.__isub__, metabolite_list))
            for x in metabolite_list:
                # Do we care?
                context(partial(setattr, x, '_model', None))

Will add a list of metabolites to the model object and add new constraints accordingly .


def remove_metabolites(self, metabolite_list, destructive=False):
        """Remove a list of metabolites from the the object.

        The change is reverted upon exit when using the model as a context.

        Parameters
        ----------
        metabolite_list : list
            A list with `cobra.Metabolite` objects as elements.

        destructive : bool
            If False then the metabolite is removed from all
            associated reactions.  If True then all associated
            reactions are removed from the Model.

        """
        if not hasattr(metabolite_list, '__iter__'):
            metabolite_list = [metabolite_list]
        # Make sure metabolites exist in model
        metabolite_list = [x for x in metabolite_list
                           if x.id in self.metabolites]
        for x in metabolite_list:
            x._model = None

            # remove reference to the metabolite in all groups
            associated_groups = self.get_associated_groups(x)
            for group in associated_groups:
                group.remove_members(x)

            if not destructive:
                for the_reaction in list(x._reaction):
                    the_coefficient = the_reaction._metabolites[x]
                    the_reaction.subtract_metabolites({x: the_coefficient})

            else:
                for x in list(x._reaction):
                    x.remove_from_model()

        self.metabolites -= metabolite_list

        to_remove = [self.solver.constraints[m.id] for m in metabolite_list]
        self.remove_cons_vars(to_remove)

        context = get_context(self)
        if context:
            context(partial(self.metabolites.__iadd__, metabolite_list))
            for x in metabolite_list:
                context(partial(setattr, x, '_model', self))

Remove a list of metabolites from the the object .


def add_boundary(self, metabolite, type="exchange", reaction_id=None,
                     lb=None, ub=None, sbo_term=None):
        """
        Add a boundary reaction for a given metabolite.

        There are three different types of pre-defined boundary reactions:
        exchange, demand, and sink reactions.
        An exchange reaction is a reversible, unbalanced reaction that adds
        to or removes an extracellular metabolite from the extracellular
        compartment.
        A demand reaction is an irreversible reaction that consumes an
        intracellular metabolite.
        A sink is similar to an exchange but specifically for intracellular
        metabolites.

        If you set the reaction `type` to something else, you must specify the
        desired identifier of the created reaction along with its upper and
        lower bound. The name will be given by the metabolite name and the
        given `type`.

        Parameters
        ----------
        metabolite : cobra.Metabolite
            Any given metabolite. The compartment is not checked but you are
            encouraged to stick to the definition of exchanges and sinks.
        type : str, {"exchange", "demand", "sink"}
            Using one of the pre-defined reaction types is easiest. If you
            want to create your own kind of boundary reaction choose
            any other string, e.g., 'my-boundary'.
        reaction_id : str, optional
            The ID of the resulting reaction. This takes precedence over the
            auto-generated identifiers but beware that it might make boundary
            reactions harder to identify afterwards when using `model.boundary`
            or specifically `model.exchanges` etc.
        lb : float, optional
            The lower bound of the resulting reaction.
        ub : float, optional
            The upper bound of the resulting reaction.
        sbo_term : str, optional
            A correct SBO term is set for the available types. If a custom
            type is chosen, a suitable SBO term should also be set.

        Returns
        -------
        cobra.Reaction
            The created boundary reaction.

        Examples
        --------
        >>> import cobra.test
        >>> model = cobra.test.create_test_model("textbook")
        >>> demand = model.add_boundary(model.metabolites.atp_c, type="demand")
        >>> demand.id
        'DM_atp_c'
        >>> demand.name
        'ATP demand'
        >>> demand.bounds
        (0, 1000.0)
        >>> demand.build_reaction_string()
        'atp_c --> '

        """
        ub = CONFIGURATION.upper_bound if ub is None else ub
        lb = CONFIGURATION.lower_bound if lb is None else lb
        types = {
            "exchange": ("EX", lb, ub, sbo_terms["exchange"]),
            "demand": ("DM", 0, ub, sbo_terms["demand"]),
            "sink": ("SK", lb, ub, sbo_terms["sink"])
        }
        if type == "exchange":
            external = find_external_compartment(self)
            if metabolite.compartment != external:
                raise ValueError("The metabolite is not an external metabolite"
                                 " (compartment is `%s` but should be `%s`). "
                                 "Did you mean to add a demand or sink? "
                                 "If not, either change its compartment or "
                                 "rename the model compartments to fix this." %
                                 (metabolite.compartment, external))
        if type in types:
            prefix, lb, ub, default_term = types[type]
            if reaction_id is None:
                reaction_id = "{}_{}".format(prefix, metabolite.id)
            if sbo_term is None:
                sbo_term = default_term
        if reaction_id is None:
            raise ValueError(
                "Custom types of boundary reactions require a custom "
                "identifier. Please set the `reaction_id`.")
        if reaction_id in self.reactions:
            raise ValueError(
                "Boundary reaction '{}' already exists.".format(reaction_id))
        name = "{} {}".format(metabolite.name, type)
        rxn = Reaction(id=reaction_id, name=name, lower_bound=lb,
                       upper_bound=ub)
        rxn.add_metabolites({metabolite: -1})
        if sbo_term:
            rxn.annotation["sbo"] = sbo_term
        self.add_reactions([rxn])
        return rxn

Add a boundary reaction for a given metabolite .


def add_reactions(self, reaction_list):
        """Add reactions to the model.

        Reactions with identifiers identical to a reaction already in the
        model are ignored.

        The change is reverted upon exit when using the model as a context.

        Parameters
        ----------
        reaction_list : list
            A list of `cobra.Reaction` objects
        """
        def existing_filter(rxn):
            if rxn.id in self.reactions:
                LOGGER.warning(
                    "Ignoring reaction '%s' since it already exists.", rxn.id)
                return False
            return True

        # First check whether the reactions exist in the model.
        pruned = DictList(filter(existing_filter, reaction_list))

        context = get_context(self)

        # Add reactions. Also take care of genes and metabolites in the loop.
        for reaction in pruned:
            reaction._model = self
            # Build a `list()` because the dict will be modified in the loop.
            for metabolite in list(reaction.metabolites):
                # TODO: Should we add a copy of the metabolite instead?
                if metabolite not in self.metabolites:
                    self.add_metabolites(metabolite)
                # A copy of the metabolite exists in the model, the reaction
                # needs to point to the metabolite in the model.
                else:
                    # FIXME: Modifying 'private' attributes is horrible.
                    stoichiometry = reaction._metabolites.pop(metabolite)
                    model_metabolite = self.metabolites.get_by_id(
                        metabolite.id)
                    reaction._metabolites[model_metabolite] = stoichiometry
                    model_metabolite._reaction.add(reaction)
                    if context:
                        context(partial(
                            model_metabolite._reaction.remove, reaction))

            for gene in list(reaction._genes):
                # If the gene is not in the model, add it
                if not self.genes.has_id(gene.id):
                    self.genes += [gene]
                    gene._model = self

                    if context:
                        # Remove the gene later
                        context(partial(self.genes.__isub__, [gene]))
                        context(partial(setattr, gene, '_model', None))

                # Otherwise, make the gene point to the one in the model
                else:
                    model_gene = self.genes.get_by_id(gene.id)
                    if model_gene is not gene:
                        reaction._dissociate_gene(gene)
                        reaction._associate_gene(model_gene)

        self.reactions += pruned

        if context:
            context(partial(self.reactions.__isub__, pruned))

        # from cameo ...
        self._populate_solver(pruned)


def remove_reactions(self, reactions, remove_orphans=False):
        """Remove reactions from the model.

        The change is reverted upon exit when using the model as a context.

        Parameters
        ----------
        reactions : list
            A list with reactions (`cobra.Reaction`), or their id's, to remove

        remove_orphans : bool
            Remove orphaned genes and metabolites from the model as well

        """
        if isinstance(reactions, string_types) or hasattr(reactions, "id"):
            warn("need to pass in a list")
            reactions = [reactions]

        context = get_context(self)

        for reaction in reactions:

            # Make sure the reaction is in the model
            try:
                reaction = self.reactions[self.reactions.index(reaction)]
            except ValueError:
                warn('%s not in %s' % (reaction, self))

            else:
                forward = reaction.forward_variable
                reverse = reaction.reverse_variable

                if context:

                    obj_coef = reaction.objective_coefficient

                    if obj_coef != 0:
                        context(partial(
                            self.solver.objective.set_linear_coefficients,
                            {forward: obj_coef, reverse: -obj_coef}))

                    context(partial(self._populate_solver, [reaction]))
                    context(partial(setattr, reaction, '_model', self))
                    context(partial(self.reactions.add, reaction))

                self.remove_cons_vars([forward, reverse])
                self.reactions.remove(reaction)
                reaction._model = None

                for met in reaction._metabolites:
                    if reaction in met._reaction:
                        met._reaction.remove(reaction)
                        if context:
                            context(partial(met._reaction.add, reaction))
                        if remove_orphans and len(met._reaction) == 0:
                            self.remove_metabolites(met)

                for gene in reaction._genes:
                    if reaction in gene._reaction:
                        gene._reaction.remove(reaction)
                        if context:
                            context(partial(gene._reaction.add, reaction))

                        if remove_orphans and len(gene._reaction) == 0:
                            self.genes.remove(gene)
                            if context:
                                context(partial(self.genes.add, gene))

                # remove reference to the reaction in all groups
                associated_groups = self.get_associated_groups(reaction)
                for group in associated_groups:
                    group.remove_members(reaction)


def add_groups(self, group_list):
        """Add groups to the model.

        Groups with identifiers identical to a group already in the model are
        ignored.

        If any group contains members that are not in the model, these members
        are added to the model as well. Only metabolites, reactions, and genes
        can have groups.

        Parameters
        ----------
        group_list : list
            A list of `cobra.Group` objects to add to the model.
        """

        def existing_filter(group):
            if group.id in self.groups:
                LOGGER.warning(
                    "Ignoring group '%s' since it already exists.", group.id)
                return False
            return True

        if isinstance(group_list, string_types) or \
                hasattr(group_list, "id"):
            warn("need to pass in a list")
            group_list = [group_list]

        pruned = DictList(filter(existing_filter, group_list))

        for group in pruned:
            group._model = self
            for member in group.members:
                # If the member is not associated with the model, add it
                if isinstance(member, Metabolite):
                    if member not in self.metabolites:
                        self.add_metabolites([member])
                if isinstance(member, Reaction):
                    if member not in self.reactions:
                        self.add_reactions([member])
                # TODO(midnighter): `add_genes` method does not exist.
                # if isinstance(member, Gene):
                #     if member not in self.genes:
                #         self.add_genes([member])

            self.groups += [group]


def remove_groups(self, group_list):
        """Remove groups from the model.

        Members of each group are not removed
        from the model (i.e. metabolites, reactions, and genes in the group
        stay in the model after any groups containing them are removed).

        Parameters
        ----------
        group_list : list
            A list of `cobra.Group` objects to remove from the model.
        """

        if isinstance(group_list, string_types) or \
                hasattr(group_list, "id"):
            warn("need to pass in a list")
            group_list = [group_list]

        for group in group_list:
            # make sure the group is in the model
            if group.id not in self.groups:
                LOGGER.warning("%r not in %r. Ignored.", group, self)
            else:
                self.groups.remove(group)
                group._model = None

def
remove_groups
(
self
,
group_list
)
:
if
isinstance
(
group_list
,
string_types
)
or
hasattr
(
group_list
,
"id"
)
:
warn
(
"need to pass in a list"
)
group_list
=
[
group_list
]
for
group
in
group_list
:
# make sure the group is in the model
if
group
.
id
not
in
self
.
groups
:
LOGGER
.
warning
(
"%r not in %r. Ignored."
,
group
,
self
)
else
:
self
.
groups
.
remove
(
group
)
group
.
_model
=


def _populate_solver(self, reaction_list, metabolite_list=None):
        """Populate attached solver with constraints and variables that
        model the provided reactions.
        """
        constraint_terms = AutoVivification()
        to_add = []
        if metabolite_list is not None:
            for met in metabolite_list:
                to_add += [self.problem.Constraint(
                    Zero, name=met.id, lb=0, ub=0)]
        self.add_cons_vars(to_add)

        for reaction in reaction_list:
            if reaction.id not in self.variables:
                forward_variable = self.problem.Variable(reaction.id)
                reverse_variable = self.problem.Variable(reaction.reverse_id)
                self.add_cons_vars([forward_variable, reverse_variable])
            else:
                reaction = self.reactions.get_by_id(reaction.id)
                forward_variable = reaction.forward_variable
                reverse_variable = reaction.reverse_variable
            for metabolite, coeff in six.iteritems(reaction.metabolites):
                if metabolite.id in self.constraints:
                    constraint = self.constraints[metabolite.id]
                else:
                    constraint = self.problem.Constraint(
                        Zero,
                        name=metabolite.id,
                        lb=0, ub=0)
                    self.add_cons_vars(constraint, sloppy=True)
                constraint_terms[constraint][forward_variable] = coeff
                constraint_terms[constraint][reverse_variable] = -coeff

        self.solver.update()
        for reaction in reaction_list:
            reaction = self.reactions.get_by_id(reaction.id)
            reaction.update_variable_bounds()
        for constraint, terms in six.iteritems(constraint_terms):
            constraint.set_linear_coefficients(terms)

def _populate_solver ( self , reaction_list , metabolite_list = None ) : constraint_terms = AutoVivification ( ) to_add = [ ] if metabolite_list is not None : for met in metabolite_list : to_add += [ self . problem . Constraint ( Zero , name = met . id , lb = 0 , ub = 0 ) ] self . add_cons_vars ( to_add ) for reaction in reaction_list : if reaction . id not in self . variables : forward_variable = self . problem . Variable ( reaction . id ) reverse_variable = self . problem . Variable ( reaction . reverse_id ) self . add_cons_vars ( [ forward_variable , reverse_variable ] ) else : reaction = self . reactions . get_by_id ( reaction . id ) forward_variable = reaction . forward_variable reverse_variable = reaction . reverse_variable for metabolite , coeff in six . iteritems ( reaction . metabolites ) : if metabolite . id in self . constraints : constraint = self . constraints [ metabolite . id ] else : constraint = self . problem . Constraint ( Zero , name = metabolite . id , lb = 0 , ub = 0 ) self . add_cons_vars ( constraint , sloppy = True ) constraint_terms [ constraint ] [ forward_variable ] = coeff constraint_terms [ constraint ] [ reverse_variable ] = - coeff self . solver . update ( ) for reaction in reaction_list : reaction = self . reactions . get_by_id ( reaction . id ) reaction . update_variable_bounds ( ) for constraint , terms in six . iteritems ( constraint_terms ) : constraint . set_linear_coefficients ( terms )

Populate attached solver with constraints and variables that model the provided reactions .


def slim_optimize(self, error_value=float('nan'), message=None):
        """Optimize model without creating a solution object.

        Creating a full solution object implies fetching shadow prices and
        flux values for all reactions and metabolites from the solver
        object. This necessarily takes some time and in cases where only one
        or two values are of interest, it is recommended to instead use this
        function which does not create a solution object returning only the
        value of the objective. Note however that the `optimize()` function
        uses efficient means to fetch values so if you need fluxes/shadow
        prices for more than say 4 reactions/metabolites, then the total
        speed increase of `slim_optimize` versus `optimize` is  expected to
        be small or even negative depending on how you fetch the values
        after optimization.

        Parameters
        ----------
        error_value : float, None
           The value to return if optimization failed due to e.g.
           infeasibility. If None, raise `OptimizationError` if the
           optimization fails.
        message : string
           Error message to use if the model optimization did not succeed.

        Returns
        -------
        float
            The objective value.
        """
        self.solver.optimize()
        if self.solver.status == optlang.interface.OPTIMAL:
            return self.solver.objective.value
        elif error_value is not None:
            return error_value
        else:
            assert_optimal(self, message)

def slim_optimize ( self , error_value = float ( 'nan' ) , message = None ) : self . solver . optimize ( ) if self . solver . status == optlang . interface . OPTIMAL : return self . solver . objective . value elif error_value is not None : return error_value else : assert_optimal ( self , message )

Optimize model without creating a solution object .


def optimize(self, objective_sense=None, raise_error=False):
        """
        Optimize the model using flux balance analysis.

        Parameters
        ----------
        objective_sense : {None, 'maximize' 'minimize'}, optional
            Whether fluxes should be maximized or minimized. In case of None,
            the previous direction is used.
        raise_error : bool
            If true, raise an OptimizationError if solver status is not
             optimal.

        Notes
        -----
        Only the most commonly used parameters are presented here.  Additional
        parameters for cobra.solvers may be available and specified with the
        appropriate keyword argument.

        """
        original_direction = self.objective.direction
        self.objective.direction = \
            {"maximize": "max", "minimize": "min"}.get(
                objective_sense, original_direction)
        self.slim_optimize()
        solution = get_solution(self, raise_error=raise_error)
        self.objective.direction = original_direction
        return solution

def optimize ( self , objective_sense = None , raise_error = False ) : original_direction = self . objective . direction self . objective . direction = { "maximize" : "max" , "minimize" : "min" } . get ( objective_sense , original_direction ) self . slim_optimize ( ) solution = get_solution ( self , raise_error = raise_error ) self . objective . direction = original_direction return solution

Optimize the model using flux balance analysis .


def repair(self, rebuild_index=True, rebuild_relationships=True):
        """Update all indexes and pointers in a model

        Parameters
        ----------
        rebuild_index : bool
            rebuild the indices kept in reactions, metabolites and genes
        rebuild_relationships : bool
             reset all associations between genes, metabolites, model and
             then re-add them.
        """
        if rebuild_index:  # DictList indexes
            self.reactions._generate_index()
            self.metabolites._generate_index()
            self.genes._generate_index()
            self.groups._generate_index()
        if rebuild_relationships:
            for met in self.metabolites:
                met._reaction.clear()
            for gene in self.genes:
                gene._reaction.clear()
            for rxn in self.reactions:
                for met in rxn._metabolites:
                    met._reaction.add(rxn)
                for gene in rxn._genes:
                    gene._reaction.add(rxn)

        # point _model to self
        for l in (self.reactions, self.genes, self.metabolites, self.groups):
            for e in l:
                e._model = self

def
repair
(
self
,
rebuild_index
=
True
,
rebuild_relationships
=
True
)
:
if
rebuild_index
:
# DictList indexes
self
.
reactions
.
_generate_index
(
)
self
.
metabolites
.
_generate_index
(
)
self
.
genes
.
_generate_index
(
)
self
.
groups
.
_generate_index
(
)
if
rebuild_relationships
:
for
met
in
self
.
metabolites
:
met
.
_reaction
.
clear
(
)
for
gene
in
self
.
genes
:
gene
.
_reaction
.
clear
(
)
for
rxn
in
self
.
reactions
:
for
met
in
rxn
.
_metabolites
:
met
.
_reaction
.
add
(
rxn
)
for
gene
in
rxn
.
_genes
:
gene
.
_reaction
.
add
(
rxn
)
# point _model to self
for
l
in
(
self
.
reactions
,
self
.
genes
,
self
.
metabolites
,
self
.
groups
)
:
for
e
in
l
:
e
.
_model
=
self


def merge(self, right, prefix_existing=None, inplace=True,
              objective='left'):
        """Merge two models to create a model with the reactions from both
        models.

        Custom constraints and variables from right models are also copied
        to left model, however note that, constraints and variables are
        assumed to be the same if they have the same name.

        right : cobra.Model
            The model to add reactions from
        prefix_existing : string
            Prefix the reaction identifier in the right that already exist
            in the left model with this string.
        inplace : bool
            Add reactions from right directly to left model object.
            Otherwise, create a new model leaving the left model untouched.
            When done within the model as context, changes to the models are
            reverted upon exit.
        objective : string
            One of 'left', 'right' or 'sum' for setting the objective of the
            resulting model to that of the corresponding model or the sum of
            both.
        """
        if inplace:
            new_model = self
        else:
            new_model = self.copy()
            new_model.id = '{}_{}'.format(self.id, right.id)
        new_reactions = deepcopy(right.reactions)
        if prefix_existing is not None:
            existing = new_reactions.query(
                lambda rxn: rxn.id in self.reactions)
            for reaction in existing:
                reaction.id = '{}{}'.format(prefix_existing, reaction.id)
        new_model.add_reactions(new_reactions)
        interface = new_model.problem
        new_vars = [interface.Variable.clone(v) for v in right.variables if
                    v.name not in new_model.variables]
        new_model.add_cons_vars(new_vars)
        new_cons = [interface.Constraint.clone(c, model=new_model.solver)
                    for c in right.constraints if
                    c.name not in new_model.constraints]
        new_model.add_cons_vars(new_cons, sloppy=True)
        new_model.objective = dict(
            left=self.objective,
            right=right.objective,
            sum=self.objective.expression + right.objective.expression
        )[objective]
        return new_model

def merge ( self , right , prefix_existing = None , inplace = True , objective = 'left' ) : if inplace : new_model = self else : new_model = self . copy ( ) new_model . id = '{}_{}' . format ( self . id , right . id ) new_reactions = deepcopy ( right . reactions ) if prefix_existing is not None : existing = new_reactions . query ( lambda rxn : rxn . id in self . reactions ) for reaction in existing : reaction . id = '{}{}' . format ( prefix_existing , reaction . id ) new_model . add_reactions ( new_reactions ) interface = new_model . problem new_vars = [ interface . Variable . clone ( v ) for v in right . variables if v . name not in new_model . variables ] new_model . add_cons_vars ( new_vars ) new_cons = [ interface . Constraint . clone ( c , model = new_model . solver ) for c in right . constraints if c . name not in new_model . constraints ] new_model . add_cons_vars ( new_cons , sloppy = True ) new_model . objective = dict ( left = self . objective , right = right . objective , sum = self . objective . expression + right . objective . expression ) [ objective ] return new_model

Merge two models to create a model with the reactions from both models .


def _escape_str_id(id_str):
    """make a single string id SBML compliant"""
    for c in ("'", '"'):
        if id_str.startswith(c) and id_str.endswith(c) \
                and id_str.count(c) == 2:
            id_str = id_str.strip(c)
    for char, escaped_char in _renames:
        id_str = id_str.replace(char, escaped_char)
    return id_str

def _escape_str_id ( id_str ) : for c in ( "'" , '"' ) : if id_str . startswith ( c ) and id_str . endswith ( c ) and id_str . count ( c ) == 2 : id_str = id_str . strip ( c ) for char , escaped_char in _renames : id_str = id_str . replace ( char , escaped_char ) return id_str


def escape_ID(cobra_model):
    """makes all ids SBML compliant"""
    for x in chain([cobra_model],
                   cobra_model.metabolites,
                   cobra_model.reactions,
                   cobra_model.genes):
        x.id = _escape_str_id(x.id)
    cobra_model.repair()
    gene_renamer = _GeneEscaper()
    for rxn, rule in iteritems(get_compiled_gene_reaction_rules(cobra_model)):
        if rule is not None:
            rxn._gene_reaction_rule = ast2str(gene_renamer.visit(rule))

def escape_ID ( cobra_model ) : for x in chain ( [ cobra_model ] , cobra_model . metabolites , cobra_model . reactions , cobra_model . genes ) : x . id = _escape_str_id ( x . id ) cobra_model . repair ( ) gene_renamer = _GeneEscaper ( ) for rxn , rule in iteritems ( get_compiled_gene_reaction_rules ( cobra_model ) ) : if rule is not None : rxn . _gene_reaction_rule = ast2str ( gene_renamer . visit ( rule ) )


def rename_genes(cobra_model, rename_dict):
    """renames genes in a model from the rename_dict"""
    recompute_reactions = set()  # need to recomptue related genes
    remove_genes = []
    for old_name, new_name in iteritems(rename_dict):
        # undefined if there a value matches a different key
        # because dict is unordered
        try:
            gene_index = cobra_model.genes.index(old_name)
        except ValueError:
            gene_index = None
        old_gene_present = gene_index is not None
        new_gene_present = new_name in cobra_model.genes
        if old_gene_present and new_gene_present:
            old_gene = cobra_model.genes.get_by_id(old_name)
            # Added in case not renaming some genes:
            if old_gene is not cobra_model.genes.get_by_id(new_name):
                remove_genes.append(old_gene)
                recompute_reactions.update(old_gene._reaction)
        elif old_gene_present and not new_gene_present:
            # rename old gene to new gene
            gene = cobra_model.genes[gene_index]
            # trick DictList into updating index
            cobra_model.genes._dict.pop(gene.id)  # ugh
            gene.id = new_name
            cobra_model.genes[gene_index] = gene
        elif not old_gene_present and new_gene_present:
            pass
        else:  # if not old gene_present and not new_gene_present
            # the new gene's _model will be set by repair
            # This would add genes from rename_dict
            # that are not associated with a rxn
            # cobra_model.genes.append(Gene(new_name))
            pass
    cobra_model.repair()

    class Renamer(NodeTransformer):
        def visit_Name(self, node):
            node.id = rename_dict.get(node.id, node.id)
            return node

    gene_renamer = Renamer()
    for rxn, rule in iteritems(get_compiled_gene_reaction_rules(cobra_model)):
        if rule is not None:
            rxn._gene_reaction_rule = ast2str(gene_renamer.visit(rule))

    for rxn in recompute_reactions:
        rxn.gene_reaction_rule = rxn._gene_reaction_rule
    for i in remove_genes:
        cobra_model.genes.remove(i)


def to_json(model, sort=False, **kwargs):
    """
    Return the model as a JSON document.

    ``kwargs`` are passed on to ``json.dumps``.

    Parameters
    ----------
    model : cobra.Model
        The cobra model to represent.
    sort : bool, optional
        Whether to sort the metabolites, reactions, and genes or maintain the
        order defined in the model.

    Returns
    -------
    str
        String representation of the cobra model as a JSON document.

    See Also
    --------
    save_json_model : Write directly to a file.
    json.dumps : Base function.
    """
    obj = model_to_dict(model, sort=sort)
    obj[u"version"] = JSON_SPEC
    return json.dumps(obj, allow_nan=False, **kwargs)

def to_json ( model , sort = False , * * kwargs ) : obj = model_to_dict ( model , sort = sort ) obj [ u"version" ] = JSON_SPEC return json . dumps ( obj , allow_nan = False , * * kwargs )


def save_json_model(model, filename, sort=False, pretty=False, **kwargs):
    """
    Write the cobra model to a file in JSON format.

    ``kwargs`` are passed on to ``json.dump``.

    Parameters
    ----------
    model : cobra.Model
        The cobra model to represent.
    filename : str or file-like
        File path or descriptor that the JSON representation should be
        written to.
    sort : bool, optional
        Whether to sort the metabolites, reactions, and genes or maintain the
        order defined in the model.
    pretty : bool, optional
        Whether to format the JSON more compactly (default) or in a more
        verbose but easier to read fashion. Can be partially overwritten by the
        ``kwargs``.

    See Also
    --------
    to_json : Return a string representation.
    json.dump : Base function.
    """
    obj = model_to_dict(model, sort=sort)
    obj[u"version"] = JSON_SPEC

    if pretty:
        dump_opts = {
            "indent": 4, "separators": (",", ": "), "sort_keys": True,
            "allow_nan": False}
    else:
        dump_opts = {
            "indent": 0, "separators": (",", ":"), "sort_keys": False,
            "allow_nan": False}
    dump_opts.update(**kwargs)

    if isinstance(filename, string_types):
        with open(filename, "w") as file_handle:
            json.dump(obj, file_handle, **dump_opts)
    else:
        json.dump(obj, filename, **dump_opts)

def
save_json_model
(
model
,
filename
,
sort
=
False
,
pretty
=
False
,
*
*
kwargs
)
:
obj
=
model_to_dict
(
model
,
sort
=
sort
)
obj
[
u"version"
]
=
JSON_SPEC
if
pretty
:
dump_opts
=
{
"indent"
:
4
,
"separators"
:
(
","
,
": "
)
,
"sort_keys"
:
True
,
"allow_nan"
:
False
}
else
:
dump_opts
=
{
"indent"
:
0
,
"separators"
:
(
","
,
":"
)
,
"sort_keys"
:
False
,
"allow_nan"
:
False
}
dump_opts
.
update
(
*
*
kwargs
)
if
isinstance
(
filename
,
string_types
)
:
with
open
(
filename
,
"w"
)
as
file_handle
:
json
.
dump
(
obj
,
file_handle
,
*
*
dump_opts
)
else
:
json
.
dump
(
obj
,
filename
,
*
*
dump_opts
)

Write the cobra model to a file in JSON format .


def load_json_model(filename):
    """
    Load a cobra model from a file in JSON format.

    Parameters
    ----------
    filename : str or file-like
        File path or descriptor that contains the JSON document describing the
        cobra model.

    Returns
    -------
    cobra.Model
        The cobra model as represented in the JSON document.

    See Also
    --------
    from_json : Load from a string.
    """
    if isinstance(filename, string_types):
        with open(filename, "r") as file_handle:
            return model_from_dict(json.load(file_handle))
    else:
        return model_from_dict(json.load(filename))

def load_json_model ( filename ) : if isinstance ( filename , string_types ) : with open ( filename , "r" ) as file_handle : return model_from_dict ( json . load ( file_handle ) ) else : return model_from_dict ( json . load ( filename ) )

Load a cobra model from a file in JSON format .


def add_linear_obj(model):
    """Add a linear version of a minimal medium to the model solver.

    Changes the optimization objective to finding the growth medium requiring
    the smallest total import flux::

        minimize sum |r_i| for r_i in import_reactions

    Arguments
    ---------
    model : cobra.Model
        The model to modify.
    """
    coefs = {}
    for rxn in find_boundary_types(model, "exchange"):
        export = len(rxn.reactants) == 1
        if export:
            coefs[rxn.reverse_variable] = 1
        else:
            coefs[rxn.forward_variable] = 1
    model.objective.set_linear_coefficients(coefs)
    model.objective.direction = "min"

def add_linear_obj ( model ) : coefs = { } for rxn in find_boundary_types ( model , "exchange" ) : export = len ( rxn . reactants ) == 1 if export : coefs [ rxn . reverse_variable ] = 1 else : coefs [ rxn . forward_variable ] = 1 model . objective . set_linear_coefficients ( coefs ) model . objective . direction = "min"

Add a linear version of a minimal medium to the model solver .


def add_mip_obj(model):
    """Add a mixed-integer version of a minimal medium to the model.

    Changes the optimization objective to finding the medium with the least
    components::

        minimize size(R) where R part of import_reactions

    Arguments
    ---------
    model : cobra.model
        The model to modify.
    """
    if len(model.variables) > 1e4:
        LOGGER.warning("the MIP version of minimal media is extremely slow for"
                       " models that large :(")
    exchange_rxns = find_boundary_types(model, "exchange")
    big_m = max(abs(b) for r in exchange_rxns for b in r.bounds)
    prob = model.problem
    coefs = {}
    to_add = []
    for rxn in exchange_rxns:
        export = len(rxn.reactants) == 1
        indicator = prob.Variable("ind_" + rxn.id, lb=0, ub=1, type="binary")
        if export:
            vrv = rxn.reverse_variable
            indicator_const = prob.Constraint(
                vrv - indicator * big_m, ub=0, name="ind_constraint_" + rxn.id)
        else:
            vfw = rxn.forward_variable
            indicator_const = prob.Constraint(
                vfw - indicator * big_m, ub=0, name="ind_constraint_" + rxn.id)
        to_add.extend([indicator, indicator_const])
        coefs[indicator] = 1
    model.add_cons_vars(to_add)
    model.solver.update()
    model.objective.set_linear_coefficients(coefs)
    model.objective.direction = "min"

Add a mixed - integer version of a minimal medium to the model .


def _as_medium(exchanges, tolerance=1e-6, exports=False):
    """Convert a solution to medium.

    Arguments
    ---------
    exchanges : list of cobra.reaction
        The exchange reactions to consider.
    tolerance : positive double
        The absolute tolerance for fluxes. Fluxes with an absolute value
        smaller than this number will be ignored.
    exports : bool
        Whether to return export fluxes as well.

    Returns
    -------
    pandas.Series
        The "medium", meaning all active import fluxes in the solution.
    """
    LOGGER.debug("Formatting medium.")
    medium = pd.Series()
    for rxn in exchanges:
        export = len(rxn.reactants) == 1
        flux = rxn.flux
        if abs(flux) < tolerance:
            continue
        if export:
            medium[rxn.id] = -flux
        elif not export:
            medium[rxn.id] = flux
    if not exports:
        medium = medium[medium > 0]

    return medium

def
_as_medium
(
exchanges
,
tolerance
=
1e-6
,
exports
=
False
)
:
LOGGER
.
debug
(
"Formatting medium."
)
medium
=
pd
.
Series
(
)
for
rxn
in
exchanges
:
export
=
len
(
rxn
.
reactants
)
==
1
flux
=
rxn
.
flux
if
abs
(
flux
)
<
tolerance
:
continue
if
export
:
medium
[
rxn
.
id
]
=
flux
elif
not
export
:
medium
[
rxn
.
id
]
=
flux
if
not
exports
:
medium
=
medium
[
medium
>
0
]
return
medium


def minimal_medium(model, min_objective_value=0.1, exports=False,
                   minimize_components=False, open_exchanges=False):
    """
    Find the minimal growth medium for the model.

    Finds the minimal growth medium for the model which allows for
    model as well as individual growth. Here, a minimal medium can either
    be the medium requiring the smallest total import flux or the medium
    requiring the least components (ergo ingredients), which will be much
    slower due to being a mixed integer problem (MIP).

    Arguments
    ---------
    model : cobra.model
        The model to modify.
    min_objective_value : positive float or array-like object
        The minimum growth rate (objective) that has to be achieved.
    exports : boolean
        Whether to include export fluxes in the returned medium. Defaults to
        False which will only return import fluxes.
    minimize_components : boolean or positive int
        Whether to minimize the number of components instead of the total
        import flux. Might be more intuitive if set to True but may also be
        slow to calculate for large communities. If set to a number `n` will
        return up to `n` alternative solutions all with the same number of
        components.
    open_exchanges : boolean or number
        Whether to ignore currently set bounds and make all exchange reactions
        in the model possible. If set to a number all exchange reactions will
        be opened with (-number, number) as bounds.

    Returns
    -------
    pandas.Series, pandas.DataFrame or None
        A series giving the import flux for each required import
        reaction and (optionally) the associated export fluxes. All exchange
        fluxes are oriented into the import reaction e.g. positive fluxes
        denote imports and negative fluxes exports. If `minimize_components`
        is a number larger 1 may return a DataFrame where each column is a
        minimal medium. Returns None if the minimization is infeasible
        (for instance if min_growth > maximum growth rate).

    Notes
    -----
    Due to numerical issues the `minimize_components` option will usually only
    minimize the number of "large" import fluxes. Specifically, the detection
    limit is given by ``integrality_tolerance * max_bound`` where ``max_bound``
    is the largest bound on an import reaction. Thus, if you are interested
    in small import fluxes as well you may have to adjust the integrality
    tolerance at first with
    `model.solver.configuration.tolerances.integrality = 1e-7` for instance.
    However, this will be *very* slow for large models especially with GLPK.

    """
    exchange_rxns = find_boundary_types(model, "exchange")
    if isinstance(open_exchanges, bool):
        open_bound = 1000
    else:
        open_bound = open_exchanges

    with model as mod:
        if open_exchanges:
            LOGGER.debug("Opening exchanges for %d imports.",
                         len(exchange_rxns))
            for rxn in exchange_rxns:
                rxn.bounds = (-open_bound, open_bound)
        LOGGER.debug("Applying objective value constraints.")
        obj_const = mod.problem.Constraint(
            mod.objective.expression, lb=min_objective_value,
            name="medium_obj_constraint")
        mod.add_cons_vars([obj_const])
        mod.solver.update()
        mod.objective = Zero
        LOGGER.debug("Adding new media objective.")
        tol = mod.solver.configuration.tolerances.feasibility

        if minimize_components:
            add_mip_obj(mod)
            if isinstance(minimize_components, bool):
                minimize_components = 1
            seen = set()
            best = num_components = mod.slim_optimize()
            if mod.solver.status != OPTIMAL:
                LOGGER.warning("Minimization of medium was infeasible.")
                return None
            exclusion = mod.problem.Constraint(Zero, ub=0)
            mod.add_cons_vars([exclusion])
            mod.solver.update()
            media = []
            for i in range(minimize_components):
                LOGGER.info("Finding alternative medium #%d.", (i + 1))
                vars = [mod.variables["ind_" + s] for s in seen]
                if len(seen) > 0:
                    exclusion.set_linear_coefficients(
                        dict.fromkeys(vars, 1))
                    exclusion.ub = best - 1
                num_components = mod.slim_optimize()
                if mod.solver.status != OPTIMAL or num_components > best:
                    break
                medium = _as_medium(exchange_rxns, tol, exports=exports)
                media.append(medium)
                seen.update(medium[medium > 0].index)
            if len(media) > 1:
                medium = pd.concat(media, axis=1, sort=True).fillna(0.0)
                medium.sort_index(axis=1, inplace=True)
            else:
                medium = media[0]
        else:
            add_linear_obj(mod)
            mod.slim_optimize()
            if mod.solver.status != OPTIMAL:
                LOGGER.warning("Minimization of medium was infeasible.")
                return None
            medium = _as_medium(exchange_rxns, tol, exports=exports)

    return medium

Find the minimal growth medium for the model .


def _init_worker(model, loopless, sense):
    """Initialize a global model object for multiprocessing."""
    global _model
    global _loopless
    _model = model
    _model.solver.objective.direction = sense
    _loopless = loopless

def _init_worker ( model , loopless , sense ) : global _model global _loopless _model = model _model . solver . objective . direction = sense _loopless = loopless

Initialize a global model object for multiprocessing .


def flux_variability_analysis(model, reaction_list=None, loopless=False,
                              fraction_of_optimum=1.0, pfba_factor=None,
                              processes=None):
    """
    Determine the minimum and maximum possible flux value for each reaction.

    Parameters
    ----------
    model : cobra.Model
        The model for which to run the analysis. It will *not* be modified.
    reaction_list : list of cobra.Reaction or str, optional
        The reactions for which to obtain min/max fluxes. If None will use
        all reactions in the model (default).
    loopless : boolean, optional
        Whether to return only loopless solutions. This is significantly
        slower. Please also refer to the notes.
    fraction_of_optimum : float, optional
        Must be <= 1.0. Requires that the objective value is at least the
        fraction times maximum objective value. A value of 0.85 for instance
        means that the objective has to be at least at 85% percent of its
        maximum.
    pfba_factor : float, optional
        Add an additional constraint to the model that requires the total sum
        of absolute fluxes must not be larger than this value times the
        smallest possible sum of absolute fluxes, i.e., by setting the value
        to 1.1 the total sum of absolute fluxes must not be more than
        10% larger than the pFBA solution. Since the pFBA solution is the
        one that optimally minimizes the total flux sum, the ``pfba_factor``
        should, if set, be larger than one. Setting this value may lead to
        more realistic predictions of the effective flux bounds.
    processes : int, optional
        The number of parallel processes to run. If not explicitly passed,
        will be set from the global configuration singleton.

    Returns
    -------
    pandas.DataFrame
        A data frame with reaction identifiers as the index and two columns:
        - maximum: indicating the highest possible flux
        - minimum: indicating the lowest possible flux

    Notes
    -----
    This implements the fast version as described in [1]_. Please note that
    the flux distribution containing all minimal/maximal fluxes does not have
    to be a feasible solution for the model. Fluxes are minimized/maximized
    individually and a single minimal flux might require all others to be
    suboptimal.

    Using the loopless option will lead to a significant increase in
    computation time (about a factor of 100 for large models). However, the
    algorithm used here (see [2]_) is still more than 1000x faster than the
    "naive" version using ``add_loopless(model)``. Also note that if you have
    included constraints that force a loop (for instance by setting all fluxes
    in a loop to be non-zero) this loop will be included in the solution.

    References
    ----------
    .. [1] Computationally efficient flux variability analysis.
       Gudmundsson S, Thiele I.
       BMC Bioinformatics. 2010 Sep 29;11:489.
       doi: 10.1186/1471-2105-11-489, PMID: 20920235

    .. [2] CycleFreeFlux: efficient removal of thermodynamically infeasible
       loops from flux distributions.
       Desouki AA, Jarre F, Gelius-Dietrich G, Lercher MJ.
       Bioinformatics. 2015 Jul 1;31(13):2159-65.
       doi: 10.1093/bioinformatics/btv096.
    """
    if reaction_list is None:
        reaction_ids = [r.id for r in model.reactions]
    else:
        reaction_ids = [r.id
                        for r in model.reactions.get_by_any(reaction_list)]

    if processes is None:
        processes = CONFIGURATION.processes
    num_reactions = len(reaction_ids)
    processes = min(processes, num_reactions)

    fva_result = DataFrame({
        "minimum": zeros(num_reactions, dtype=float),
        "maximum": zeros(num_reactions, dtype=float)
    }, index=reaction_ids)
    prob = model.problem
    with model:
        # Safety check before setting up FVA.
        model.slim_optimize(error_value=None,
                            message="There is no optimal solution for the "
                                    "chosen objective!")
        # Add the previous objective as a variable to the model then set it to
        # zero. This also uses the fraction to create the lower/upper bound for
        # the old objective.
        # TODO: Use utility function here (fix_objective_as_constraint)?
        if model.solver.objective.direction == "max":
            fva_old_objective = prob.Variable(
                "fva_old_objective",
                lb=fraction_of_optimum * model.solver.objective.value)
        else:
            fva_old_objective = prob.Variable(
                "fva_old_objective",
                ub=fraction_of_optimum * model.solver.objective.value)
        fva_old_obj_constraint = prob.Constraint(
            model.solver.objective.expression - fva_old_objective, lb=0, ub=0,
            name="fva_old_objective_constraint")
        model.add_cons_vars([fva_old_objective, fva_old_obj_constraint])

        if pfba_factor is not None:
            if pfba_factor < 1.:
                warn("The 'pfba_factor' should be larger or equal to 1.",
                     UserWarning)
            with model:
                add_pfba(model, fraction_of_optimum=0)
                ub = model.slim_optimize(error_value=None)
                flux_sum = prob.Variable("flux_sum", ub=pfba_factor * ub)
                flux_sum_constraint = prob.Constraint(
                    model.solver.objective.expression - flux_sum, lb=0, ub=0,
                    name="flux_sum_constraint")
            model.add_cons_vars([flux_sum, flux_sum_constraint])

        model.objective = Zero  # This will trigger the reset as well
        for what in ("minimum", "maximum"):
            if processes > 1:
                # We create and destroy a new pool here in order to set the
                # objective direction for all reactions. This creates a
                # slight overhead but seems the most clean.
                chunk_size = len(reaction_ids) // processes
                pool = multiprocessing.Pool(
                    processes,
                    initializer=_init_worker,
                    initargs=(model, loopless, what[:3])
                )
                for rxn_id, value in pool.imap_unordered(_fva_step,
                                                         reaction_ids,
                                                         chunksize=chunk_size):
                    fva_result.at[rxn_id, what] = value
                pool.close()
                pool.join()
            else:
                _init_worker(model, loopless, what[:3])
                for rxn_id, value in map(_fva_step, reaction_ids):
                    fva_result.at[rxn_id, what] = value

    return fva_result[["minimum", "maximum"]]

Determine the minimum and maximum possible flux value for each reaction .