예제 #1
0
def mip_score(community, environment=None, min_mass_weight=False, min_growth=1, direction=-1, max_uptake=100, validate=False):
    """
    Implements the metabolic interaction potential (MIP) score as defined in (Zelezniak et al, 2015).

    Args:
        community (Community): microbial community model
        environment (Environment): Metabolic environment in which the SMETANA score is calculated
        direction (int): direction of uptake reactions (negative or positive, default: -1)
        extracellular_id (str): extracellular compartment id
        min_mass_weight (bool): minimize by molecular weight of nutrients (default: False)
        min_growth (float): minimum growth rate (default: 1)
        max_uptake (float): maximum uptake rate (default: 100)
        validate (bool): validate solution using FBA (for debugging purposes, default: False)

    Returns:
        float: MIP score
    """
    # TODO: 1_program_cloneModels.prof
    interacting_community = community.copy(copy_models=False, interacting=True, merge_extracellular_compartments=False, create_biomass=True)
    noninteracting = community.copy(copy_models=False, interacting=False)

    exch_reactions = interacting_community.merged.get_exchange_reactions()

    if environment:
        environment.apply(interacting_community.merged, inplace=True)
        environment.apply(noninteracting.merged, inplace=True)
        exch_reactions = set(exch_reactions) - set(environment)
        
    interacting_medium, sol1 = minimal_medium(interacting_community.merged, direction=direction,
                                             exchange_reactions=exch_reactions,
                                             min_mass_weight=min_mass_weight,
                                             min_growth=min_growth,
                                             max_uptake=max_uptake, validate=validate)

    #
    # Calculate minimal media for non-interacting community
    #
    noninteracting_medium, sol2 = minimal_medium(noninteracting.merged,
                                                 exchange_reactions=exch_reactions,
                                                 direction=direction,
                                                 min_mass_weight=min_mass_weight,
                                                 min_growth=min_growth,
                                                 max_uptake=max_uptake, validate=validate)

    if noninteracting_medium is None:
        score = None
    else:
        score = len(noninteracting_medium) - len(interacting_medium)

    extras = {'noninteracting_medium': noninteracting_medium, 'interacting_medium': interacting_medium,
              'noninteracting_solution': sol2, 'interacting_solution': sol1}

    return score, extras
예제 #2
0
def mro_score(community, environment=None, direction=-1, min_mass_weight=False, min_growth=1, max_uptake=100, validate=False):
    """
    Implements the metabolic resource overlap (MRO) score as defined in (Zelezniak et al, 2015).

    Args:
        community (Community): microbial community model
        environment (Environment): Metabolic environment in which the SMETANA score is colulated
        direction (int): direction of uptake reactions (negative or positive, default: -1)
        extracellular_id (str): extracellular compartment id
        min_mass_weight (bool): minimize by molecular weight of nutrients (default: False)
        min_growth (float): minimum growth rate (default: 1)
        max_uptake (float): maximum uptake rate (default: 100)

    Returns:
        float: MRO score
    """
    # TODO: 1_program_cloneModels.prof
    inter_community = community.copy(copy_models=False, interacting=True, merge_extracellular_compartments=False, create_biomass=False)
    indep_community = inter_community.copy(copy_models=False, interacting=False, create_biomass=True)

    exch_reactions = set(inter_community.merged.get_exchange_reactions()) - set([inter_community.merged.biomass_reaction])
    if environment:
        environment.apply(inter_community.merged, inplace=True)
        environment.apply(indep_community.merged, inplace=True)
        exch_reactions = exch_reactions - set(environment)

    noninteracting_medium, sol = minimal_medium(indep_community.merged,
                                                    exchange_reactions=exch_reactions,
                                                    direction=direction,
                                                    min_mass_weight=min_mass_weight,
                                                    min_growth=min_growth,
                                                    max_uptake=max_uptake, validate=validate)

    solutions = [sol]

    if sol.status != Status.OPTIMAL:
        raise RuntimeError('Failed to find a valid solution')

    # anabiotic environment is limited to non-interacting community minimal media
    noninteracting_exch = set(noninteracting_medium)

    minimal_medium_set = noninteracting_medium | set(environment)
    indep_environment = Environment.from_reactions(minimal_medium_set, max_uptake=max_uptake)
    indep_environment.apply(inter_community.merged, inplace=True)

    individual_media = {}
    for org_id in inter_community.organisms:
        biomass_reaction = inter_community.organisms_biomass_reactions[org_id]
        inter_community.merged.biomass_reaction = biomass_reaction

        org_noninteracting_exch = inter_community.organisms_exchange_reactions[org_id]

        medium, sol = minimal_medium(inter_community.merged,
                                   exchange_reactions=org_noninteracting_exch,
                                   direction=direction,
                                   min_mass_weight=min_mass_weight,
                                   min_growth=min_growth,
                                   max_uptake=max_uptake, validate=validate)
        solutions.append(sol)

        if sol.status != Status.OPTIMAL:
            raise RuntimeError('Failed to find a valid solution')

        individual_media[org_id] = {org_noninteracting_exch[r].original_metabolite for r in medium}


    pairwise = {(o1, o2): individual_media[o1] & individual_media[o2] for o1, o2 in combinations(community.organisms, 2)}

    numerator = len(individual_media) * sum(map(len, pairwise.values()))
    denominator = float(len(pairwise) * sum(map(len, individual_media.values())))

    score = numerator / denominator if denominator != 0 else None
    extras = {'noninteracting_medium': noninteracting_medium, 'individual_media': individual_media, 
              'pairwise': pairwise, 'solutions': solutions}

    return score, extras
