Example #1
0
def test_bad_exchange(model: Model) -> None:
    """Test bad exchange reaction identification."""
    with pytest.raises(ValueError):
        m = Metabolite("baddy", compartment="nonsense")
        model.add_boundary(m, type="exchange")
    m = Metabolite("goody", compartment="e")
    rxn = model.add_boundary(m, type="exchange")
    assert isinstance(rxn, Reaction)
Example #2
0
    def test_gapfilling(self, salmonella):
        m = Model()
        m.add_metabolites([Metabolite(m_id) for m_id in ["a", "b", "c"]])
        exa = Reaction("EX_a")
        exa.add_metabolites({m.metabolites.a: 1})
        b2c = Reaction("b2c")
        b2c.add_metabolites({m.metabolites.b: -1, m.metabolites.c: 1})
        dmc = Reaction("DM_c")
        dmc.add_metabolites({m.metabolites.c: -1})
        m.add_reactions([exa, b2c, dmc])
        m.objective = 'DM_c'

        universal = Model()
        a2b = Reaction("a2b")
        a2d = Reaction("a2d")
        universal.add_reactions([a2b, a2d])
        a2b.build_reaction_from_string("a --> b", verbose=False)
        a2d.build_reaction_from_string("a --> d", verbose=False)

        # # GrowMatch
        # result = gapfilling.growMatch(m, universal)[0]
        result = gapfilling.gapfill(m, universal)[0]
        assert len(result) == 1
        assert result[0].id == "a2b"

        # # SMILEY
        # result = gapfilling.SMILEY(m, "b", universal)[0]
        with m:
            m.objective = m.add_boundary(m.metabolites.b, type='demand')
            result = gapfilling.gapfill(m, universal)[0]
            assert len(result) == 1
            assert result[0].id == "a2b"

        # # 2 rounds of GrowMatch with exchange reactions
        # result = gapfilling.growMatch(m, None, ex_rxns=True, iterations=2)
        result = gapfilling.gapfill(m,
                                    None,
                                    exchange_reactions=True,
                                    iterations=2)
        assert len(result) == 2
        assert len(result[0]) == 1
        assert len(result[1]) == 1
        assert {i[0].id for i in result} == {"EX_b", "EX_c"}

        # somewhat bigger model
        universal = Model("universal_reactions")
        with salmonella as model:
            for i in [i.id for i in model.metabolites.f6p_c.reactions]:
                reaction = model.reactions.get_by_id(i)
                universal.add_reactions([reaction.copy()])
                model.remove_reactions([reaction])
            gf = gapfilling.GapFiller(model,
                                      universal,
                                      penalties={'TKT2': 1e3},
                                      demand_reactions=False)
            solution = gf.fill()
            assert 'TKT2' not in {r.id for r in solution[0]}
            assert gf.validate(solution[0])
    def test_gapfilling(self, salmonella):
        m = Model()
        m.add_metabolites([Metabolite(m_id) for m_id in ["a", "b", "c"]])
        exa = Reaction("EX_a")
        exa.add_metabolites({m.metabolites.a: 1})
        b2c = Reaction("b2c")
        b2c.add_metabolites({m.metabolites.b: -1, m.metabolites.c: 1})
        dmc = Reaction("DM_c")
        dmc.add_metabolites({m.metabolites.c: -1})
        m.add_reactions([exa, b2c, dmc])
        m.objective = 'DM_c'

        universal = Model()
        a2b = Reaction("a2b")
        a2d = Reaction("a2d")
        universal.add_reactions([a2b, a2d])
        a2b.build_reaction_from_string("a --> b", verbose=False)
        a2d.build_reaction_from_string("a --> d", verbose=False)

        # # GrowMatch
        # result = gapfilling.growMatch(m, universal)[0]
        result = gapfilling.gapfill(m, universal)[0]
        assert len(result) == 1
        assert result[0].id == "a2b"

        # # SMILEY
        # result = gapfilling.SMILEY(m, "b", universal)[0]
        with m:
            m.objective = m.add_boundary(m.metabolites.b, type='demand')
            result = gapfilling.gapfill(m, universal)[0]
            assert len(result) == 1
            assert result[0].id == "a2b"

        # # 2 rounds of GrowMatch with exchange reactions
        # result = gapfilling.growMatch(m, None, ex_rxns=True, iterations=2)
        result = gapfilling.gapfill(m, None, exchange_reactions=True,
                                    iterations=2)
        assert len(result) == 2
        assert len(result[0]) == 1
        assert len(result[1]) == 1
        assert {i[0].id for i in result} == {"EX_b", "EX_c"}

        # somewhat bigger model
        universal = Model("universal_reactions")
        with salmonella as model:
            for i in [i.id for i in model.metabolites.f6p_c.reactions]:
                reaction = model.reactions.get_by_id(i)
                universal.add_reactions([reaction.copy()])
                model.remove_reactions([reaction])
            gf = gapfilling.GapFiller(model, universal,
                                      penalties={'TKT2': 1e3},
                                      demand_reactions=False)
            solution = gf.fill()
            assert 'TKT2' not in {r.id for r in solution[0]}
            assert gf.validate(solution[0])
