Beispiel #1
0
    def simplify(self):
        inactive = [r_id for r_id, states in self.reaction_states.items() if not any(states)]
        self.model.remove_reactions(inactive)
        del_metabolites = disconnected_metabolites(self.model)
        self.model.remove_metabolites(del_metabolites)

        for r_id in inactive:
            del self.reaction_states[r_id]
Beispiel #2
0
def filter_reactions_by_kingdoms(model,
                                 kingdoms,
                                 kingdom_map,
                                 exclusive=False,
                                 inplace=False):
    """ Filter reactions in model by Kingdoms.
    A reaction is considered valid for a given Kingdom if it is present in at least one model from that Kingdom.

    Args:
        model (CBModel): model
        kingdoms (set): Kingdom names
        kingdom_map (dict): mapping between model ids and kingdoms
        exclusive (bool): only accept reactions *exclusive* to given Kingdom (default: False)
        inplace (bool): automatically remove invalid reactions from model (default: False)

    Returns:
        list: list of reactions that belong to the given Kingdom

    """

    valid = []
    invalid = []

    for r_id, rxn in model.reactions.items():
        model_ids = rxn.metadata['BiGG models'].split(';')
        model_kingdoms = set([kingdom_map[model_id] for model_id in model_ids])

        if exclusive and model_kingdoms == kingdoms:
            valid.append(r_id)
        elif not exclusive and len(model_kingdoms & kingdoms) > 0:
            valid.append(r_id)
        else:
            invalid.append(r_id)

    if inplace:
        model.remove_reactions(invalid)
        model.remove_metabolites(disconnected_metabolites(model))

    else:
        return valid
Beispiel #3
0
def carve_model(model, reaction_scores, outputfile=None, min_growth=0.1, min_atpm=0.1, flavor=None, inplace=False,
                default_score=-0.1, uptake_score=1.0, soft_score=1.0,
                soft_constraints=None, hard_constraints=None,
                init_env=None, debug_output=None, eps=1e-5, feast=1e-6, opti=1e-6):
    """ Reconstruct a metabolic model using the CarveMe approach.
    Args:
        model (CBModel): universal model
        reaction_scores (pandas.DataFrame): reaction scores
        outputfile (str): write model to SBML file (optional)
        flavor (str): SBML flavor ('cobra' or 'fbc2', optional)
        inplace (bool): Change model in place (default: True)
        default_score (float): penalty for non-annotated intracellular reactions (default: -1.0)
        uptake_score (float): penalty for utilization of extracellular compounds (default: 0.0)
        soft_score (float): score for soft constraints (default: 1.0)
        soft_constraints (dict): dictionary from reaction id to expected flux direction (-1, 1, 0)
        hard_constraints (dict): dictionary of flux bounds
        init_env (Environment): initialize final model with given Environment (optional)
    Returns:
        CBModel: reconstructed model
    """

    scores = reaction_scores

    if default_score is None:
        default_score = -1.0

    if uptake_score is None:
        uptake_score = 0.0

    if soft_score is None:
        soft_score = 1.0

    if soft_constraints:
        not_in_model = set(soft_constraints) - set(model.reactions)
        if not_in_model:
            soft_constraints = {r_id: val for r_id, val in soft_constraints.items() if r_id in model.reactions}
            warnings.warn("Soft constraints contain reactions not in the model:\n" + "\n".join(not_in_model))

    if hard_constraints:
        not_in_model = set(hard_constraints) - set(model.reactions)
        if not_in_model:
            hard_constraints = {r_id: (lb, ub) for r_id, (lb, ub) in hard_constraints.items() if
                                r_id in model.reactions}
            warnings.warn("Hard constraints contain reactions not in the model:\n" + "\n".join(not_in_model))
    reconstructed_model = model.copy()
    solutions = minmax_reduction(reconstructed_model, scores, eps=eps, default_score=default_score, uptake_score=uptake_score,
                                 soft_score=soft_score, soft_constraints=soft_constraints, min_growth=min_growth,
                                 min_atpm=min_atpm,
                                 hard_constraints=hard_constraints, debug_output=debug_output, feast=feast, opti=opti)

    solutions = select_best_models(solutions)

    models = []
    i = 0
    objective = 0
    try:
        for sol in solutions:
            reconstructed_model = model.copy()
            print("Solution " + str(i))
            print(sol)
            i = i + 1
            inactive = inactive_reactions(reconstructed_model, sol, reaction_scores)
            reconstructed_model.remove_reactions(inactive)
            del_metabolites = disconnected_metabolites(reconstructed_model)
            reconstructed_model.remove_metabolites(del_metabolites)
            print(FBA(reconstructed_model, objective={'R_BIOMASS': 1}))
            models.append(reconstructed_model)
            objective = objective + sol.fobj
        objective = objective / len(solutions)
    except:
        reconstructed_model = model.copy()
        print(solutions)
        inactive = inactive_reactions(reconstructed_model, solutions, reaction_scores)
        reconstructed_model.remove_reactions(inactive)
        del_metabolites = disconnected_metabolites(reconstructed_model)
        reconstructed_model.remove_metabolites(del_metabolites)
        print(FBA(reconstructed_model, objective={'R_BIOMASS': 1}))
        models.append(reconstructed_model)
        objective = solutions.fobj

    return objective, models
