예제 #1
0
def test_biomass_presence(model):
    """
    Expect the model to contain at least one biomass reaction.

    The biomass composition aka biomass formulation aka biomass reaction
    is a common pseudo-reaction accounting for biomass synthesis in
    constraints-based modelling. It describes the stoichiometry of
    intracellular compounds that are required for cell growth. While this
    reaction may not be relevant to modeling the metabolism of higher
    organisms, it is essential for single-cell modeling.

    Implementation:
    Identifies possible biomass reactions using two principal steps:
        1. Return reactions that include the SBO annotation "SBO:0000629" for
        biomass.
    If no reactions can be identifies this way:
        1. Look for the ``buzzwords`` "biomass", "growth" and "bof" in reaction
        IDs.
        2. Look for metabolite IDs or names that contain the ``buzzword``
        "biomass" and obtain the set of reactions they are involved in.
        3. Remove boundary reactions from this set.
        4. Return the union of reactions that match the buzzwords and of the
        reactions that metabolites are involved in that match the buzzword.
    This test checks if at least one biomass reaction is present.

    """
    ann = test_biomass_presence.annotation
    ann["data"] = [rxn.id for rxn in helpers.find_biomass_reaction(model)]
    outcome = len(ann["data"]) > 0
    ann["metric"] = 1.0 - float(outcome)
    ann["message"] = wrapper.fill(
        """In this model {} the following biomass reactions were
        identified: {}""".format(len(ann["data"]), truncate(ann["data"])))
    assert outcome, ann["message"]