예제 #3
0
def metabolite_uptake_score(community, environment, min_mass_weight=True, min_growth=1.0, max_uptake=100.0, abstol=1e-6, validate=False, n_solutions=100):
    """
    Calculate frequency of metabolite requirement for species growth

    Zelezniak A. et al, Metabolic dependencies drive species co-occurrence in diverse microbial communities (PNAS 2015)

    Args:
        community (Community): community object
        environment (Environment): Metabolic environment in which the SMETANA score is colulated
        min_mass_weight: Prefer simpler compounds 
        min_growth (float): minimum growth rate (default: 1)
        max_uptake (float): maximum uptake rate (default: 100)
        abstol (float): tolerance for detecting a non-zero exchange flux (default: 1e-6)
        validate (bool): validate solution using FBA (for debugging purposes, default: False)
        n_solutions (int): How many unique solutions to calculate (default: 100)

    Returns:
        dict: Keys are dependant model names, values are dictionaries with required compounds frequencies 
        dict: Extra information
    """
    interacting_community = community.copy(copy_models=False, interacting=True, create_biomass=False,
                                           merge_extracellular_compartments=False)

    environment.apply(interacting_community.merged, inplace=True)
    rxn2met = {ex.organism_reaction: ex.original_metabolite
               for org_exchanges in interacting_community.organisms_exchange_reactions.itervalues()
               for ex in org_exchanges.itervalues()}

    m_rxns = interacting_community.merged.reactions
    media_metabolites = {met
           for exch_id in interacting_community.merged.get_exchange_reactions()
           for met in interacting_community.merged.reactions[exch_id].stoichiometry
           if exch_id in m_rxns and m_rxns[exch_id].lb < 0}

    solutions = []
    scores = {}
    extras = {'dependencies': {}}
    for org_id, exchange_rxns in community.organisms_exchange_reactions.iteritems():
        biomass_reaction = interacting_community.organisms_biomass_reactions[org_id]
        interacting_community.merged.biomass_reaction = biomass_reaction

        # Remove metabolites present in the medium from the list of uptake candidates
        exchange_rxns = {rxn_id for rxn_id, cnm in exchange_rxns.iteritems()
                         if cnm.extracellular_metabolite not in media_metabolites}

        medium_list, sol = minimal_medium(interacting_community.merged,
                                   exchange_reactions=exchange_rxns,
                                   direction=-1,
                                   min_mass_weight=min_mass_weight,
                                   min_growth=min_growth,
                                   n_solutions=n_solutions,
                                   max_uptake=max_uptake, validate=validate, abstol=abstol)
        solutions.append(sol)

        if medium_list:
            medium_list = map(lambda medium: [rxn2met[rxn_id] for rxn_id in medium], medium_list)
            medium_list_n = float(len(medium_list))
            scores[org_id] = {m: count / medium_list_n for m, count in Counter(chain(*medium_list)).iteritems()}
        else:
            scores[org_id] = {} if sol.status == Status.OPTIMAL else None
        extras['dependencies'][org_id] = medium_list

    return scores, extras
