Пример #1
0
def _formulate_imat(model, up_regulated, down_regulated, epsilon = 1):
    """ Formulates iMAT problem

    Arguments:
        model: Model -- a metabolic constraint-based model
        up_regulated: dict (of str of float): up_regulated reactions with score
        down_regulated: dict (of str of float): down_regulated reactions with score
    """
    # Constants
    active_pos = 'active_+'
    active_neg = 'active_-'
    inactive = 'inactive_+'

    # Initialize model
    solver = get_solver()
    solver.add_variables(model.get_reactions_bounds())
    solver.add_constraints(model.s)

    # Initialize binary variables
    for name in model.reactions:
        solver.add_variable(name + active_pos, var_type=solver.BINARY)
        solver.add_variable(name + active_neg, var_type=solver.BINARY)

        if name in down_regulated:
            solver.add_variable(name + inactive, var_type=solver.BINARY)

    # Update model wiht binary variables
    solver.update()

    # Add binary variables constraints
    for name in model.reactions:
        lb, ub = model.get_reaction_bounds(name)

        # Vi + Yi+ (lb - epsilon) >= lb
        solver.add_constraint('imat_up_lower_bound_' + name + active_pos, [(name, 1), (name + active_pos, lb), (name + active_pos, -epsilon)], solver.GREATER_EQUAL, lb)

        # Vi + Yi- (ub + epsilon) <= ub
        solver.add_constraint('imat_up_upper_bound_' + name + active_neg, [(name, 1), (name + active_neg, ub), (name + active_neg, epsilon)], solver.LESS_EQUAL, ub)

        if name in down_regulated:
            # lb (1 - Yi+) <= Vi
            solver.add_constraint('imat_down_lower_bound_' + name + inactive + '_1', [(name, 1), (name + inactive, lb)], solver.GREATER_EQUAL, lb)

            # Vi <= ub (1 - Yi+)
            solver.add_constraint('imat_down_upper_bound_' + name + inactive + '_2', [(name, 1), (name + inactive, ub)], solver.LESS_EQUAL, ub)

    # Set objective function, max: sum(up_pos + up_neg) + sum(down_pos)
    objective = []

    for name in up_regulated:
        objective.append((name + active_pos, 1))
        objective.append((name + active_neg, 1))

    for name in down_regulated:
        objective.append((name + inactive, 1))

    solver.set_objective(objective)

    return solver
Пример #2
0
def pFBA(model, objective=None, maximize=True, relax=0.999999):
    """ Performs a parsimonious flux balance analysis (pFBA)

    Arguments:
        model: Model -- a metabolic constraint-based model
        objective: dict(reaction: value) -- objective coefficients (optional)
        maximize: bool -- maximize or minimize (maximize by default)

    Returns:
        solution: Solution -- simulation solution
    """
    objective = model.get_objective() if objective is None else objective

    # Initialize model
    solver = get_solver()
    solver.add_variables(model.get_reactions_bounds())
    solver.add_constraints(model.s)

    # Perform FBA
    fba_solution = FBA(model, objective, maximize, solver)

    # Split reversible reactions
    for k, (lb, ub) in model.get_reactions_bounds().items():
        if lb < 0 < ub:
            solver.add_variable(k + '_neg', 0, abs(lb))
            solver.add_variable(k + '_pos', 0, ub)

    solver.update()

    for k, (lb, ub) in model.get_reactions_bounds().items():
        if lb < 0 < ub:
            solver.add_constraint(k + '_neg', {k: 1, k + '_neg': 1}, solver.GREATER_EQUAL, 0)
            solver.add_constraint(k + '_pos', {k: -1, k + '_pos': 1}, solver.GREATER_EQUAL, 0)

    # Constraint FBA objective to max value
    solver.add_constraint('fba_constraint', objective, solver.GREATER_EQUAL, fba_solution.obj_value * relax)

    # Set pFBA objective: min (internal reactions)
    pfba_objective = {}
    for k, (lb, ub) in model.get_reactions_bounds().items():
        if lb < 0 < ub:
            pfba_objective[k + '_neg'] = 1
            pfba_objective[k + '_pos'] = 1

        else:
            pfba_objective[k] = 1

    solver.set_objective(pfba_objective, False)

    # Run optimization
    pfba_solution = solver.optimize()

    # Merge splited reactions values
    for k, (lb, ub) in model.get_reactions_bounds().items():
        if lb < 0 < ub:
            del pfba_solution.values[k + '_neg']
            del pfba_solution.values[k + '_pos']

    return pfba_solution