Example #4
0
def create_community_model(source_models):
    """ Create a community model from a list of source models.

    A community model contains all of the reactions and metabolites from the
    source models. As a source model for a species is added to the community
    model, a model ID prefix is added to the IDs of reactions and metabolites.
    This is the same as assigning each species to a different compartment,
    which is required because cells are closed compartments that do not share
    metabolites. A shared compartment is added to the community model and all
    unique exchange reactions from the source models are added to the community
    model to exchange metabolites between the shared compartment and the system
    boundary. For each source model, all exchange reactions are converted to
    transport reactions to move the metabolite between the shared compartment
    and the extracellular compartment of the source model.

    Parameters
    ----------
    source_models : list of str
        List of path names to model files

    Returns
    -------
    cobra.core.Model
        Community model

    Raises
    ------
    Exception
        If there are less than two models in the list of source models.
        If there is a duplicate model ID in the list of source models.
        If there is more than one objective
        If the type of IDs in the model metabolites could not be determined.
    """

    # There must be at least two source models to make a community model.
    if len(source_models) < 2:
        raise Exception(
            'There must be at least two species in a community model')

    # Start with an empty model.
    community = Model('Community')
    community.compartments['u'] = 'Lumen'

    # Keep track of the source models. Each element is a tuple with ID and source file name.
    community.notes['species'] = list()

    # IDs of all exchange reactions in the community.
    exchange_reaction_ids = set()

    # IDs of all models in the community (duplicates are not allowed).
    model_ids = set()

    # Add of the source models to the community model.
    for model_filename in source_models:
        # Load the model from a file.
        model = load_model_from_file(model_filename)

        # Since the model ID is used as a prefix for reactions and metabolites it must be unique.
        if model.id in model_ids:
            raise Exception(
                'Model ID {0} from {1} is a duplicate in the community'.format(
                    model.id, model_filename))
        model_ids.add(model.id)

        # Check for multiple objectives in the model (which changed significantly in cobra 0.6).
        if cobra06:
            linear_coefficients = linear_reaction_coefficients(model)
            if len(linear_coefficients) != 1:
                raise Exception(
                    'Wrong number of objectives for model {0}, only one growth objective is allowed'
                    .format(model_filename))
            objective_id = '{0}_{1}'.format(
                model.id,
                six.next(six.iterkeys(linear_coefficients)).id)
            objective_value = six.next(six.itervalues(linear_coefficients))
        else:
            if len(model.objective) != 1:
                raise Exception(
                    'Wrong number of objectives for model {0}, only one growth objective is allowed'
                    .format(model_filename))
            objective_id = '{0}_{1}'.format(
                model.id,
                six.next(six.iterkeys(model.objective)).id)
            objective_value = six.next(six.itervalues(model.objective))

        # All metabolites need to have a compartment suffix.
        for metabolite in model.metabolites:
            metabolite.notes['type'] = _id_type(metabolite.id)
        unknown = model.metabolites.query(lambda x: 'unknown' in x['type'],
                                          'notes')
        if len(unknown) > 0:
            raise Exception(
                'Unknown compartment suffixes found in metabolites for {0}'.
                format(model_filename))

        # Get the exchange reactions from the species model.
        exchange_reactions = model.reactions.query(
            lambda x: x.startswith('EX_'), 'id')

        # Add any exchange reactions that are not already in the community model.
        for reaction in exchange_reactions:
            if reaction.id not in exchange_reaction_ids:
                exchange_reaction_ids.add(reaction.id)
                if cobra06:
                    metabolite = six.next(six.iterkeys(
                        reaction.metabolites)).copy()
                    metabolite.compartment = community_compartment
                    metabolite.id = _change_compartment(
                        metabolite.id, community_compartment,
                        metabolite.notes['type'])
                    rxn = community.add_boundary(
                        metabolite)  # This is slow on cobra06
                    rxn.id = reaction.id  # Keep same ID as species model
                else:
                    community.add_reactions([copy_exchange_reaction(reaction)])

        # Update the reaction IDs with species prefix and convert exchange reactions to transport reactions.
        for reaction in model.reactions:
            # Change the exchange reactions to transport reactions to move the metabolite between the
            # community compartment and the extracellular compartment of this organism.
            if reaction in exchange_reactions:
                e_metabolite = six.next(six.iterkeys(reaction.metabolites))
                u_metabolite = community.metabolites.get_by_id(
                    _change_compartment(e_metabolite.id, community_compartment,
                                        e_metabolite.notes['type']))
                reaction.add_metabolites({u_metabolite: 1.})
                reaction.id = '{0}_TR_{1}'.format(
                    model.id, reaction.id[3:])  # Strip "EX_" prefix
                reaction.bounds = (-1000., 1000.)
            else:
                reaction.id = '{0}_{1}'.format(model.id, reaction.id)

        # Update the metabolite IDs with species prefix.
        for metabolite in model.metabolites:
            if metabolite.compartment != community_compartment:
                metabolite.id = '{0}_{1}'.format(model.id, metabolite.id)

        # Add the species model to the community model.
        community += model
        if cobra06:
            # Workaround until agreement reached on issue #505.
            objective_reaction = community.reactions.get_by_id(objective_id)
            set_objective(community, {objective_reaction: objective_value},
                          additive=True)
        species = {
            'id': model.id,
            'objective': objective_id,
            'filename': model_filename
        }
        community.notes['species'].append(species)

    # Update the community ID to include all of the species in the community.
    # Note that the community ID is used as the file name when saving the
    # community model to a JSON file.
    community.id = 'x'.join(model_ids)
    return community