예제 #4
0
def mro_score(community,
              environment=None,
              direction=-1,
              min_mass_weight=False,
              min_growth=0.1,
              max_uptake=10,
              validate=False,
              verbose=True,
              exclude=None):
    """
    Implements the metabolic resource overlap (MRO) score as defined in (Zelezniak et al, 2015).

    Args:
        community (Community): microbial community model
        environment (Environment): Metabolic environment in which the SMETANA score is colulated
        direction (int): direction of uptake reactions (negative or positive, default: -1)
        extracellular_id (str): extracellular compartment id
        min_mass_weight (bool): minimize by molecular weight of nutrients (default: False)
        min_growth (float): minimum growth rate (default: 0.1)
        max_uptake (float): maximum uptake rate (default: 10)

    Returns:
        float: MRO score
    """

    noninteracting = community.copy(copy_models=False,
                                    interacting=False,
                                    create_biomass=True)
    exch_reactions = set(community.merged.get_exchange_reactions())

    if environment:
        environment.apply(community.merged, inplace=True, warning=False)
        environment.apply(noninteracting.merged, inplace=True, warning=False)
        exch_reactions &= set(environment)

    noninteracting_medium, sol = minimal_medium(
        noninteracting.merged,
        exchange_reactions=exch_reactions,
        direction=direction,
        min_mass_weight=min_mass_weight,
        min_growth=min_growth,
        max_uptake=max_uptake,
        validate=validate,
        warnings=verbose)

    solutions = [sol]

    if sol.status != Status.OPTIMAL:
        if verbose:
            warn(
                'MRO: Failed to find a valid solution for non-interacting community'
            )
        return None, None

    # anabiotic environment is limited to non-interacting community minimal media
    noninteracting_exch = set(noninteracting_medium)
    noninteracting_env = Environment.from_reactions(noninteracting_exch,
                                                    max_uptake=max_uptake)
    noninteracting_env.apply(community.merged, inplace=True)

    individual_media = {}

    if exclude is not None:
        exclude = {'M_{}_e'.format(x) for x in exclude}
    else:
        exclude = {}

    solver = solver_instance(community.merged)
    for org_id in community.organisms:
        biomass_reaction = community.organisms_biomass_reactions[org_id]
        community.merged.biomass_reaction = biomass_reaction

        org_noninteracting_exch = community.organisms_exchange_reactions[
            org_id]

        medium, sol = minimal_medium(
            community.merged,
            exchange_reactions=org_noninteracting_exch,
            direction=direction,
            min_mass_weight=min_mass_weight,
            min_growth=min_growth,
            max_uptake=max_uptake,
            validate=validate,
            solver=solver,
            warnings=verbose)
        solutions.append(sol)

        if sol.status != Status.OPTIMAL:
            warn('MRO: Failed to find a valid solution for: ' + org_id)
            return None, None

        individual_media[org_id] = {
            org_noninteracting_exch[r].original_metabolite
            for r in medium
        } - exclude

    pairwise = {(o1, o2): individual_media[o1] & individual_media[o2]
                for o1, o2 in combinations(community.organisms, 2)}

    numerator = len(individual_media) * sum(map(len, pairwise.values()))
    denominator = float(
        len(pairwise) * sum(map(len, individual_media.values())))

    score = numerator / denominator if denominator != 0 else None
    extras = {
        'noninteracting_medium': noninteracting_medium,
        'individual_media': individual_media,
        'pairwise': pairwise,
        'solutions': solutions
    }

    return score, extras
