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
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
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
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
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
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