예제 #1
0
def crossover(community, sol, fluxes=False, pfba=False):
    """Get the crossover solution."""
    gcs = sol.members.growth_rate.drop("medium")
    com_growth = sol.growth_rate
    logger.info("Starting crossover...")
    with community as com:
        logger.info("constraining growth rates.")
        context = get_context(community)
        if context is not None:
            context(partial(reset_min_community_growth, com))
        reset_min_community_growth(com)
        com.variables.community_objective.lb = 0.0
        com.variables.community_objective.ub = com_growth + 1e-6
        com.objective = 1000.0 * com.variables.community_objective
        for sp in com.species:
            const = com.constraints["objective_" + sp]
            const.ub = gcs[sp]
        logger.info("finding closest feasible solution")
        s = com.optimize()
        if s is None:
            reset_solver(com)
            s = com.optimize()
        if s is not None:
            s = CommunitySolution(com, slim=not fluxes)
        for sp in com.species:
            com.constraints["objective_" + sp].ub = None
    if s is None:
        raise OptimizationError("crossover could not converge (status = %s)." %
                                community.solver.status)
    s.objective_value /= 1000.0
    return s
예제 #2
0
def elasticities(com, fraction=0.5, reactions=None, progress=True):
    """Calculate elasticities for reactions.

    Calculates elasticity coefficients using the specified reactions as
    response and exchange bounds (diet) and taxa abundances as
    effectors/parameters. Will use an arbitrary flux distribution as base.

    Arguments
    ---------
    com : micom.Community
        The community for wrhich to calculate elasticities.
    fraction : double
        The tradeoff to use for the cooperative tradeoff method. Fraction of
        maximal community growth to enforce.
    reactions : iterable
        A list of reactions to get elasticities for. Elements can either be
        reactions from the model, strings specifying the ids of reactions
        or ints specifying the indices of reactions. Defaults to using all
        reactions.
    progress : boolean
        Whether to shwo progress bars. Will show two, one for the diet
        optimizations and another one for the taxa abundances.

    Returns
    -------
    pandas.DataFrame
        A data frame with the following columns:
        "reaction" - the exchange reaction (response),
        "taxon" - the taxon the reaction is from,
        "effector" - the parameter that was changed,
        "direction" - whether the flux runs in the forward or reverse
            direction,
        "elasticity" - the elasticity coefficient,
        "type" - the type of effector either "exchange" for diet or "abundance"
        for taxa abundances.
    """
    growth_rate = None
    if reactions is None:
        reactions = com.reactions
    reactions = com.reactions.get_by_any(reactions)
    with com:
        context = get_context(com)
        context(partial(reset_min_community_growth, com))
        by_medium = elasticities_by_medium(
            com, reactions, fraction, growth_rate, progress
        )
        by_medium["type"] = "exchanges"

        by_abundance = elasticities_by_abundance(
            com, reactions, fraction, growth_rate, progress
        )
        by_abundance["type"] = "abundance"

    both = pd.concat([by_medium, by_abundance]).reset_index(drop=True)
    both.loc[both.taxon == "m", "taxon"] = "medium"
    return both
예제 #3
0
def knock_out_metabolite(metabolite, force_steady_state=False):
    """'Knockout' a metabolite. This can be done in 2 ways:

    1. Implementation follows the description in [1] "All fluxes around
    the metabolite M should be restricted to only produce the
    metabolite, for which balancing constraint of mass conservation is
    relaxed to allow nonzero values of the incoming fluxes whereas all
    outgoing fluxes are limited to zero."

    2. Force steady state All reactions consuming the metabolite are
    restricted to only produce the metabolite. A demand reaction is
    added to sink the metabolite produced to keep the problem feasible
    under the S.v = 0 constraint.


    Knocking out a metabolite overrules the constraints set on the
    reactions producing the metabolite.

    Parameters
    ----------
    force_steady_state: bool
        If True, uses approach 2.

    References
    ----------
    .. [1] Kim, P.-J., Lee, D.-Y., Kim, T. Y., Lee, K. H., Jeong, H.,
    Lee, S. Y., & Park, S. (2007). Metabolite essentiality elucidates
    robustness of Escherichia coli metabolism. PNAS, 104(34), 13638-13642

    """
    # restrict reactions to produce metabolite
    for rxn in metabolite.reactions:
        if rxn.metabolites[metabolite] > 0:
            rxn.bounds = (0, 0) if rxn.upper_bound < 0 \
                else (0, rxn.upper_bound)
        elif rxn.metabolites[metabolite] < 0:
            rxn.bounds = (0, 0) if rxn.lower_bound > 0 \
                else (rxn.lower_bound, 0)
    if force_steady_state:
        metabolite._model.add_boundary(metabolite,
                                       type="knock-out",
                                       lb=0,
                                       ub=1000,
                                       reaction_id="KO_{}".format(
                                           metabolite.id))
    else:
        previous_bounds = metabolite.constraint.lb, metabolite.constraint.ub
        metabolite.constraint.lb, metabolite.constraint.ub = -1000, 1000
        context = get_context(metabolite)
        if context:

            def reset():
                metabolite.constraint.lb, metabolite.constraint.ub = previous_bounds

            context(reset)