Пример #3
0
def FVA(model, reactions=None, objective=None, percentage=None, return_simulations=False, verbose=1):
    """ Performs a Flux Variability Analysis

    Arguements:
        model: Model -- a metabolic constrain-based model
        reaction: list (of str) -- list of reactions to analyse (optional)
        objective: dict(reaction: value) -- objective coefficients (optional)
        percentage: float -- percentage of the objective to keep (optional)

    Returns:
        solution: dict (of str of tuple) -- dict with each reaction and the min and max flux value
    """
    # Initialise model
    solver = get_solver()
    solver.add_variables(model.get_reactions_bounds())
    solver.add_constraints(model.s)

    # Constraint with defined objective
    if (objective is not None) and (percentage is not None):
        solution = FBA(model, objective, True, solver)
        solver.add_constraint('objective_constraint', objective, solver.EQUAL, solution.obj_value * percentage)

    # Reactions to analyse
    reactions = model.reactions.keys() if reactions is None else reactions

    # Maximize and minimize each reaction at a time
    fva, solutions = {}, DataFrame(np.NaN, index=reactions, columns={'_'.join([reac, obj]) for reac in reactions for obj in {'min', 'max'}})

    for reaction in reactions:
        # Minimize
        min_solution = FBA(model, {reaction: 1}, False, solver)
        min_value = None

        if min_solution.solution_status == solver.OPTIMAL:
            min_value = min_solution.obj_value

        # Maximize
        max_solution = FBA(model, {reaction: 1}, True, solver)
        max_value = None

        if max_solution.solution_status == solver.OPTIMAL:
            max_value = max_solution.obj_value

        # Store solution
        fva[reaction] = [min_value, max_value]

        if return_simulations:
            solutions['_'.join([reaction, 'min'])] = Series(min_solution.values.values(), index=min_solution.values.keys())[reactions]
            solutions['_'.join([reaction, 'max'])] = Series(max_solution.values.values(), index=max_solution.values.keys())[reactions]

    return (fva, solutions) if return_simulations else fva
Пример #4
0
def FBA(model, objective=None, maximize=True, solver=None, opt_abs_values=False):
    """ Performs a Flux Balance Analysis simulation

    Arguments:
        model: Model -- a metabolic constraint-based model
        objective: dict(reaction: value) -- objective coefficients (optional)
        maximize: bool -- maximize or minimize (maximize by default)
        solver: Solver -- Solver instance, reuse formulated problem

    Returns:
        solution: Solution -- simulation solution
    """
    objective = model.get_objective() if objective is None else objective

    # Initialize model
    if solver is None:
        solver = get_solver()
        solver.add_variables(model.get_reactions_bounds())
        solver.add_constraints(model.s)

    # Optimisation with absolute objective values
    if opt_abs_values:
        # Split reversible reactions
        for k, (lb, ub) in model.get_reactions_bounds().items():
            if lb < 0 < ub:
                solver.add_variable(k + '_neg', 0, abs(lb))
                solver.add_variable(k + '_pos', 0, ub)

        solver.update()

        for k, (lb, ub) in model.get_reactions_bounds().items():
            if lb < 0 < ub:
                solver.add_constraint(k + '_neg', {k: 1, k + '_neg': 1}, solver.GREATER_EQUAL, 0)
                solver.add_constraint(k + '_pos', {k: -1, k + '_pos': 1}, solver.GREATER_EQUAL, 0)

        # Set objective: min/max: abs(objective)
        abs_objective = {}
        for k, (lb, ub) in model.get_reactions_bounds(objective.keys()).items():
            if lb < 0 < ub:
                abs_objective[k + '_neg'] = 1
                abs_objective[k + '_pos'] = 1

            else:
                abs_objective[k] = 1

        objective = abs_objective.copy()

    # Set objective function
    solver.set_objective(objective, maximize)

    # Run optimization
    solution = solver.optimize()

    # If optimisation with absolute objective values
    if opt_abs_values:
        # Merge splited reactions values
        for k, (lb, ub) in model.get_reactions_bounds().items():
            if lb < 0 < ub:
                del solution.values[k + '_neg']
                del solution.values[k + '_pos']

    return solution