Beispiel #4
0
def carve_model(model,
                reaction_scores,
                outputfile=None,
                flavor=None,
                inplace=True,
                default_score=-1.0,
                uptake_score=0.0,
                soft_score=1.0,
                soft_constraints=None,
                hard_constraints=None,
                ref_model=None,
                ref_score=0.0,
                init_env=None,
                debug_output=None):
    """ Reconstruct a metabolic model using the CarveMe approach.

    Args:
        model (CBModel): universal model
        reaction_scores (pandas.DataFrame): reaction scores
        outputfile (str): write model to SBML file (optional)
        flavor (str): SBML flavor ('cobra' or 'fbc2', optional)
        inplace (bool): Change model in place (default: True)
        default_score (float): penalty for non-annotated intracellular reactions (default: -1.0)
        uptake_score (float): penalty for utilization of extracellular compounds (default: 0.0)
        soft_score (float): score for soft constraints (default: 1.0)
        soft_constraints (dict): dictionary from reaction id to expected flux direction (-1, 1, 0)
        hard_constraints (dict): dictionary of flux bounds
        init_env (Environment): initialize final model with given Environment (optional)

    Returns:
        CBModel: reconstructed model
    """

    if not inplace:
        model = model.copy()

    scores = dict(reaction_scores[['reaction', 'normalized_score']].values)

    if soft_constraints:
        not_in_model = set(soft_constraints) - set(model.reactions)
        if not_in_model:
            soft_constraints = {
                r_id: val
                for r_id, val in soft_constraints.items()
                if r_id in model.reactions
            }
            warnings.warn(
                "Soft constraints contain reactions not in the model:\n" +
                "\n".join(not_in_model))

    if hard_constraints:
        not_in_model = set(hard_constraints) - set(model.reactions)
        if not_in_model:
            hard_constraints = {
                r_id: (lb, ub)
                for r_id, (lb, ub) in hard_constraints.items()
                if r_id in model.reactions
            }
            warnings.warn(
                "Hard constraints contain reactions not in the model:\n" +
                "\n".join(not_in_model))

    if ref_model:
        ref_reactions = set(model.reactions) & set(ref_model.reactions)
    else:
        ref_reactions = None

    sol = minmax_reduction(model,
                           scores,
                           default_score=default_score,
                           uptake_score=uptake_score,
                           soft_score=soft_score,
                           soft_constraints=soft_constraints,
                           hard_constraints=hard_constraints,
                           ref_reactions=ref_reactions,
                           ref_score=ref_score,
                           debug_output=debug_output)

    if sol.status == Status.OPTIMAL:
        inactive = inactive_reactions(model, sol)
    else:
        print("MILP solver failed: {}".format(sol.message))
        return

    if debug_output:
        pd.DataFrame.from_dict(sol.values, orient='index').to_csv(
            debug_output + '_milp_solution.tsv', sep='\t', header=False)

    model.remove_reactions(inactive)

    del_metabolites = disconnected_metabolites(model)
    model.remove_metabolites(del_metabolites)

    for i, row in reaction_scores.iterrows():
        r_id = row['reaction']
        if r_id in model.reactions:
            try:
                gpr = parse_gpr_rule(row['GPR'], prefix='G_')
                model.set_gpr_association(r_id, gpr, add_genes=True)
            except:
                print('Failed to parse:', row['GPR'])

    cleanup_metadata(model)

    if init_env:
        init_env.apply(model, inplace=True, warning=False)

    if outputfile:
        save_cbmodel(model, outputfile, flavor=flavor)

    return model