Example #5
0
def test_gapfilling(salmonella):
    """Test Gapfilling."""
    m = Model()
    m.add_metabolites([Metabolite(m_id) for m_id in ["a", "b", "c"]])
    exa = Reaction("EX_a")
    exa.add_metabolites({m.metabolites.a: 1})
    b2c = Reaction("b2c")
    b2c.add_metabolites({m.metabolites.b: -1, m.metabolites.c: 1})
    dmc = Reaction("DM_c")
    dmc.add_metabolites({m.metabolites.c: -1})
    m.add_reactions([exa, b2c, dmc])
    m.objective = 'DM_c'

    universal = Model()
    a2b = Reaction("a2b")
    a2d = Reaction("a2d")
    universal.add_reactions([a2b, a2d])
    a2b.build_reaction_from_string("a --> b", verbose=False)
    a2d.build_reaction_from_string("a --> d", verbose=False)

    # # GrowMatch
    # result = gapfilling.growMatch(m, universal)[0]
    result = gapfill(m, universal)[0]
    assert len(result) == 1
    assert result[0].id == "a2b"

    # # SMILEY
    # result = gapfilling.SMILEY(m, "b", universal)[0]
    with m:
        m.objective = m.add_boundary(m.metabolites.b, type='demand')
        result = gapfill(m, universal)[0]
        assert len(result) == 1
        assert result[0].id == "a2b"

    # # 2 rounds of GrowMatch with exchange reactions
    # result = gapfilling.growMatch(m, None, ex_rxns=True, iterations=2)
    result = gapfill(m, None, exchange_reactions=True,
                     iterations=2)
    assert len(result) == 2
    assert len(result[0]) == 1
    assert len(result[1]) == 1
    assert {i[0].id for i in result} == {"EX_b", "EX_c"}

    # # Gapfilling solution adds metabolites not present in original model
    # test for when demand = T
    # a demand reaction must be added to clear new metabolite
    universal_noDM = Model()
    a2b = Reaction("a2b")
    universal_noDM.add_reactions([a2b])
    a2b.build_reaction_from_string("a --> b + d", verbose=False)
    result = gapfill(m, universal_noDM,
                     exchange_reactions=False,
                     demand_reactions=True)[0]
    # add reaction a2b and demand reaction to clear met d
    assert len(result) == 2
    assert "a2b" in [x.id for x in result]

    # test for when demand = False
    # test for when metabolites are added to the model and
    # must be cleared by other reactions in universal model
    # (i.e. not necessarily a demand reaction)
    universal_withDM = universal_noDM.copy()
    d_dm = Reaction("d_dm")
    universal_withDM.add_reactions([d_dm])
    d_dm.build_reaction_from_string("d -->", verbose=False)
    result = gapfill(m, universal_withDM,
                     exchange_reactions=False,
                     demand_reactions=False)[0]
    assert len(result) == 2
    assert "a2b" in [x.id for x in result]

    # somewhat bigger model
    universal = Model("universal_reactions")
    with salmonella as model:
        for i in [i.id for i in model.metabolites.f6p_c.reactions]:
            reaction = model.reactions.get_by_id(i)
            universal.add_reactions([reaction.copy()])
            model.remove_reactions([reaction])
        gf = GapFiller(model, universal,
                       penalties={'TKT2': 1e3},
                       demand_reactions=False)
        solution = gf.fill()
        assert 'TKT2' not in {r.id for r in solution[0]}
        assert gf.validate(solution[0])
