def add_pfba(model, objective=None, fraction_of_optimum=1.0): """Add pFBA objective Add objective to minimize the summed flux of all reactions to the current objective. See Also ------- pfba Parameters ---------- model : cobra.Model The model to add the objective to objective : An objective to set in combination with the pFBA objective. fraction_of_optimum : float Fraction of optimum which must be maintained. The original objective reaction is constrained to be greater than maximal_value * fraction_of_optimum. """ if objective is not None: model.objective = objective if model.solver.objective.name == '_pfba_objective': raise ValueError('model already has pfba objective') sutil.fix_objective_as_constraint(model, fraction=fraction_of_optimum) reaction_variables = ((rxn.forward_variable, rxn.reverse_variable) for rxn in model.reactions) variables = chain(*reaction_variables) pfba_objective = model.problem.Objective(add( [mul((sympy.singleton.S.One, variable)) for variable in variables]), direction='min', sloppy=True, name="_pfba_objective") set_objective(model, pfba_objective)
def add_pfba(model, objective=None, fraction_of_optimum=1.0): """Add pFBA objective Add objective to minimize the summed flux of all reactions to the current objective. See Also ------- pfba Parameters ---------- model : cobra.Model The model to add the objective to objective : An objective to set in combination with the pFBA objective. fraction_of_optimum : float Fraction of optimum which must be maintained. The original objective reaction is constrained to be greater than maximal_value * fraction_of_optimum. """ if objective is not None: model.objective = objective if model.solver.objective.name == "_pfba_objective": raise ValueError("The model already has a pFBA objective.") sutil.fix_objective_as_constraint(model, fraction=fraction_of_optimum) reaction_variables = ((rxn.forward_variable, rxn.reverse_variable) for rxn in model.reactions) variables = chain(*reaction_variables) model.objective = model.problem.Objective(Zero, direction="min", sloppy=True, name="_pfba_objective") model.objective.set_linear_coefficients({v: 1.0 for v in variables})
def add_pfba(model, objective=None, fraction_of_optimum=1.0): """Add pFBA objective Add objective to minimize the summed flux of all reactions to the current objective. See Also ------- pfba Parameters ---------- model : cobra.Model The model to add the objective to objective : An objective to set in combination with the pFBA objective. fraction_of_optimum : float Fraction of optimum which must be maintained. The original objective reaction is constrained to be greater than maximal_value * fraction_of_optimum. """ if objective is not None: model.objective = objective if model.solver.objective.name == '_pfba_objective': raise ValueError('The model already has a pFBA objective.') sutil.fix_objective_as_constraint(model, fraction=fraction_of_optimum) reaction_variables = ((rxn.forward_variable, rxn.reverse_variable) for rxn in model.reactions) variables = chain(*reaction_variables) model.objective = model.problem.Objective( Zero, direction='min', sloppy=True, name="_pfba_objective") model.objective.set_linear_coefficients(dict.fromkeys(variables, 1.0))
def test_fix_objective_as_constraint_minimize(self, solver, model): model.reactions.Biomass_Ecoli_core.bounds = (0.1, 0.1) minimize_glucose = model.problem.Objective( model.reactions.EX_glc__D_e.flux_expression, direction='min') su.set_objective(model, minimize_glucose) su.fix_objective_as_constraint(model) fx_name = 'Fixed_objective_{}'.format(model.objective.name) constr = model.constraints assert (constr[fx_name].lb, constr[fx_name].ub) == (None, model.solver.objective.value)
def test_fix_objective_as_constraint_minimize(model, solver): model.solver = solver model.reactions.Biomass_Ecoli_core.bounds = (0.1, 0.1) minimize_glucose = model.problem.Objective( model.reactions.EX_glc__D_e.flux_expression, direction='min') su.set_objective(model, minimize_glucose) su.fix_objective_as_constraint(model) fx_name = 'fixed_objective_{}'.format(model.objective.name) constr = model.constraints # Ensure that a solution exists on non-GLPK solvers. model.slim_optimize() assert (constr[fx_name].lb, constr[fx_name].ub) == (None, model.solver.objective.value)
def test_fix_objective_as_constraint(solver, model): model.solver = solver with model as m: su.fix_objective_as_constraint(model, 1.0) constraint_name = m.constraints[-1] assert abs(m.constraints[-1].expression - m.objective.expression) < 1e-6 assert constraint_name not in m.constraints su.fix_objective_as_constraint(model) constraint_name = model.constraints[-1] assert abs(model.constraints[-1].expression - model.objective.expression) < 1e-6 assert constraint_name in model.constraints
def test_fix_objective_as_constraint(self, solver, model): model.solver = solver with model as m: su.fix_objective_as_constraint(model, 1.0) constraint_name = m.constraints[-1] assert abs(m.constraints[-1].expression - m.objective.expression) < 1e-6 assert constraint_name not in m.constraints su.fix_objective_as_constraint(model) constraint_name = model.constraints[-1] assert abs(model.constraints[-1].expression - model.objective.expression) < 1e-6 assert constraint_name in model.constraints
def test_fix_objective_as_constraint(solver: str, model: "Model") -> None: """Test fixing present objective as a constraint.""" model.solver = solver with model as m: su.fix_objective_as_constraint(model, 1.0) constraint_name = m.constraints[-1] assert abs(m.constraints[-1].expression - m.objective.expression) < 1e-6 assert constraint_name not in m.constraints su.fix_objective_as_constraint(model) constraint_name = model.constraints[-1] assert abs(model.constraints[-1].expression - model.objective.expression) < 1e-6 assert constraint_name in model.constraints
def test_fix_objective_as_constraint_minimize(self, model, solver): model.solver = solver model.reactions.Biomass_Ecoli_core.bounds = (0.1, 0.1) minimize_glucose = model.problem.Objective( model.reactions.EX_glc__D_e.flux_expression, direction='min') su.set_objective(model, minimize_glucose) su.fix_objective_as_constraint(model) fx_name = 'fixed_objective_{}'.format(model.objective.name) constr = model.constraints # Ensure that a solution exists on non-GLPK solvers. model.slim_optimize() assert (constr[fx_name].lb, constr[fx_name].ub) == ( None, model.solver.objective.value)
def add_pfba_Weighted(model, weightings = None, objective=None, fraction_of_optimum=1.0): """ ################################################################################# # This function is a modified version of cobrapy add_pfba function # # # ################################################################################# Add pFBA objective Add objective to minimize the summed flux of all reactions to the current objective. See Also ------- pfba Parameters ---------- model : cobra.Model The model to add the objective to objective : An objective to set in combination with the pFBA objective. fraction_of_optimum : float Fraction of optimum which must be maintained. The original objective reaction is constrained to be greater than maximal_value * fraction_of_optimum. """ if weightings == None: weightings = getweightings(model) if objective is not None: model.objective = objective if model.solver.objective.name == '_pfba_objective': raise ValueError('The model already has a pFBA objective.') sutil.fix_objective_as_constraint(model, fraction=fraction_of_optimum) reaction_variables = ((rxn.forward_variable, rxn.reverse_variable) for rxn in model.reactions) variables = chain(*reaction_variables) model.objective = model.problem.Objective( Zero, direction='min', sloppy=True, name="_pfba_objective") #print([v for v in variables]) tempDict = dict() for v in variables: w = str(v).split("=")[1].replace(" ","").replace("<","") found=False for rxn in weightings.keys(): if w.__contains__(rxn): tempDict[v]=weightings[rxn] found=True break if not found: print("Weightings for reaction "+w+" not found, so assuming weighting = 1") tempDict[v] = 1 model.objective.set_linear_coefficients(tempDict)
def add_pfba(model, objective=None, fraction_of_optimum=1.0): if objective is not None: model.objective = objective if model.solver.objective.name == '_pfba_objective': raise ValueError('The model already has a pFBA objective.') sutil.fix_objective_as_constraint(model, fraction=fraction_of_optimum) reaction_variables = ((rxn.forward_variable, rxn.reverse_variable) for rxn in model.reactions) variables = chain(*reaction_variables) model.objective = model.problem.Objective(Zero, direction='min', sloppy=True, name="_pfba_objective") model.objective.set_linear_coefficients({v: 1.0 for v in variables})
def test_fix_objective_as_constraint_minimize(model: "Model", solver: str) -> None: """Test fixing present objective as a constraint but as a minimization.""" model.solver = solver model.reactions.Biomass_Ecoli_core.bounds = (0.1, 0.1) minimize_glucose = model.problem.Objective( model.reactions.EX_glc__D_e.flux_expression, direction="min") su.set_objective(model, minimize_glucose) su.fix_objective_as_constraint(model) fx_name = f"fixed_objective_{model.objective.name}" constr = model.constraints # Ensure that a solution exists on non-GLPK solvers. model.slim_optimize() assert (constr[fx_name].lb, constr[fx_name].ub) == ( None, model.solver.objective.value, )
def pFBA_by_percent_of_optimum(model, rxn_ids, optimum_fraction, exclude_from_min=True): # Minimize flux through all reactions such that the fraction of objective optimum is still achieved remove_ids = set() with model as m: # Fix previous objective as constraint with threshold of predefined fraction of uncontexualized flux solver.fix_objective_as_constraint(m, fraction=optimum_fraction) # Formulate pFBA objective if exclude_from_min == True: rxn_vars = ((rxn.forward_variable, rxn.reverse_variable) for rxn in m.reactions if rxn.id not in rxn_ids) excl_rxn_vars = ((rxn.forward_variable, rxn.reverse_variable) for rxn in m.reactions if rxn.id in rxn_ids) excl_rxn_vars = chain(*excl_rxn_vars) else: rxn_vars = ((rxn.forward_variable, rxn.reverse_variable) for rxn in m.reactions) rxn_vars = chain(*rxn_vars) pfba_obj = m.problem.Objective(Zero, direction='min', sloppy=True) m.objective = pfba_obj # Set linear coefficients based on if they are to be excluded from minimization m.objective.set_linear_coefficients({x: 1.0 for x in rxn_vars}) if exclude_from_min == True: m.objective.set_linear_coefficients({y: 0.0 for y in excl_rxn_vars}) # Identify those reactions of interest that carry flux in pFBA solution solution = m.optimize() fluxes = solution.fluxes for reaction, flux in fluxes.items(): if reaction in rxn_ids and abs(flux) < 1e-6: remove_ids |= set([reaction]) # Report percentage to be pruned in each step #print(str(round(((float(len(remove_ids)) / float(len(rxn_ids))) * 100.0), 2)) + '%') return remove_ids
def pfba_gapfill(model, reaction_bag, obj=None, obj_lb=10., obj_constraint=False, iters=1, tasks=None, task_lb=0.05, add_exchanges=True, extracellular='e', cores=4): ''' Function that utilizes iterations of pFBA solution with a universal reaction bag in order to gapfill a model. Parameters ---------- model : cobra.Model Model to be gapfilled reaction_bag : cobra.Model Reaction bag reference to use during gapfilling obj : string Reaction ID for objective function in model to be gapfilled. obj_lb : float Lower bound for objective function obj_constraint : bool Sets objective as contstraint which must be maximized tasks : list or None List of reactions IDs (strings) of metabolic tasks to set a minimum lower bound for task_lb : float Lower bound for any metabolic tasks iters : int Number of gapfilling rounds. Unique reactions from each round are saved and the union is added simulatneously to the model add_exchanges : bool Identifies extracellular metabolites added during gapfilling that are not associated with exchange reactions and creates them extracellular : string Label for extracellular compartment of model cores : int Number of processors to utilize during flux sampling ''' start_time = time.time() # Save some basic network info for downstream membership testing orig_rxn_ids = set([str(x.id) for x in model.reactions]) orig_cpd_ids = set([str(y.id) for y in model.metabolites]) univ_rxn_ids = set([str(z.id) for z in reaction_bag.reactions]) # Find overlap in model and reaction bag overlap_rxn_ids = univ_rxn_ids.intersection(orig_rxn_ids) # Get model objective reaction ID if obj == None: obj = get_objective(model) else: obj = obj # Modify universal reaction bag new_rxn_ids = set() print('Creating universal model...') with reaction_bag as universal: # Remove overlapping reactions from universal bag, and reset objective if needed for rxn in overlap_rxn_ids: universal.reactions.get_by_id(rxn).remove_from_model() # Set objective in universal if told by user # Made constraint as fraction of minimum in next step if obj_constraint: universal.add_reactions([model.reactions.get_by_id(obj)]) universal.objective = obj orig_rxn_ids.remove(obj) orig_rxns = [] for rxn in orig_rxn_ids: orig_rxns.append(copy.deepcopy(model.reactions.get_by_id(rxn))) else: orig_rxns = list(copy.deepcopy(model.reactions)) # Add pFBA to universal model and add model reactions add_pfba(universal) #universal = copy.deepcopy(universal) # reset solver universal.add_reactions(orig_rxns) # If previous objective not set as constraint, set minimum lower bound if not obj_constraint: universal.reactions.get_by_id(obj).lower_bound = obj_lb # Set metabolic tasks that must carry flux in gapfilled solution if tasks != None: for task in tasks: try: universal.reactions.get_by_id(task).lower_bound = task_lb except: print(task + 'not found in model. Ignoring.') continue # Run FBA and save solution print('Optimizing model with combined reactions...') solution = universal.optimize() if iters > 1: print('Generating flux sampling object...') sutil.fix_objective_as_constraint(universal, fraction=0.99) optgp_object = OptGPSampler(universal, processes=cores) # Assess the sampled flux distributions print('Sampling ' + str(iters) + ' flux distributions...') flux_samples = optgp_object.sample(iters) rxns = list(flux_samples.columns) for distribution in flux_samples.iterrows(): for flux in range(0, len(list(distribution[1]))): if abs(list(distribution[1])[flux]) > 1e-6: new_rxn_ids |= set([rxns[flux]]).difference(orig_rxn_ids) else: rxns = list(solution.fluxes.index) fluxes = list(solution.fluxes) for flux in range(0, len(fluxes)): if abs(fluxes[flux]) > 1e-6: new_rxn_ids |= set([rxns[flux]]) # Screen new reaction IDs if obj in new_rxn_ids: new_rxn_ids.remove(obj) for rxn in orig_rxn_ids: try: new_rxn_ids.remove(rxn) except: continue # Get reactions and metabolites to be added to the model print('Gapfilling model...') new_rxns = copy.deepcopy([reaction_bag.reactions.get_by_id(rxn) for rxn in new_rxn_ids]) new_cpd_ids = set() for rxn in new_rxns: new_cpd_ids |= set([str(x.id) for x in list(rxn.metabolites)]) new_cpd_ids = new_cpd_ids.difference(orig_cpd_ids) new_cpds = copy.deepcopy([reaction_bag.metabolites.get_by_id(cpd) for cpd in new_cpd_ids]) # Copy model and gapfill new_model = copy.deepcopy(model) new_model.add_metabolites(new_cpds) new_model.add_reactions(new_rxns) # Identify extracellular metabolites with no exchanges if add_exchanges == True: new_exchanges = extend_exchanges(new_model, new_cpd_ids, extracellular) if len(new_exchanges) > 0: new_rxn_ids |= new_exchanges duration = int(round(time.time() - start_time)) print('Took ' + str(duration) + ' seconds to gapfill ' + str(len(new_rxn_ids)) + \ ' reactions and ' + str(len(new_cpd_ids)) + ' metabolites.') new_obj_val = new_model.slim_optimize() if new_obj_val > 1e-6: print('Gapfilled model objective now carries flux (' + str(new_obj_val) + ').') else: print('Gapfilled model objective still does not carry flux.') return new_model