예제 #5
0
def mip_score(community,
              environment=None,
              min_mass_weight=False,
              min_growth=0.1,
              direction=-1,
              max_uptake=10,
              validate=False,
              verbose=True,
              exclude=None):
    """
    Implements the metabolic interaction potential (MIP) score as defined in (Zelezniak et al, 2015).

    Args:
        community (Community): microbial community model
        environment (Environment): Metabolic environment in which the SMETANA score is calculated
        direction (int): direction of uptake reactions (negative or positive, default: -1)
        extracellular_id (str): extracellular compartment id
        min_mass_weight (bool): minimize by molecular weight of nutrients (default: False)
        min_growth (float): minimum growth rate (default: 0.1)
        max_uptake (float): maximum uptake rate (default: 10)
        validate (bool): validate solution using FBA (for debugging purposes, default: False)

    Returns:
        float: MIP score
    """

    noninteracting = community.copy(copy_models=False, interacting=False)
    exch_reactions = set(community.merged.get_exchange_reactions())

    if environment:
        environment.apply(community.merged, inplace=True, warning=False)
        environment.apply(noninteracting.merged, inplace=True, warning=False)
        exch_reactions &= set(environment)

    interacting_medium, sol1 = minimal_medium(
        community.merged,
        direction=direction,
        exchange_reactions=exch_reactions,
        min_mass_weight=min_mass_weight,
        min_growth=min_growth,
        max_uptake=max_uptake,
        validate=validate,
        warnings=verbose)

    noninteracting_medium, sol2 = minimal_medium(
        noninteracting.merged,
        exchange_reactions=exch_reactions,
        direction=direction,
        min_mass_weight=min_mass_weight,
        min_growth=min_growth,
        max_uptake=max_uptake,
        validate=validate,
        warnings=verbose)

    if noninteracting_medium is None:
        if verbose:
            warn(
                'MIP: Failed to find a valid solution for non-interacting community'
            )
        return None, None
    else:

        if exclude is not None:
            exclude_rxns = {'R_EX_M_{}_e_pool'.format(x) for x in exclude}
            interacting_medium = set(interacting_medium) - exclude_rxns
            noninteracting_medium = set(noninteracting_medium) - exclude_rxns

        score = len(noninteracting_medium) - len(interacting_medium)

    extras = {
        'noninteracting_medium': noninteracting_medium,
        'interacting_medium': interacting_medium,
        'noninteracting_solution': sol2,
        'interacting_solution': sol1
    }

    return score, extras
예제 #6
0
def metabolite_uptake_score(community,
                            environment=None,
                            min_mass_weight=False,
                            min_growth=0.1,
                            max_uptake=10.0,
                            abstol=1e-6,
                            validate=False,
                            n_solutions=100,
                            pool_gap=0.5,
                            verbose=True,
                            exclude=None):  #TODO: implement excluded
    """
    Calculate frequency of metabolite requirement for species growth

    Zelezniak A. et al, Metabolic dependencies drive species co-occurrence in diverse microbial communities (PNAS 2015)

    Args:
        community (Community): microbial community
        environment (Environment): metabolic environment
        min_mass_weight (bool): Prefer smaller compounds (default: False)
        min_growth (float): minimum growth rate (default: 0.1)
        max_uptake (float): maximum uptake rate (default: 10)
        abstol (float): tolerance for detecting a non-zero exchange flux (default: 1e-6)
        validate (bool): validate solution using FBA (for debugging purposes, default: False)
        n_solutions (int): number of alternative solutions to calculate (default: 100)

    Returns:
        dict: Keys are organism names, values are dictionaries with metabolite frequencies 
        dict: Extra information
    """

    if environment:
        environment.apply(community.merged, inplace=True, warning=False)

    scores = {}

    solver = solver_instance(community.merged)

    for org_id, exchange_rxns in community.organisms_exchange_reactions.items(
    ):
        biomass_reaction = community.organisms_biomass_reactions[org_id]
        community.merged.biomass_reaction = biomass_reaction

        medium_list, sols = minimal_medium(
            community.merged,
            exchange_reactions=exchange_rxns.keys(),
            min_mass_weight=min_mass_weight,
            min_growth=min_growth,
            n_solutions=n_solutions,
            max_uptake=max_uptake,
            validate=validate,
            abstol=abstol,
            use_pool=True,
            pool_gap=pool_gap,
            solver=solver,
            warnings=verbose)

        if medium_list:
            counter = Counter(chain(*medium_list))
            scores[org_id] = {
                cnm.original_metabolite: counter[ex] / float(len(medium_list))
                for ex, cnm in exchange_rxns.items()
            }
        else:
            if verbose:
                warn('MUS: Failed to find a minimal growth medium for ' +
                     org_id)
            scores[org_id] = None

    return scores