Example #6
0
def test_gapfilling(salmonella: Model) -> None:
    """Test Gapfilling."""
    m = Model()
    m.add_metabolites([Metabolite(m_id) for m_id in ["a", "b", "c"]])
    exa = Reaction("EX_a")
    exa.add_metabolites({m.metabolites.a: 1})
    b2c = Reaction("b2c")
    b2c.add_metabolites({m.metabolites.b: -1, m.metabolites.c: 1})
    dmc = Reaction("DM_c")
    dmc.add_metabolites({m.metabolites.c: -1})
    m.add_reactions([exa, b2c, dmc])
    m.objective = "DM_c"

    universal = Model()
    a2b = Reaction("a2b")
    a2d = Reaction("a2d")
    universal.add_reactions([a2b, a2d])
    a2b.build_reaction_from_string("a --> b", verbose=False)
    a2d.build_reaction_from_string("a --> d", verbose=False)

    # # GrowMatch
    # result = gapfilling.growMatch(m, universal)[0]
    result = gapfill(m, universal)[0]
    assert len(result) == 1
    assert result[0].id == "a2b"

    # # SMILEY
    # result = gapfilling.SMILEY(m, "b", universal)[0]
    with m:
        m.objective = m.add_boundary(m.metabolites.b, type="demand")
        result = gapfill(m, universal)[0]
        assert len(result) == 1
        assert result[0].id == "a2b"

    # # 2 rounds of GrowMatch with exchange reactions
    # result = gapfilling.growMatch(m, None, ex_rxns=True, iterations=2)
    result = gapfill(m, None, exchange_reactions=True, iterations=2)
    assert len(result) == 2
    assert len(result[0]) == 1
    assert len(result[1]) == 1
    assert {i[0].id for i in result} == {"EX_b", "EX_c"}

    # # Gapfilling solution adds metabolites not present in original model
    # test for when demand = T
    # a demand reaction must be added to clear new metabolite
    universal_noDM = Model()
    a2b = Reaction("a2b")
    universal_noDM.add_reactions([a2b])
    a2b.build_reaction_from_string("a --> b + d", verbose=False)
    result = gapfill(m,
                     universal_noDM,
                     exchange_reactions=False,
                     demand_reactions=True)[0]
    # add reaction a2b and demand reaction to clear met d
    assert len(result) == 2
    assert "a2b" in [x.id for x in result]

    # test for when demand = False
    # test for when metabolites are added to the model and
    # must be cleared by other reactions in universal model
    # (i.e. not necessarily a demand reaction)
    universal_withDM = universal_noDM.copy()
    d_dm = Reaction("d_dm")
    universal_withDM.add_reactions([d_dm])
    d_dm.build_reaction_from_string("d -->", verbose=False)
    result = gapfill(m,
                     universal_withDM,
                     exchange_reactions=False,
                     demand_reactions=False)[0]
    assert len(result) == 2
    assert "a2b" in [x.id for x in result]

    # somewhat bigger model
    universal = Model("universal_reactions")
    with salmonella as model:
        for i in [i.id for i in model.metabolites.f6p_c.reactions]:
            reaction = model.reactions.get_by_id(i)
            universal.add_reactions([reaction.copy()])
            model.remove_reactions([reaction])
        gf = GapFiller(model,
                       universal,
                       penalties={"TKT2": 1e3},
                       demand_reactions=False)
        solution = gf.fill()
        assert "TKT2" not in {r.id for r in solution[0]}
        assert gf.validate(solution[0])