Source code for test_sbo

# -*- coding: utf-8 -*-

# Copyright 2017 Novo Nordisk Foundation Center for Biosustainability,
# Technical University of Denmark.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Tests for SBO terms performed on an instance of ``cobra.Model``."""

from __future__ import absolute_import, division

import pytest

import memote.support.basic as basic
import memote.support.helpers as helpers
import memote.support.sbo as sbo
from memote.utils import annotate, get_ids, truncate, wrapper


@annotate(title="Metabolite General SBO Presence", format_type="count")
[docs]def test_metabolite_sbo_presence(model): """Expect all metabolites to have a some form of SBO-Term annotation. The Systems Biology Ontology (SBO) allows researchers to annotate a model with terms which indicate the intended function of its individual components. The available terms are controlled and relational and can be viewed here http://www.ebi.ac.uk/sbo/main/tree. Implementation: Check if each cobra.Metabolite has a non-zero "annotation" attribute that contains the key "sbo". """ ann = test_metabolite_sbo_presence.annotation ann["data"] = get_ids(sbo.find_components_without_sbo_terms(model, "metabolites")) try: ann["metric"] = len(ann["data"]) / len(model.metabolites) ann["message"] = wrapper.fill( """A total of {} metabolites ({:.2%}) lack annotation with any type of SBO term: {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no metabolites." pytest.skip(ann["message"]) assert len(ann["data"]) == len(model.metabolites), ann["message"]
@annotate(title="Reaction General SBO Presence", format_type="count")
[docs]def test_reaction_sbo_presence(model): """Expect all reactions to have a some form of SBO-Term annotation. The Systems Biology Ontology (SBO) allows researchers to annotate a model with terms which indicate the intended function of its individual components. The available terms are controlled and relational and can be viewed here http://www.ebi.ac.uk/sbo/main/tree. Implementation: Check if each cobra.Reaction has a non-zero "annotation" attribute that contains the key "sbo". """ ann = test_reaction_sbo_presence.annotation ann["data"] = get_ids(sbo.find_components_without_sbo_terms(model, "reactions")) try: ann["metric"] = len(ann["data"]) / len(model.reactions) ann["message"] = wrapper.fill( """A total of {} reactions ({:.2%}) lack annotation with any type of SBO term: {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no reactions." pytest.skip(ann["message"]) assert len(ann["data"]) == len(model.reactions), ann["message"]
@annotate(title="Gene General SBO Presence", format_type="count")
[docs]def test_gene_sbo_presence(model): """Expect all genes to have a some form of SBO-Term annotation. The Systems Biology Ontology (SBO) allows researchers to annotate a model with terms which indicate the intended function of its individual components. The available terms are controlled and relational and can be viewed here http://www.ebi.ac.uk/sbo/main/tree. Check if each cobra.Gene has a non-zero "annotation" attribute that contains the key "sbo". """ ann = test_gene_sbo_presence.annotation ann["data"] = get_ids(sbo.find_components_without_sbo_terms(model, "genes")) try: ann["metric"] = len(ann["data"]) / len(model.genes) ann["message"] = wrapper.fill( """A total of {} genes ({:.2%}) lack annotation with any type of SBO term: {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no genes." pytest.skip(ann["message"]) assert len(ann["data"]) == len(model.genes), ann["message"]
@annotate(title="Metabolic Reaction SBO:0000176 Presence", format_type="count")
[docs]def test_metabolic_reaction_specific_sbo_presence(model): """Expect all metabolic reactions to be annotated with SBO:0000176. SBO:0000176 represents the term 'biochemical reaction'. Every metabolic reaction that is not a transport or boundary reaction should be annotated with this. The results shown are relative to the total amount of pure metabolic reactions. Implementation: Check if each pure metabolic reaction has a non-zero "annotation" attribute that contains the key "sbo" with the associated value being the SBO term above. """ ann = test_metabolic_reaction_specific_sbo_presence.annotation pure = basic.find_pure_metabolic_reactions(model) ann["data"] = get_ids( sbo.check_component_for_specific_sbo_term(pure, "SBO:0000176") ) try: ann["metric"] = len(ann["data"]) / len(pure) ann["message"] = wrapper.fill( """A total of {} metabolic reactions ({:.2%} of all purely metabolic reactions) lack annotation with the SBO term "SBO:0000176" for 'biochemical reaction': {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no metabolic reactions." pytest.skip(ann["message"]) assert len(ann["data"]) == len(pure), ann["message"]
@annotate(title="Transport Reaction SBO:0000185 Presence", format_type="count")
[docs]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"]
@annotate(title="Metabolite SBO:0000247 Presence", format_type="count")
[docs]def test_metabolite_specific_sbo_presence(model): """Expect all metabolites to be annotated with SBO:0000247. SBO:0000247 represents the term 'simple chemical'. Every metabolite should be annotated with this. Implementation: Check if each cobra.Metabolite has a non-zero "annotation" attribute that contains the key "sbo" with the associated value being one of the SBO terms above. """ ann = test_metabolite_specific_sbo_presence.annotation ann["data"] = get_ids( sbo.check_component_for_specific_sbo_term(model.metabolites, "SBO:0000247") ) try: ann["metric"] = len(ann["data"]) / len(model.metabolites) ann["message"] = wrapper.fill( """A total of {} transport reactions ({:.2%} of all metabolites) lack annotation with the SBO term "SBO:0000247" for 'simple chemical': {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no metabolites." pytest.skip(ann["message"]) assert len(ann["data"]) == len(model.metabolites), ann["message"]
@annotate(title="Gene SBO:0000243 Presence", format_type="count")
[docs]def test_gene_specific_sbo_presence(model): """Expect all genes to be annotated with SBO:0000243. SBO:0000243 represents the term 'gene'. Every gene should be annotated with this. Implementation: Check if each cobra.Gene has a non-zero "annotation" attribute that contains the key "sbo" with the associated value being one of the SBO terms above. """ ann = test_gene_specific_sbo_presence.annotation ann["data"] = get_ids( sbo.check_component_for_specific_sbo_term(model.genes, "SBO:0000243") ) try: ann["metric"] = len(ann["data"]) / len(model.genes) ann["message"] = wrapper.fill( """A total of {} genes ({:.2%} of all genes) lack annotation with the SBO term "SBO:0000243" for 'gene': {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no genes." pytest.skip(ann["message"]) assert len(ann["data"]) == len(model.genes), ann["message"]
@annotate(title="Exchange Reaction SBO:0000627 Presence", format_type="count")
[docs]def test_exchange_specific_sbo_presence(model): """Expect all exchange reactions to be annotated with SBO:0000627. SBO:0000627 represents the term 'exchange reaction'. The Systems Biology Ontology defines an exchange reaction as follows: 'A modeling process to provide matter influx or efflux to a model, for example to replenish a metabolic network with raw materials (eg carbon / energy sources). Such reactions are conceptual, created solely for modeling purposes, and do not have a physical correspondence. Exchange reactions, often represented as 'R_EX_', can operate in the negative (uptake) direction or positive (secretion) direction. By convention, a negative flux through an exchange reaction represents uptake of the corresponding metabolite, and a positive flux represent discharge.' Every exchange reaction should be annotated with this. Exchange reactions differ from demand reactions in that the metabolites are removed from or added to the extracellular environment only. Implementation: Check if each exchange reaction has a non-zero "annotation" attribute that contains the key "sbo" with the associated value being one of the SBO terms above. """ ann = test_exchange_specific_sbo_presence.annotation exchanges = helpers.find_exchange_rxns(model) ann["data"] = get_ids( sbo.check_component_for_specific_sbo_term(exchanges, "SBO:0000627") ) try: ann["metric"] = len(ann["data"]) / len(exchanges) ann["message"] = wrapper.fill( """A total of {} exchange reactions ({:.2%} of all exchange reactions) lack annotation with the SBO term "SBO:0000627" for 'exchange reaction': {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no exchange reactions." pytest.skip(ann["message"]) assert len(ann["data"]) == len(exchanges), ann["message"]
@annotate(title="Demand Reaction SBO:0000628 Presence", format_type="count")
[docs]def test_demand_specific_sbo_presence(model): """Expect all demand reactions to be annotated with SBO:0000627. SBO:0000628 represents the term 'demand reaction'. The Systems Biology Ontology defines a demand reaction as follows: 'A modeling process analogous to exchange reaction, but which operates upon "internal" metabolites. Metabolites that are consumed by these reactions are assumed to be used in intra-cellular processes that are not part of the model. Demand reactions, often represented 'R_DM_', can also deliver metabolites (from intra-cellular processes that are not considered in the model).' Every demand reaction should be annotated with this. Demand reactions differ from exchange reactions in that the metabolites are not removed from the extracellular environment, but from any of the organism's compartments. Demand reactions differ from sink reactions in that they are designated as irreversible. Implementation: Check if each demand reaction has a non-zero "annotation" attribute that contains the key "sbo" with the associated value being one of the SBO terms above. """ ann = test_demand_specific_sbo_presence.annotation demands = helpers.find_demand_reactions(model) ann["data"] = get_ids( sbo.check_component_for_specific_sbo_term(demands, "SBO:0000628") ) try: ann["metric"] = len(ann["data"]) / len(demands) ann["message"] = wrapper.fill( """A total of {} genes ({:.2%} of all demand reactions) lack annotation with the SBO term "SBO:0000628" for 'demand reaction': {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "The model has no demand reactions." pytest.skip(ann["message"]) assert len(ann["data"]) == len(demands), ann["message"]
@annotate(title="Sink Reactions SBO:0000632 Presence", format_type="count")
[docs]def test_sink_specific_sbo_presence(model): """Expect all sink reactions to be annotated with SBO:0000632. SBO:0000632 represents the term 'sink reaction'. The Systems Biology Ontology defines a sink reaction as follows: 'A modeling process to provide matter influx or efflux to a model, for example to replenish a metabolic network with raw materials (eg carbon / energy sources). Such reactions are conceptual, created solely for modeling purposes, and do not have a physical correspondence. Unlike the analogous demand (SBO:....) reactions, which are usually designated as irreversible, sink reactions always represent a reversible uptake/secretion processes, and act as a metabolite source with no cost to the cell. Sink reactions, also referred to as R_SINK_, are generally used for compounds that are metabolized by the cell but are produced by non-metabolic, un-modeled cellular processes.' Every sink reaction should be annotated with this. Sink reactions differ from exchange reactions in that the metabolites are not removed from the extracellular environment, but from any of the organism's compartments. Implementation: Check if each sink reaction has a non-zero "annotation" attribute that contains the key "sbo" with the associated value being one of the SBO terms above. """ ann = test_sink_specific_sbo_presence.annotation sinks = helpers.find_sink_reactions(model) ann["data"] = get_ids( sbo.check_component_for_specific_sbo_term(sinks, "SBO:0000632") ) try: ann["metric"] = len(ann["data"]) / len(sinks) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "No sink reactions found." pytest.skip(ann["message"]) ann["message"] = wrapper.fill( """A total of {} genes ({:.2%} of all sink reactions) lack annotation with the SBO term "SBO:0000632" for 'sink reaction': {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) assert len(ann["data"]) == len(sinks), ann["message"]
@annotate(title="Biomass Reactions SBO:0000629 Presence", format_type="count")
[docs]def test_biomass_specific_sbo_presence(model): """Expect all biomass reactions to be annotated with SBO:0000629. SBO:0000629 represents the term 'biomass production'. The Systems Biology Ontology defines an exchange reaction as follows: 'Biomass production, often represented 'R_BIOMASS_', is usually the optimization target reaction of constraint-based models, and can consume multiple reactants to produce multiple products. It is also assumed that parts of the reactants are also consumed in unrepresented processes and hence products do not have to reflect all the atom composition of the reactants. Formulation of a biomass production process entails definition of the macromolecular content (eg. cellular protein fraction), metabolic constitution of each fraction (eg. amino acids), and subsequently the atomic composition (eg. nitrogen atoms). More complex biomass functions can additionally incorporate details of essential vitamins and cofactors required for growth.' Every reaction representing the biomass production should be annotated with this. Implementation: Check if each biomass reaction has a non-zero "annotation" attribute that contains the key "sbo" with the associated value being one of the SBO terms above. """ ann = test_biomass_specific_sbo_presence.annotation biomass = helpers.find_biomass_reaction(model) ann["data"] = get_ids( sbo.check_component_for_specific_sbo_term(biomass, "SBO:0000629") ) try: ann["metric"] = len(ann["data"]) / len(biomass) except ZeroDivisionError: ann["metric"] = 1.0 ann["message"] = "No biomass reactions found." pytest.skip(ann["message"]) ann["message"] = wrapper.fill( """A total of {} biomass reactions ({:.2%} of all biomass reactions) lack annotation with the SBO term "SBO:0000629" for 'biomass production': {}""".format( len(ann["data"]), ann["metric"], truncate(ann["data"]) ) ) assert len(ann["data"]) == 0, ann["message"]