예제 #4
0
def test_get_context(model: "Model") -> None:
    """Test if context retrieval is working."""
    with model as model:
        # reverse optimization direcion
        model.objective_direction = "min"
        # retrieve context
        context = get_context(model)
        # check size of the context
        if context:
            assert context.size() == 1

    # there shouldn't be any history
    if context:
        assert context.size() == 0
예제 #5
0
def exchange_elasticities(com, fraction=1.0, progress=True):
    """Calculate elasticities for exchange reactions.

    Calculates elasticity coefficients using the exchange reactions as
    response and exchange bounds (diet) and taxa abundances as
    effectors/parameters. Will use an arbitrary flux distribution as base.

    Arguments
    ---------
    com : micom.Community
        The community for wrhich to calculate elasticities.
    fraction : double
        The tradeoff to use for the cooperative tradeoff method. Fraction of
        maximal community growth to enforce.
    progress : boolean
        Whether to shwo progress bars. Will show two, one for the diet
        optimizations and another one for the taxa abundances.

    Returns
    -------
    pandas.DataFrame
        A data frame with the following columns:
        "reaction" - the exchange reaction (response),
        "effector" - the parameter that was changed,
        "direction" - whether the flux runs in the forward od reverse direction,
        "elasticity" - the elasticity coefficient,
        "type" - the type of effector either "exchange" for diet or "abundance"
        for taxa abundances.
    """
    growth_rate = None
    with com:
        context = get_context(com)
        context(partial(reset_min_community_growth, com))
        rxns = com.exchanges
        by_medium = elasticities_by_medium(com, rxns, fraction, growth_rate,
                                           progress)
        by_medium["type"] = "exchanges"

        by_abundance = elasticities_by_abundance(com, rxns, fraction,
                                                 growth_rate, progress)
        by_abundance["type"] = "abundance"

    return pd.concat([by_medium, by_abundance])
예제 #6
0
파일: media.py 프로젝트: Gibbons-Lab/micom
def minimal_medium(
    community,
    community_growth,
    exchanges=None,
    min_growth=0.0,
    exports=False,
    minimize_components=False,
    open_exchanges=False,
    solution=False,
):
    """Find the minimal growth medium for the community.

    Finds the minimal growth medium for the community which allows for
    community 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).

    Arguments
    ---------
    community : micom.Community
        The community to modify.
    community_growth : positive float
        The minimum community-wide growth rate.
    exchanges : list of cobra.Reactions
        The list of exchange reactions that are penalized.
    min_growth : positive float or array-like object.
        The minimum growth rate for each individual in the community. Either
        a single value applied to all individuals or one value for each.
    exports : boolean
        Whether to include export fluxes in the returned medium. Defaults to
        False which will only return import fluxes.
    minimize_components : boolean
        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.
    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.
    solution : boolean
        Whether to also return the entire solution and all fluxes for the
        minimal medium.


    Returns
    -------
    pandas.Series or dict
        A series {rid: flux} giving the import flux for each required import
        reaction. If `solution` is True retuns a dictionary
        {"medium": panas.Series, "solution": micom.CommunitySolution}.

    """
    logger.info("calculating minimal medium for %s" % community.id)
    boundary_rxns = community.exchanges
    if isinstance(open_exchanges, bool):
        open_bound = 1000
    else:
        open_bound = open_exchanges
    min_growth = _format_min_growth(min_growth, community.species)
    with community as com:
        if open_exchanges:
            logger.info("opening exchanges for %d imports" %
                        len(boundary_rxns))
            for rxn in boundary_rxns:
                rxn.bounds = (-open_bound, open_bound)
        logger.info("applying growth rate constraints")
        context = get_context(community)
        if context is not None:
            context(partial(reset_min_community_growth, com))
            com.variables.community_objective.lb = community_growth
        _apply_min_growth(community, min_growth)
        com.objective = Zero
        logger.info("adding new media objective")
        if minimize_components:
            add_mip_obj(com, boundary_rxns)
        else:
            add_linear_obj(com, boundary_rxns)
        sol = com.optimize(fluxes=True, pfba=False)
        if sol is None:
            logger.warning("minimization of medium was unsuccessful")
            return None

        logger.info("formatting medium")
        medium = pd.Series()
        tol = community.solver.configuration.tolerances.feasibility
        for rxn in boundary_rxns:
            export = len(rxn.reactants) == 1
            flux = sol.fluxes.loc["medium", rxn.id]
            if abs(flux) < tol:
                continue
            if export:
                medium[rxn.id] = -flux
            elif not export:
                medium[rxn.id] = flux
        if not exports:
            medium = medium[medium > 0]

    if solution:
        return {"medium": medium, "solution": sol}
    else:
        return medium