Beispiel #5
0
def gapFill(model,
            universe,
            constraints=None,
            min_growth=0.1,
            scores=None,
            inplace=True,
            bigM=1e3,
            abstol=1e-9,
            solver=None,
            tag=None):
    """ Gap Fill a metabolic model by adding reactions from a reaction universe

    Args:
        model (CBModel): original model
        universe (CBModel): universe model
        constraints (dict): additional constraints (optional)
        min_growth (float): minimum growth rate (default: 0.1)
        scores (dict): reaction scores (optional, see notes)
        inplace (bool): modify given model in place (default: True)
        bigM (float): maximal reaction flux (default: 1000)
        abstol (float): minimum threshold to consider a reaction active (default: 1e-9)
        solver (Solver): solver instance (optional)
        tag (str): add a metadata tag to gapfilled reactions (optional)

    Returns:
        CBModel: gap filled model (if inplace=False)

    Notes:
        Scores can be used to make some reactions more likely to be included.
        Scored reactions have a penalty of 1/(1+score), which varies between [0, 1].
        Unscored reactions have a penalty of 1.
    """

    new_reactions = set(universe.reactions) - set(model.reactions)

    model = merge_models(model, universe, inplace, tag=tag)

    for r_id in new_reactions:
        if r_id.startswith('R_EX'):
            model.set_lower_bound(r_id, 0)

    if not solver:
        solver = solver_instance(model)

    if not scores:
        scores = {}

    if not hasattr(solver, '_gapfill_flag'):
        solver._gapfill_flag = True

        for r_id in new_reactions:
            solver.add_variable('y_' + r_id,
                                0,
                                1,
                                vartype=VarType.BINARY,
                                update_problem=False)

        solver.update()

        for r_id in new_reactions:
            solver.add_constraint('lb_' + r_id, {
                r_id: 1,
                'y_' + r_id: bigM
            },
                                  '>',
                                  0,
                                  update_problem=False)
            solver.add_constraint('ub_' + r_id, {
                r_id: 1,
                'y_' + r_id: -bigM
            },
                                  '<',
                                  0,
                                  update_problem=False)

        biomass = model.biomass_reaction
        solver.add_constraint('min_growth', {biomass: 1},
                              '>',
                              min_growth,
                              update_problem=False)

        solver.update()

    objective = {
        'y_' + r_id: 1.0 / (1.0 + scores.get(r_id, 0.0))
        for r_id in new_reactions
    }

    solution = solver.solve(linear=objective,
                            minimize=True,
                            constraints=constraints)

    if solution.status == Status.OPTIMAL:

        inactive = [
            r_id for r_id in new_reactions
            if abs(solution.values[r_id]) < abstol
        ]

    else:
        #        inactive = new_reactions
        raise RuntimeError('Failed to gapfill model for medium {}'.format(tag))

    model.remove_reactions(inactive)
    del_metabolites = disconnected_metabolites(model)
    model.remove_metabolites(del_metabolites)

    if not inplace:
        return model