예제 #2
0
파일: test_sbo.py 프로젝트: sgalkina/memote
def test_biomass_specific_sbo_presence(read_only_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.
    """
    ann = test_biomass_specific_sbo_presence.annotation
    biomass = helpers.find_biomass_reaction(read_only_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"]) == len(biomass), ann["message"]
예제 #3
0
 def pytest_namespace(self):
     """Insert model information into the pytest namespace."""
     namespace = dict()
     namespace["memote"] = memote = dict()
     memote["biomass_ids"] = [
         rxn.id for rxn in find_biomass_reaction(self._model)
     ]
     memote["compartment_ids"] = sorted(self._model.compartments)
     try:
         memote["compartment_ids"].remove("c")
     except ValueError:
         LOGGER.error(
             "The model does not contain a compartment ID labeled 'c' for "
             "the cytosol which is an essential compartment. Many syntax "
             "tests depend on this being labeled accordingly.")
     # Add experimental information if there are any.
     if self._exp_config is None:
         memote["experimental"] = dict()
         memote["experimental"]["essentiality"] = list()
         memote["experimental"]["growth"] = list()
     else:
         # Load experimental data.
         self._exp_config.load_data(self._model)
         memote["experimental"] = self._exp_config
     return namespace
예제 #4
0
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)]
예제 #5
0
def test_essential_precursors_not_in_biomass(model, number):
    """
    Expect correct amount of missing essential precursors to be identified.
    """
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        assert len(biomass.essential_precursors_not_in_biomass(model,
                                                               rxn)) is number
예제 #6
0
def test_essential_precursors_not_in_biomass(model, number):
    """
    Expect correct amount of missing essential precursors to be identified.
    """
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        assert len(biomass.essential_precursors_not_in_biomass(
            model, rxn
        )) is number
예제 #7
0
def test_production_biomass_precursors_default(model, num):
    """
    Expect that there are no biomass precursors that cannot be produced.

    This is without changing the model's default state.
    """
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        blocked_mets = biomass.find_blocked_biomass_precursors(rxn, model)
        assert len(blocked_mets) == num
예제 #8
0
def test_biomass_weight_production(model, expected):
    """
    Expect that the sum of total mass of all biomass components equals 1.

    Allow for an absolute tolerance of 1e-03.
    """
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        control_sum = biomass.sum_biomass_weight(rxn)
        assert np.isclose(1, control_sum, atol=1e-03) is expected
예제 #9
0
def test_biomass_weight_production(model, expected):
    """
    Expect that the sum of total mass of all biomass components equals 1.

    Allow for an absolute tolerance of 1e-03.
    """
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        control_sum = biomass.sum_biomass_weight(rxn)
        assert np.isclose(1, control_sum, atol=1e-03) == expected
예제 #10
0
def test_production_biomass_precursors_default(model, num):
    """
    Expect that there are no biomass precursors that cannot be produced.

    This is without changing the model"s default state.
    """
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        blocked_mets = biomass.find_blocked_biomass_precursors(rxn, model)
        assert len(blocked_mets) == num
예제 #11
0
def test_production_biomass_precursors_exchange(model, num):
    """
    Expect that there are no biomass precursors that cannot be produced.

    This is after opening the model"s exchange reactions.
    """
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        helpers.open_boundaries(model)
        blocked_mets = biomass.find_blocked_biomass_precursors(rxn, model)
        assert len(blocked_mets) == num
예제 #12
0
def test_production_biomass_precursors_exchange(model, num):
    """
    Expect that there are no biomass precursors that cannot be produced.

    This is after opening the model"s exchange reactions.
    """
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        helpers.open_boundaries(model)
        blocked_mets = biomass.find_blocked_biomass_precursors(rxn, model)
        assert len(blocked_mets) == num
예제 #13
0
 def _collect_meta_info(self):
     """Record environment information."""
     os.environ["BIOMASS_REACTIONS"] = "|".join(
         [rxn.id for rxn in find_biomass_reaction(self._model)])
     self._meta["platform"] = platform.system()
     self._meta["release"] = platform.release()
     self._meta["python"] = platform.python_version()
     self._meta["packages"] = dict(
         (dist.project_name, dist.version)
         for dist in pip.get_installed_distributions())
     self._meta["timestamp"] = datetime.utcnow().isoformat(" ")
     if self.repo is not None:
         self._collect_git_info()
예제 #14
0
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)
예제 #15
0
 def pytest_namespace(self):
     """Insert model information into the pytest namespace."""
     biomass_ids = [rxn.id for rxn in find_biomass_reaction(self._model)]
     compartment_ids = sorted(self._model.compartments)
     try:
         compartment_ids.remove("c")
     except ValueError:
         LOGGER.error(
             "The model does not contain a compartment ID labeled 'c' for "
             "the cytosol which is an essential compartment. Many syntax "
             "tests depend on this being labeled accordingly.")
     return {
         "memote": {
             "biomass_ids": biomass_ids,
             "compartment_ids": compartment_ids
         }
     }
예제 #16
0
def get_internals(model):
    """
    Return non-boundary reactions and their metabolites.

    Boundary reactions are unbalanced by their nature. They are excluded here
    and only the metabolites of the others are considered.

    Parameters
    ----------
    model : cobra.Model
        The metabolic model under investigation.

    """
    biomass = set(find_biomass_reaction(model))
    if len(biomass) == 0:
        LOGGER.warning("No biomass reaction detected. Consistency test results "
                       "are unreliable if one exists.")
    return set(model.reactions) - (set(model.boundary) | biomass)
예제 #17
0
def get_internals(model):
    """
    Return non-exchange reactions and their metabolites.

    Exchange reactions are unbalanced by their nature. They are excluded here
    and only the metabolites of the others are considered.

    Parameters
    ----------
    model : cobra.Model
        The metabolic model under investigation.

    """
    biomass = set(find_biomass_reaction(model))
    if len(biomass) == 0:
        LOGGER.warn("No biomass reaction detected. Consistency test results "
                    "are unreliable if one exists.")
    return set(model.reactions) - (set(model.exchanges) | biomass)
예제 #18
0
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"]
예제 #19
0
 def pytest_generate_tests(self, metafunc):
     """Parametrize marked functions at runtime."""
     if metafunc.definition.get_closest_marker("biomass"):
         metafunc.parametrize("reaction_id", [
             rxn.id for rxn in find_biomass_reaction(self._model)])
         return
     # Parametrize experimental test cases.
     for kind in ["essentiality", "growth"]:
         # Find a corresponding pytest marker on the test case.
         if not metafunc.definition.get_closest_marker(kind):
             continue
         exp = getattr(self._exp_config, kind, None)
         if exp is None:
             metafunc.parametrize("experiment", [])
         else:
             metafunc.parametrize(
                 "experiment", list(exp.items()))
         # We only expect one kind of experimental marker per test case
         # and thus end execution here.
         return
예제 #20
0
 def pytest_generate_tests(self, metafunc):
     """Parametrize marked functions at runtime."""
     if metafunc.definition.get_closest_marker("biomass"):
         metafunc.parametrize(
             "reaction_id",
             [rxn.id for rxn in find_biomass_reaction(self._model)])
         return
     # Parametrize experimental test cases.
     for kind in ["essentiality", "growth"]:
         # Find a corresponding pytest marker on the test case.
         if not metafunc.definition.get_closest_marker(kind):
             continue
         exp = getattr(self._exp_config, kind, None)
         if exp is None:
             metafunc.parametrize("experiment", [])
         else:
             names = sorted(exp)
             metafunc.parametrize("experiment",
                                  argvalues=[(n, exp[n]) for n in names],
                                  ids=names)
         # We only expect one kind of experimental marker per test case
         # and thus end execution here.
         return
예제 #21
0
def test_gam_in_biomass(model, boolean):
    """Expect the biomass reactions to contain atp and adp."""
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        assert biomass.gam_in_biomass(rxn) is boolean
예제 #22
0
def find_direct_metabolites(model, reaction, tolerance=1E-06):
    """
    Return list of possible direct biomass precursor metabolites.

    The term direct metabolites describes metabolites that are involved only
    in either transport and/or boundary reactions, AND the biomass reaction(s),
    but not in any purely metabolic reactions.

    Parameters
    ----------
    model : cobra.Model
        The metabolic model under investigation.
    reaction : cobra.Reaction
        The biomass reaction of the model under investigation.
    tolerance : float, optional
        Tolerance below which values will be regarded as zero.

    Returns
    -------
    list
        Metabolites that qualify as direct metabolites i.e. biomass precursors
        that are taken up to be consumed by the biomass reaction only.

    """
    biomass_rxns = set(helpers.find_biomass_reaction(model))
    tra_bou_bio_rxns = helpers.find_interchange_biomass_reactions(
        model, biomass_rxns)
    try:
        precursors = find_biomass_precursors(model, reaction)
        main_comp = helpers.find_compartment_id_in_model(model, 'c')
        ext_space = helpers.find_compartment_id_in_model(model, 'e')
    except KeyError:
        LOGGER.error("Failed to properly identify cytosolic and extracellular "
                     "compartments.")
        raise_with_traceback(KeyError("The cytosolic and/or extracellular "
                                      "compartments could not be identified."))
    except RuntimeError:
        LOGGER.error("Failed to properly identify cytosolic and extracellular "
                     "compartments.")
        raise_with_traceback(RuntimeError("The cytosolic and/or extracellular "
                                          "compartments could not be "
                                          "identified."))
    else:
        tra_bou_bio_mets = [met for met in precursors if
                            met.reactions.issubset(tra_bou_bio_rxns)]
        rxns_of_interest = set([rxn for met in tra_bou_bio_mets
                                for rxn in met.reactions
                                if rxn not in biomass_rxns])

    solution = model.optimize(raise_error=True)
    if np.isclose(solution.objective_value, 0, atol=tolerance):
        LOGGER.error("Failed to generate a non-zero objective value with "
                     "flux balance analysis.")
        raise OptimizationError(
            "The flux balance analysis on this model returned an "
            "objective value of zero. Make sure the model can "
            "grow! Check if the constraints are not too strict!")

    tra_bou_bio_fluxes = {r: solution[r.id] for r in rxns_of_interest}
    met_flux_sum = {m: 0 for m in tra_bou_bio_mets}

    return detect_false_positive_direct_metabolites(
        tra_bou_bio_mets, biomass_rxns, main_comp, ext_space,
        tra_bou_bio_fluxes, met_flux_sum)
예제 #23
0
def test_gam_in_biomass(model, boolean):
    """Expect the biomass reactions to contain atp and adp."""
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        assert biomass.gam_in_biomass(model, rxn) is boolean
예제 #24
0
def test_find_biomass_reaction(model, expected):
    """
    Expect the biomass reaction to be identified correctly.
    """
    assert len(helpers.find_biomass_reaction(model)) == expected
예제 #25
0
def test_bundle_biomass_components(model, number):
    """Expect the type of biomass reaction to be identified correctly."""
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        assert len(biomass.bundle_biomass_components(model, rxn)) is number
예제 #26
0
def test_find_direct_metabolites(model, number):
    """Expect the appropriate amount of direct metabolites to be found."""
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        assert len(biomass.find_direct_metabolites(model, rxn)) is number
예제 #27
0
def test_find_direct_metabolites(model, number):
    """Expect the appropriate amount of direct metabolites to be found."""
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        assert len(biomass.find_direct_metabolites(model, rxn)) is number
예제 #28
0
def test_find_direct_metabolites_errors(model):
    """Expect the appropriate amount of direct metabolites to be found."""
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        biomass.find_direct_metabolites(model, rxn)
예제 #29
0
def test_bundle_biomass_components(model, number):
    """Expect the type of biomass reaction to be identified correctly."""
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        assert len(biomass.bundle_biomass_components(model, rxn)) is number
예제 #30
0
def test_find_direct_metabolites_errors(model):
    """Expect the appropriate amount of direct metabolites to be found."""
    biomass_rxns = helpers.find_biomass_reaction(model)
    for rxn in biomass_rxns:
        biomass.find_direct_metabolites(model, rxn)
예제 #31
0
파일: biomass.py 프로젝트: sulheim/memote
def find_direct_metabolites(model, reaction, tolerance=1E-06):
    """
    Return list of possible direct biomass precursor metabolites.

    The term direct metabolites describes metabolites that are involved only
    in either transport and/or boundary reactions, AND the biomass reaction(s),
    but not in any purely metabolic reactions.

    Parameters
    ----------
    model : cobra.Model
        The metabolic model under investigation.
    reaction : cobra.Reaction
        The biomass reaction of the model under investigation.
    tolerance : float, optional
        Tolerance below which values will be regarded as zero.

    Returns
    -------
    list
        Metabolites that qualify as direct metabolites i.e. biomass precursors
        that are taken up to be consumed by the biomass reaction only.

    """
    biomass_rxns = set(helpers.find_biomass_reaction(model))
    tra_bou_bio_rxns = helpers.find_interchange_biomass_reactions(
        model, biomass_rxns)
    try:
        precursors = find_biomass_precursors(model, reaction)
        main_comp = helpers.find_compartment_id_in_model(model, 'c')
        ext_space = helpers.find_compartment_id_in_model(model, 'e')
    except KeyError:
        LOGGER.error("Failed to properly identify cytosolic and extracellular "
                     "compartments.")
        raise_with_traceback(
            KeyError("The cytosolic and/or extracellular "
                     "compartments could not be identified."))
    except RuntimeError:
        LOGGER.error("Failed to properly identify cytosolic and extracellular "
                     "compartments.")
        raise_with_traceback(
            RuntimeError("The cytosolic and/or extracellular "
                         "compartments could not be "
                         "identified."))
    else:
        tra_bou_bio_mets = [
            met for met in precursors
            if met.reactions.issubset(tra_bou_bio_rxns)
        ]
        rxns_of_interest = set([
            rxn for met in tra_bou_bio_mets for rxn in met.reactions
            if rxn not in biomass_rxns
        ])

    solution = model.optimize(raise_error=True)
    if np.isclose(solution.objective_value, 0, atol=tolerance):
        LOGGER.error("Failed to generate a non-zero objective value with "
                     "flux balance analysis.")
        raise OptimizationError(
            "The flux balance analysis on this model returned an "
            "objective value of zero. Make sure the model can "
            "grow! Check if the constraints are not too strict!")

    tra_bou_bio_fluxes = {r: solution[r.id] for r in rxns_of_interest}
    met_flux_sum = {m: 0 for m in tra_bou_bio_mets}

    return detect_false_positive_direct_metabolites(tra_bou_bio_mets,
                                                    biomass_rxns, main_comp,
                                                    ext_space,
                                                    tra_bou_bio_fluxes,
                                                    met_flux_sum)
예제 #32
0
def test_find_biomass_reaction(model, expected):
    """
    Expect the biomass reaction to be identified correctly.
    """
    assert len(helpers.find_biomass_reaction(model)) == expected