Пример #5
0
def min_differences(model, reference=None, multipliers={}, mode=''):
    """ Minimizes the absolute difference between the model simulation and the given flux values.

    Arguments:
        model: Model -- a metabolic constraint-based model
        flux_values: dict (of str and float): reference flux values
        multipliers: dict (of str and float): reactions objective multipliers
        mode: ['', 'backward', 'forward']: minimise a given direction of the reversible reactions
    """
    # Run pFBA if reference is missing
    if reference is None:
        reference = pFBA(model).values

    # Initialize model
    solver = get_solver()
    solver.add_variables(model.get_reactions_bounds())
    solver.add_constraints(model.s)

    # Split reversible reactions
    for reaction, (lb, ub) in model.get_reactions_bounds().items():
        if reaction in reference and lb < 0 < ub:
            solver.add_variable(reaction + '_backward', 0, abs(lb))
            solver.add_variable(reaction + '_forward', 0, ub)

    # Create objective variables
    objective = []
    for reaction in reference:
        # Get reaction boundaries and multiplier
        lb, ub = model.get_reaction_bounds(reaction)
        r_mul = multipliers[reaction] if reaction in multipliers else 1

        # Create positive and negative variables for reversivle and non-reversible reactions
        reaction_vars = {reaction + s1 + s2 if lb < 0 < ub else reaction + s1 for s1 in ['_f_neg', '_f_pos'] for s2 in ['_backward', '_forward']}
        solver.add_variables_from_list(reaction_vars, lower_bound=0)

        # Add variables to objective function according to chosen mode
        objective.extend([(r, r_mul) for r in reaction_vars if r.endswith(mode)])

    # UPDATE variables then start adding constraints
    solver.update()

    # Add positive range constrains of splitted reactions
    for reaction, (lb, ub) in model.get_reactions_bounds().items():
        if reaction in reference and lb < 0 < ub:
            solver.add_constraint(reaction + '_backward', {reaction: 1, reaction + '_backward': 1}, solver.GREATER_EQUAL, 0)
            solver.add_constraint(reaction + '_forward', {reaction: -1, reaction + '_forward': 1}, solver.GREATER_EQUAL, 0)

    # Set difference constraints: F1 - V > -Vref; F2 + V > Vref
    for reaction, value in reference.items():
        # Get reaction boundaries
        lb, ub = model.get_reaction_bounds(reaction)

        # Create positive and negative variables for reversivle and non-reversible reactions
        if lb < 0 < ub:
            for s2 in ['_backward', '_forward']:
                solver.add_constraint(reaction + '_f_pos' + s2 + '_c', {reaction + '_f_pos' + s2: 1, reaction: -1}, solver.GREATER_EQUAL, -value)
                solver.add_constraint(reaction + '_f_neg' + s2 + '_c', {reaction + '_f_neg' + s2: 1, reaction: 1}, solver.GREATER_EQUAL, value)

        else:
            solver.add_constraint(reaction + '_f_pos' + '_c', {reaction + '_f_pos': 1, reaction: -1}, solver.GREATER_EQUAL, -value)
            solver.add_constraint(reaction + '_f_neg' + '_c', {reaction + '_f_neg': 1, reaction: 1}, solver.GREATER_EQUAL, value)

    # Set objective variables: min: F1 + F2
    solver.set_objective(objective, False)

    # Run optimization
    solution = solver.optimize()

    return solution