def find_abc_tag_transporter(model): """ Find Atp-binding cassette transport rxns without 'abc' tag. Parameters ---------- model : cobra.Model A cobrapy metabolic model Notes ----- An ABC transport reaction is defined as follows: 1. It contains metabolites from at least 2 compartments, 2. at least 1 metabolite undergoes no chemical reaction, i.e., the formula stays the same on both sides of the equation, and 3. ATP is converted to ADP (+ Pi + H, yet this isn't checked for explicitly). Reactions that only transport protons ('H') across the membrane are excluded, as well as reactions with redox cofactors whose formula is either 'X' or 'XH2' """ transport_rxns = helpers.find_transport_reactions(model) atp_adp_rxns = helpers.find_converting_reactions(model, ["atp", "adp"]) gtp_gdp_rxns = helpers.find_converting_reactions(model, ["gtp", "gdp"]) ctp_cdp_rxns = helpers.find_converting_reactions(model, ["ctp", "cdp"]) energy_requiring = set().union(atp_adp_rxns, gtp_gdp_rxns, ctp_cdp_rxns) abc_transporters = set(transport_rxns).intersection(energy_requiring) return [ rxn for rxn in abc_transporters if not re.match("[A-Z0-9]+\w*?abc\w*?", rxn.id) ]
def test_find_constrained_transport_reactions(model, num): """Expect num of contrained transport rxns to be identified correctly.""" transporters = helpers.find_transport_reactions(model) constrained_transporters = set( [rxn for rxn in transporters if basic.is_constrained_reaction( model, rxn)]) assert len(constrained_transporters) == num
def test_transport_reaction_gpr_presence(model): """ Expect a small fraction of transport reactions not to have a GPR rule. As it is hard to identify the exact transport processes within a cell, transport reactions are often added purely for modeling purposes. Highlighting where assumptions have been made versus where there is proof may help direct the efforts to improve transport and transport energetics of the tested metabolic model. However, transport reactions without GPR may also be valid: Diffusion, or known reactions with yet undiscovered genes likely lack GPR. Implementation: Check which cobra.Reactions classified as transport reactions have a non-empty "gene_reaction_rule" attribute. """ # TODO: Update threshold with improved insight from meta study. ann = test_transport_reaction_gpr_presence.annotation ann["data"] = get_ids(basic.check_transport_reaction_gpr_presence(model)) ann["metric"] = len(ann["data"]) / len( helpers.find_transport_reactions(model)) ann["message"] = wrapper.fill( """There are a total of {} transport reactions ({:.2%} of all transport reactions) without GPR: {}""".format(len(ann["data"]), ann["metric"], truncate(ann["data"]))) assert ann["metric"] < 0.2, ann["message"]
def test_transport_reaction_presence(read_only_model, store): """Expect >= 1 transport reactions are present in the model.""" store["transporters"] = [ rxn.id for rxn in helpers.find_transport_reactions(read_only_model) ] store["num_transporters"] = len(store["transporters"]) assert store["num_transporters"] >= 1
def test_find_constrained_transport_reactions(model): """ Expect zero or more transport reactions to have fixed constraints. Cellular metabolism in any organism usually involves the transport of metabolites across a lipid bi-layer. Hence, this test reports how many of these reactions, which transports metabolites from one compartment to another, have fixed constraints. This test does not have any mandatory 'pass' criteria. Implementation: Please refer to "Transport Reactions" for details on how memote identifies transport reactions. From the pool of transport reactions identify reactions which are constrained to values other than the model's median lower and upper bounds. """ ann = test_find_constrained_transport_reactions.annotation transporters = helpers.find_transport_reactions(model) ann["data"] = get_ids_and_bounds([ rxn for rxn in transporters if basic.is_constrained_reaction(model, rxn) ]) ann["metric"] = len(ann["data"]) / len(transporters) ann["message"] = wrapper.fill( """A total of {:d} ({:.2%}) transport reactions have fixed constraints in the model: {}""".format(len(ann["data"]), ann["metric"], truncate(ann["data"])))
def test_find_constrained_transport_reactions(model): """ Expect zero or more transport reactions to have fixed constraints. Cellular metabolism in any organism usually involves the transport of metabolites across a lipid bi-layer. Hence, this test reports how many of these reactions, which transports metabolites from one compartment to another, have fixed constraints. This test does not have any mandatory 'pass' criteria. Implementation: Please refer to "Transport Reactions" for details on how memote identifies transport reactions. From the pool of transport reactions identify reactions which are constrained to values other than the model's median lower and upper bounds. """ ann = test_find_constrained_transport_reactions.annotation transporters = helpers.find_transport_reactions(model) ann["data"] = get_ids_and_bounds( [rxn for rxn in transporters if basic.is_constrained_reaction( model, rxn)]) ann["metric"] = len(ann["data"]) / len(transporters) ann["message"] = wrapper.fill( """A total of {:d} ({:.2%}) transport reactions have fixed constraints in the model: {}""".format(len(ann["data"]), ann["metric"], truncate(ann["data"])))
def find_direct_metabolites(model, reaction): """ Return list of possible direct biomass precursor metabolites. Parameters ---------- model : cobra.Model The metabolic model under investigation. reaction : cobra.core.reaction.Reaction The biomass reaction of the model under investigation. Returns ------- list Metabolites that qualify as direct metabolites i.e. biomass precursors that are taken up to be consumed by the biomass reaction only. """ transport_reactions = set(helpers.find_transport_reactions(model)) exchange_reactions = set(model.exchanges) biomass_reactions = set(helpers.find_biomass_reaction(model)) combined_set = transport_reactions | exchange_reactions | biomass_reactions precursors = find_biomass_precursors(reaction) return [met for met in precursors if met.reactions.issubset(combined_set)]
def test_transport_reaction_specific_sbo_presence(read_only_model): """Expect all transport reactions to be annotated properly. 'SBO:0000185', 'SBO:0000588', 'SBO:0000587', 'SBO:0000655', 'SBO:0000654', 'SBO:0000660', 'SBO:0000659', 'SBO:0000657', and 'SBO:0000658' represent the terms 'transport reaction' and 'translocation reaction', in addition to their children (more specific transport reaction labels). Every transport reaction that is not a pure metabolic or boundary reaction should be annotated with one of these terms. The results shown are relative to the total of all transport reactions. """ sbo_transport_terms = helpers.TRANSPORT_RXN_SBO_TERMS ann = test_transport_reaction_specific_sbo_presence.annotation transports = helpers.find_transport_reactions(read_only_model) ann["data"] = get_ids(sbo.check_component_for_specific_sbo_term( transports, sbo_transport_terms)) try: ann["metric"] = len(ann["data"]) / len(transports) ann["message"] = wrapper.fill( """A total of {} metabolic reactions ({:.2%} of all transport reactions) lack annotation with one of the SBO terms: {} for 'biochemical reaction': {}""".format( len(ann["data"]), ann["metric"], sbo_transport_terms, truncate(ann["data"]))) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no transport reactions." pytest.skip(ann["message"]) assert len(ann["data"]) == len(transports), ann["message"]
def test_transport_reaction_gpr_presence(model): """ Expect a small fraction of transport reactions not to have a GPR rule. As it is hard to identify the exact transport processes within a cell, transport reactions are often added purely for modeling purposes. Highlighting where assumptions have been made versus where there is proof may help direct the efforts to improve transport and transport energetics of the tested metabolic model. However, transport reactions without GPR may also be valid: Diffusion, or known reactions with yet undiscovered genes likely lack GPR. Implementation: Check which cobra.Reactions classified as transport reactions have a non-empty "gene_reaction_rule" attribute. """ # TODO: Update threshold with improved insight from meta study. ann = test_transport_reaction_gpr_presence.annotation ann["data"] = get_ids( basic.check_transport_reaction_gpr_presence(model) ) ann["metric"] = len(ann["data"]) / len( helpers.find_transport_reactions(model) ) ann["message"] = wrapper.fill( """There are a total of {} transport reactions ({:.2%} of all transport reactions) without GPR: {}""".format(len(ann["data"]), ann["metric"], truncate(ann["data"]))) assert ann["metric"] < 0.2, ann["message"]
def test_transport_reaction_specific_sbo_presence(model): """Expect all transport reactions to be annotated properly. 'SBO:0000185', 'SBO:0000588', 'SBO:0000587', 'SBO:0000655', 'SBO:0000654', 'SBO:0000660', 'SBO:0000659', 'SBO:0000657', and 'SBO:0000658' represent the terms 'transport reaction' and 'translocation reaction', in addition to their children (more specific transport reaction labels). Every transport reaction that is not a pure metabolic or boundary reaction should be annotated with one of these terms. The results shown are relative to the total of all transport reactions. Implementation: Check if each transport reaction has a non-zero "annotation" attribute that contains the key "sbo" with the associated value being one of the SBO terms above. """ sbo_transport_terms = helpers.TRANSPORT_RXN_SBO_TERMS ann = test_transport_reaction_specific_sbo_presence.annotation transports = helpers.find_transport_reactions(model) ann["data"] = get_ids(sbo.check_component_for_specific_sbo_term( transports, sbo_transport_terms)) try: ann["metric"] = len(ann["data"]) / len(transports) ann["message"] = wrapper.fill( """A total of {} metabolic reactions ({:.2%} of all transport reactions) lack annotation with one of the SBO terms: {} for 'biochemical reaction': {}""".format( len(ann["data"]), ann["metric"], sbo_transport_terms, truncate(ann["data"]))) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no transport reactions." pytest.skip(ann["message"]) assert len(ann["data"]) == len(transports), ann["message"]
def test_transport_reaction_specific_sbo_presence(read_only_model): """Expect all transport reactions to be annotated with SBO:0000185. SBO:0000185 represents the term 'transport reaction'. Every transport reaction that is not a pure metabolic or boundary reaction should be annotated with this. The results shown are relative to the total of all transport reactions. """ ann = test_transport_reaction_specific_sbo_presence.annotation transports = helpers.find_transport_reactions(read_only_model) ann["data"] = get_ids( sbo.check_component_for_specific_sbo_term(transports, "SBO:0000185")) try: ann["metric"] = len(ann["data"]) / len(transports) ann["message"] = wrapper.fill( """A total of {} metabolic reactions ({:.2%} of all transport reactions) lack annotation with the SBO term "SBO:0000185" for 'biochemical reaction': {}""".format(len(ann["data"]), ann["metric"], truncate(ann["data"]))) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no transport reactions." pytest.skip(ann["message"]) assert len(ann["data"]) == len(transports), ann["message"]
def test_find_transport_reactions(read_only_model): """Expect >= 1 transport reactions are present in the read_only_model.""" ann = test_find_transport_reactions.annotation ann["data"] = get_ids(helpers.find_transport_reactions(read_only_model)) ann["metric"] = len(ann["data"]) / len(read_only_model.reactions) ann["message"] = wrapper.fill( """A total of {:d} ({:.2%}) transport reactions are defined in the model, this excludes purely metabolic reactions, exchanges, or pseudo-reactions: {}""".format(len(ann["data"]), ann["metric"], truncate(ann["data"]))) assert len(ann["data"]) >= 1, ann["message"]
def find_pure_metabolic_reactions(model): """ Return reactions that are neither transporters, exchanges, nor pseudo. Parameters ---------- model : cobra.Model The metabolic model under investigation. """ exchanges = set(model.exchanges) transporters = set(helpers.find_transport_reactions(model)) biomass = set(helpers.find_biomass_reaction(model)) return set(model.reactions) - (exchanges | transporters | biomass)
def test_find_transport_reactions(model): """ Expect >= 1 transport reactions are present in the model. Cellular metabolism in any organism usually involves the transport of metabolites across a lipid bi-layer. This test reports how many of these reactions, which transports metabolites from one compartment to another, are present in the model, as at least one transport reaction must be present for cells to take up nutrients and/or excrete waste. Implementation: A transport reaction is defined as follows: 1. It contains metabolites from at least 2 compartments and 2. at least 1 metabolite undergoes no chemical reaction, i.e., the formula and/or annotation stays the same on both sides of the equation. A notable exception is transport via PTS, which also contains the following restriction: 3. The transported metabolite(s) are transported into a compartment through the exchange of a phosphate. An example of transport via PTS would be pep(c) + glucose(e) -> glucose-6-phosphate(c) + pyr(c) Reactions similar to transport via PTS (referred to as "modified transport reactions") follow a similar pattern: A(x) + B-R(y) -> A-R(y) + B(y) Such modified transport reactions can be detected, but only when the formula is defined for all metabolites in a particular reaction. If this is not the case, transport reactions are identified through annotations, which cannot detect modified transport reactions. """ ann = test_find_transport_reactions.annotation ann["data"] = get_ids(helpers.find_transport_reactions(model)) ann["metric"] = len(ann["data"]) / len(model.reactions) ann["message"] = wrapper.fill( """A total of {:d} ({:.2%}) transport reactions are defined in the model, this excludes purely metabolic reactions, exchanges, or pseudo-reactions: {}""".format(len(ann["data"]), ann["metric"], truncate(ann["data"]))) assert len(ann["data"]) >= 1, ann["message"]
def test_find_constrained_transport_reactions(read_only_model): """ Expect zero or more transport reactions to have fixed constraints. Cellular metabolism in any organism usually involves the transport of metabolites across a lipid bi-layer. Hence, this test reports how many of these reactions, which transports metabolites from one compartment to another, have fixed constraints. This test does not have any mandatory 'pass' criteria. A transport reaction is defined as follows: 1. It contains metabolites from at least 2 compartments and 2. at least 1 metabolite undergoes no chemical reaction, i.e., the formula and/or annotation stays the same on both sides of the equation. A notable exception is transport via PTS, which also contains the following restriction: 3. The transported metabolite(s) are transported into a compartment through the exchange of a phosphate. An example of transport via PTS would be pep(c) + glucose(e) -> glucose-6-phosphate(c) + pyr(c) Reactions similar to transport via PTS (referred to as "modified transport reactions") follow a similar pattern: A(x) + B-R(y) -> A-R(y) + B(y) Such modified transport reactions can be detected, but only when a formula field exists for all metabolites in a particular reaction. If this is not the case, transport reactions are identified through annotations, which cannot detect modified transport reactions. """ ann = test_find_constrained_transport_reactions.annotation transporters = helpers.find_transport_reactions(read_only_model) ann["data"] = get_ids_and_bounds( [rxn for rxn in transporters if basic.is_constrained_reaction( read_only_model, rxn)]) ann["metric"] = len(ann["data"]) / len(transporters) ann["message"] = wrapper.fill( """A total of {:d} ({:.2%}) transport reactions have fixed constraints in the model: {}""".format(len(ann["data"]), ann["metric"], truncate(ann["data"])))
def test_find_transport_reactions(model): """ Expect >= 1 transport reactions are present in the model. Cellular metabolism in any organism usually involves the transport of metabolites across a lipid bi-layer. This test reports how many of these reactions, which transports metabolites from one compartment to another, are present in the model, as at least one transport reaction must be present for cells to take up nutrients and/or excrete waste. Implementation: A transport reaction is defined as follows: 1. It contains metabolites from at least 2 compartments and 2. at least 1 metabolite undergoes no chemical reaction, i.e., the formula and/or annotation stays the same on both sides of the equation. A notable exception is transport via PTS, which also contains the following restriction: 3. The transported metabolite(s) are transported into a compartment through the exchange of a phosphate. An example of transport via PTS would be pep(c) + glucose(e) -> glucose-6-phosphate(c) + pyr(c) Reactions similar to transport via PTS (referred to as "modified transport reactions") follow a similar pattern: A(x) + B-R(y) -> A-R(y) + B(y) Such modified transport reactions can be detected, but only when the formula is defined for all metabolites in a particular reaction. If this is not the case, transport reactions are identified through annotations, which cannot detect modified transport reactions. """ ann = test_find_transport_reactions.annotation ann["data"] = get_ids(helpers.find_transport_reactions(model)) ann["metric"] = len(ann["data"]) / len(model.reactions) ann["message"] = wrapper.fill( """A total of {:d} ({:.2%}) transport reactions are defined in the model, this excludes purely metabolic reactions, exchanges, or pseudo-reactions: {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]))) assert len(ann["data"]) >= 1, ann["message"]
def find_reaction_tag_transporter(model): """ Return incorrectly tagged transport reactions. Make an exception for the ATP synthase reaction (ATPS) which a unique case for a transport reaction and thus does not get the tag. Parameters ---------- model : cobra.Model A cobrapy metabolic model Notes ----- A transport reaction is defined as follows: 1. It contains metabolites from at least 2 compartments and 2. at least 1 metabolite undergoes no chemical reaction, i.e., the formula stays the same on both sides of the equation. Reactions that only transport protons ('H') across the membrane are excluded, as well as reactions with redox cofactors whose formula is either 'X' or 'XH2' """ transport_rxns = helpers.find_transport_reactions(model) atp_adp_rxns = helpers.find_converting_reactions(model, ("MNXM3", "MNXM7")) gtp_gdp_rxns = helpers.find_converting_reactions(model, ("MNXM51", "MNXM30")) ctp_cdp_rxns = helpers.find_converting_reactions(model, ["MNXM63", "MNXM220"]) energy_requiring = set().union(atp_adp_rxns, gtp_gdp_rxns, ctp_cdp_rxns) non_abc_transporters = set(transport_rxns).difference(energy_requiring) return [ rxn for rxn in non_abc_transporters if not re.match("[A-Z0-9]+\w*?t\w*?", rxn.id) if not rxn.id.startswith('ATPS') ]
def find_rxn_id_suffix_compartment(model, suffix): """ Find mis-tagged non-transport reactions. Find non-transport reactions whose ID bear a compartment tag but which do not contain any metabolites in the given compartment. Parameters ---------- model : cobra.Model A cobrapy metabolic model. suffix : str The suffix of the compartment to be checked. Returns ------- list Non-transport reactions that have at least one metabolite in the compartment given by `suffix` but whose IDs do not have the `suffix` appended. """ transport_rxns = set(helpers.find_transport_reactions(model)) exchange_demand_rxns = set(model.exchanges) comp_pattern = re.compile("[A-Z0-9]+\w*?{}\w*?".format(SUFFIX_MAP[suffix])) rxns = [] for rxn in model.reactions: if comp_pattern.match(rxn.id): if ('biomass' not in rxn.id.lower()) and ( rxn not in transport_rxns and rxn not in exchange_demand_rxns): rxns.append(rxn) return [rxn for rxn in rxns if suffix not in rxn.compartments]
def test_transport_reaction_presence(read_only_model): """ Expect more than one transport reaction to be defined in the model. Cellular metabolism in any organism usually involves the transport of metabolites across a lipid bi-layer. Hence, this test checks that there is at least one reaction, which transports metabolites from one compartment to another. A transport reaction is defined as follows: 1. It contains metabolites from at least two compartments and 2. at least one metabolite undergoes no chemical conversion, i.e., the formula stays the same on both sides of the equation. This test will not be able to identify transport via the PTS System. """ ann = test_transport_reaction_presence.annotation ann["data"] = get_ids(helpers.find_transport_reactions(read_only_model)) ann["message"] = wrapper.fill( """A total of {:d} ({:.2%}) transport reactions are defined in the model, this excludes purely metabolic reactions, exchanges, or pseudo-reactions: {}""".format(len(ann["data"]), ann["metric"], truncate(ann["data"]))) assert len(ann["data"]) >= 1, ann["message"]
def test_find_transport_reactions(model, num): """Expect amount of transporters to be identified correctly.""" assert len(helpers.find_transport_reactions(model)) == num
def check_transport_reaction_gpr_presence(model): """Return the list of transport reactions that have no associated gpr.""" return [rxn for rxn in helpers.find_transport_reactions(model) if not rxn.gene_reaction_rule]
def test_find_transport_reactions(model, num): """Expect amount of transporters to be identified correctly.""" assert len(helpers.find_transport_reactions(model)) == num
def check_transport_reaction_gpr_presence(model): """Return the list of transport reactions that have no associated gpr.""" return [ rxn for rxn in helpers.find_transport_reactions(model) if not rxn.gene_reaction_rule ]