def fva(self) -> pd.DataFrame: model = self.read_model() result = fba(model) fluxes = result.fluxes try: fva_result = flux_variability_analysis( model, reactions=model.reactions, fraction_of_optimum=1.0 ) # type: FluxVariabilityResult df = fva_result.data_frame df_out = pd.DataFrame( { "model": self.model_path.name, "objective": self.objective_id, "reaction": df.index, "flux": fluxes, "status": CuratorConstants.STATUS_OPTIMAL, "minimum": df.lower_bound, "maximum": df.upper_bound, } ) except Exception as e: logger.error(f"{e}") df_out = pd.DataFrame( { "model": self.model_path.name, "objective": self.objective_id, "reaction": [r.id for r in model.reactions], "flux": fluxes, "status": CuratorConstants.STATUS_INFEASIBLE, "minimum": CuratorConstants.VALUE_INFEASIBLE, "maximum": CuratorConstants.VALUE_INFEASIBLE, } ) return df_out
def reaction_deletion(self) -> pd.DataFrame: model = self.read_model() reaction_status = [] reaction_values = [] for reaction in model.reactions: reaction_bounds = (reaction.lower_bound, reaction.upper_bound) reaction.bounds = (0, 0) # run fba try: result = fba(model) value = result.objective_value status = CuratorConstants.STATUS_OPTIMAL except Exception as e: logger.error(f"{e}") value = CuratorConstants.VALUE_INFEASIBLE status = CuratorConstants.STATUS_INFEASIBLE reaction_status.append(status) reaction_values.append(value) # restore bounds reaction.bounds = reaction_bounds[:] return pd.DataFrame( { "model": self.model_path.name, "objective": self.objective_id, "reaction": [r.id for r in model.reactions], "status": reaction_status, "value": reaction_values, } )
def optimize_models_cameo(model_paths: List[Path]) -> pd.DataFrame: """FBA optimization for all given models.""" results = [] n_models = len(model_paths) for k, path in enumerate(model_paths): # load model start_time = time.time() model = read_sbml_model(str(path)) load_time = time.time() - start_time # [s] # run optimization start_time = time.time() result = fba(model) simulate_time = time.time() - start_time # [s] objective_value = result.objective_value filename = path.name model = filename.split(".")[0] res = (model, objective_value, load_time, simulate_time) results.append(res) print("[{}/{}]".format(k, n_models), res) return pd.DataFrame(data=results, columns=("model", "objective_value", "load_time", "simulate_time"))
def write_results(): """optimize results and write out to a file""" from cameo import load_model, fba outF = open("KOFBAFluxes-2.txt","w") model = load_model('KOmodel.json') print(len(model.genes)) print(len(model.metabolites)) print(len(model.reactions)) # new_solution = model.optimize() fba_result = fba(model) print(fba_result) # print(fba_result.data_frame) print(len(fba_result.data_frame)) # print(model.reactions) print(dir(fba_result)) print(fba_result.data_frame) fbaD = fba_result.data_frame.T.to_dict() fbaCorrD = {} for keyS, valueF in fbaD.items(): fbaCorrD[keyS] = valueF["flux"] for keyS, valueF in fbaCorrD.items(): # print(keyS, valueF) outF.write(str(keyS) + ", " + str(valueF) + "\n")
def test_apply_designs(self, model, diff_fva): result = diff_fva.run() works = [] for strain_design in result: with model: strain_design.apply(model) try: solution = fba(model, objective="Biomass_Ecoli_core_N_lp_w_fsh_GAM_rp__Nmet2") works.append(solution["EX_succ_lp_e_rp_"] > 1e-6 and solution.objective_value > 1e-6) except Infeasible: works.append(False) assert any(works)
def evaluate_design(model, strain_design, pathway, aerobic, bpcy, pyield): with TimeMachine() as tm: if not aerobic and 'EX_o2_e' in model.reactions: model.reactions.EX_o2_e.change_bounds(lb=0, time_machine=tm) pathway.apply(model, time_machine=tm) strain_design.apply(model, time_machine=tm) try: solution = fba(model, objective=model.biomass) _bpcy = bpcy(model, solution, strain_design.targets) _pyield = pyield(model, solution, strain_design.targets) target_flux = solution.fluxes[pyield.product] biomass = solution.fluxes[bpcy.biomass] except SolveError: _bpcy, _pyield, target_flux, biomass = np.nan, np.nan, np.nan, np.nan return _bpcy, _pyield, target_flux, biomass
def fba(self, measured_metabolites, filter_by_subsystem=False, add_constraints=False): if add_constraints: self.increasing_metabolite_constrains(measured_metabolites) if measured_metabolites is not None: self.set_objective_coefficients(measured_metabolites) reactions = None if filter_by_subsystem: reactions = self.filter_reaction_by_subsystems() return fba(self, reactions=reactions)
def evaluate_design(model, strain_design, pathway, aerobic, bpcy, pyield): with model: if not aerobic and 'EX_o2_e' in model.reactions: model.reactions.EX_o2_e.lower_bound = 0 pathway.apply(model) strain_design.apply(model) try: solution = fba(model, objective=model.biomass) _bpcy = bpcy(model, solution, strain_design.targets) _pyield = pyield(model, solution, strain_design.targets) target_flux = solution.fluxes[pyield.product] biomass = solution.fluxes[bpcy.biomass] except OptimizationError: _bpcy, _pyield, target_flux, biomass = np.nan, np.nan, np.nan, np.nan return _bpcy, _pyield, target_flux, biomass
def test_apply_designs(self, model, diff_fva): result = diff_fva.run() works = [] for strain_design in result: with model: strain_design.apply(model) try: solution = fba( model, objective="Biomass_Ecoli_core_N_lp_w_fsh_GAM_rp__Nmet2" ) works.append(solution["EX_succ_lp_e_rp_"] > 1e-6 and solution.objective_value > 1e-6) except Infeasible: works.append(False) assert any(works)
def test_apply_designs(self, model): result = DifferentialFVA(model, model.reactions.EX_succ_lp_e_rp_, points=5).run() works = [] for strain_design in result: with TimeMachine() as tm: strain_design.apply(model, tm) try: solution = fba( model, objective="Biomass_Ecoli_core_N_lp_w_fsh_GAM_rp__Nmet2" ) works.append(solution["EX_succ_lp_e_rp_"] > 1e-6 and solution.objective_value > 1e-6) except Infeasible: works.append(False) assert any(works)
def _fba(model, analysis): '''! Private function - to simulate a model using Flux Balance Analysis (FBA) or FBA-related methods, with Cameo. @model String: Model acceptable by Cameo (see http://cameo.bio/02-import-models.html). @analysis String: Type of FBA to perform. Allowable types are FBA (standard flux balance analysis) and pFBA (parsimonious FBA). ''' import cameo if analysis == 'FBA': print('Run flux balance analysis on model %s' % str(model)) return cameo.fba(model) elif analysis == 'pFBA': print('Run parsimonious flux balance analysis on model %s' \ % str(model)) return cameo.pfba(model)
def gene_deletion(self) -> pd.DataFrame: model = self.read_model() gene_status = [] gene_values = [] knockout_reactions = self.knockout_reactions_for_genes(self.model_path) for gene in model.genes: reaction_bounds = dict() # knockout all reactions affected by gene by setting bounds zero for rid in knockout_reactions[gene.id]: reaction = model.reactions.get_by_id(rid) reaction_bounds[reaction.id] = ( reaction.lower_bound, reaction.upper_bound, ) reaction.bounds = (0, 0) try: # run fba result = fba(model) value = result.objective_value status = CuratorConstants.STATUS_OPTIMAL except Exception as e: logger.error(f"{e}") value = CuratorConstants.VALUE_INFEASIBLE status = CuratorConstants.STATUS_INFEASIBLE gene_status.append(status) gene_values.append(value) # restore bounds for rid, bounds in reaction_bounds.items(): model.reactions.get_by_id(rid).bounds = bounds[:] return pd.DataFrame( { "model": self.model_path.name, "objective": self.objective_id, "gene": [gene.id for gene in model.genes], "status": gene_status, "value": gene_values, } )
def objective(self) -> pd.DataFrame: model = self.read_model() try: # fbc optimization result = fba(model) value = result.objective_value status = CuratorConstants.STATUS_OPTIMAL except Exception as e: logger.error(f"{e}") value = CuratorConstants.VALUE_INFEASIBLE status = CuratorConstants.STATUS_INFEASIBLE return pd.DataFrame( { "model": self.model_path.name, "objective": [self.objective_id], "status": [status], "value": [value], } )
def calculate_yield(model, source, product): try: flux_dist = fba(model, objective=product) return flux_dist[product.id] / abs(flux_dist[source.id]) except OptimizationError: return 0.0
def gimme(model, expression_profile=None, cutoff=None, objective=None, objective_dist=None, fraction_of_optimum=0.9, normalization=or2min_and2max, condition=None, not_measured_value=None, *args, **kwargs): """ Gene Inactivity Moderated by Metabolism and Expression (GIMME)[1] Parameters ---------- model: SolverBased Model A constraint based model expression_profile: ExpressionProfile An expression profile cutoff: float inactivity threshold objective: str or other cameo compatible objective The Minimal Required Functionalities (MRF) objective_dist: FluxDistributionResult A predetermined flux distribution for the objective can be provided (optional) fraction_of_optimum: float The fraction of the MRF normalization: function expression profile normalization function condition: str, int or None The condition from the expression profile. If None (default), the first condition on the profile will be used. normalization: function The normalization function to convert the gene expression profile into reaction expression profile (default: max) Returns ------- GimmeResult References ---------- .. [1] Becker, S. a and Palsson, B. O. (2008). Context-specific metabolic networks are consistent with experiments. PLoS Computational Biology, 4(5), e1000082. doi:10.1371/journal.pcbi.1000082 """ assert isinstance(model, SolverBasedModel) assert isinstance(expression_profile, ExpressionProfile) assert isinstance(fraction_of_optimum, numbers.Number) assert isinstance(cutoff, numbers.Number) objective = model.objective if objective is None else objective objective_dist = fba( model, objective=objective) if objective_dist is None else objective_dist assert isinstance(objective_dist, FluxDistributionResult) if objective.direction == 'max': fix_obj_constraint = model.solver.interface.Constraint( model.objective.expression, lb=fraction_of_optimum * objective_dist.objective_value, name="required metabolic functionalities") else: fix_obj_constraint = model.solver.interface.Constraint( model.objective.expression, ub=fraction_of_optimum * objective_dist.objective_value, name="required metabolic functionalities") objective_terms = list() condition = expression_profile.conditions[ 0] if condition is None else condition not_measured_value = cutoff if not_measured_value is None else not_measured_value reaction_profile = expression_profile.to_reaction_dict( condition, model, not_measured_value, normalization) coefficients = { r: cutoff - exp if cutoff > exp else 0 for r, exp in six.iteritems(reaction_profile) } for rid, coefficient in six.iteritems(coefficients): reaction = model.reactions.get_by_id(rid) if coefficient > 0: objective_terms.append( coefficient * (reaction.forward_variable + reaction.reverse_variable)) with TimeMachine() as tm: gimme_objective = model.solver.interface.Objective( Add(*objective_terms), direction="min") tm(do=partial(setattr, model, "objective", gimme_objective), undo=partial(setattr, model, "objective", model.objective.expression)) tm(do=partial(model.solver.add, fix_obj_constraint), undo=partial(model.solver.remove, [fix_obj_constraint])) solution = model.solve() return GimmeResult(solution.fluxes, solution.f, objective_dist.fluxes, reaction_profile, cutoff)
def run(self, product=None, max_predictions=float("inf"), min_production=.1, timeout=None, callback=None, silent=False, allow_native_exchanges=False): """Run pathway prediction for a desired product. Parameters ---------- product : Metabolite, str Metabolite or id or name of metabolite to find production pathways for. max_predictions : int, optional The maximum number of predictions to compute. min_production : float The minimum acceptable production flux to product. timeout : int The time limit [seconds] per attempted prediction. callback : function A function that takes a successfully predicted pathway. silent : bool If True will print the pathways and max flux values. allow_native_exchanges: bool If True, exchange reactions for native metabolites will be allowed. Returns ------- PathwayPredictions The predicted pathways. """ product = self._find_product(product) pathways = list() with TimeMachine() as tm, self.model: tm(do=partial(setattr, self.model.solver.configuration, 'timeout', timeout), undo=partial(setattr, self.model.solver.configuration, 'timeout', self.model.solver.configuration.timeout)) try: product_reaction = self.model.reactions.get_by_id('DM_' + product.id) except KeyError: product_reaction = self.model.add_boundary(product, type='demand') product_reaction.lower_bound = min_production counter = 1 while counter <= max_predictions: logger.debug('Predicting pathway No. %d' % counter) try: self.model.slim_optimize(error_value=None) except OptimizationError as e: logger.error( 'No pathway could be predicted. Terminating pathway predictions.' ) logger.error(e) break vars_to_cut = list() for i, y_var_id in enumerate(self._y_vars_ids): y_var = self.model.solver.variables[y_var_id] if y_var.primal == 1.0: vars_to_cut.append(y_var) logger.info(vars_to_cut) if len(vars_to_cut) == 0: # no pathway found: logger.info( "It seems %s is a native product in model %s. " "Let's see if we can find better heterologous pathways." % (product, self.model)) # knockout adapter with native product for adapter in self.adpater_reactions: if product in adapter.metabolites: logger.info( 'Knocking out adapter reaction %s containing native product.' % adapter) adapter.knock_out() continue pathway = [ self.model.reactions.get_by_id(y_var.name[2:]) for y_var in vars_to_cut ] pathway_metabolites = set([ m for pathway_reaction in pathway for m in pathway_reaction.metabolites ]) logger.info('Pathway predicted: %s' % '\t'.join([ r.build_reaction_string(use_metabolite_names=True) for r in pathway ])) pathway_metabolites.add(product) # Figure out adapter reactions to include adapters = [ adapter for adapter in self.adpater_reactions if adapter.products[0] in pathway_metabolites ] # Figure out exchange reactions to include exchanges = [ exchange for exchange in self._exchanges if abs(exchange.flux) > non_zero_flux_threshold and exchange.id != product_reaction.id ] if allow_native_exchanges: exchanges = [ exchange for exchange in exchanges if list(exchange.metabolites)[0] in pathway_metabolites ] pathway = PathwayResult(pathway, exchanges, adapters, product_reaction) if not silent: util.display_pathway(pathway, counter) integer_cut = self.model.solver.interface.Constraint( Add(*vars_to_cut), name="integer_cut_" + str(counter), ub=len(vars_to_cut) - 1) logger.debug('Adding integer cut.') tm(do=partial(self.model.solver.add, integer_cut), undo=partial(self.model.solver.remove, integer_cut)) # Test pathway in the original model with self.original_model: pathway.apply(self.original_model) try: solution = fba(self.original_model, objective=pathway.product.id) except OptimizationError as e: logger.error(e) logger.error( "Addition of pathway {} made the model unsolvable. " "Skipping pathway.".format(pathway)) continue else: if solution[ pathway.product.id] > non_zero_flux_threshold: pathways.append(pathway) if not silent: print("Max flux: %.5f" % solution[pathway.product.id]) else: logger.error( "Pathway {} couldn't be verified. Production flux {}" "is below requirement {}. Skipping pathway.". format(pathway, solution[pathway.product.id], non_zero_flux_threshold)) finally: counter += 1 if callback is not None: callback(pathway) return PathwayPredictions(pathways)
def gimme( model, expression_profile=None, cutoff=None, objective=None, objective_dist=None, fraction_of_optimum=0.9, normalization=or2min_and2max, condition=None, not_measured_value=None, *args, **kwargs ): """ Gene Inactivity Moderated by Metabolism and Expression (GIMME)[1] Parameters ---------- model: SolverBased Model A constraint based model expression_profile: ExpressionProfile An expression profile cutoff: float inactivity threshold objective: str or other cameo compatible objective The Minimal Required Functionalities (MRF) objective_dist: FluxDistributionResult A predetermined flux distribution for the objective can be provided (optional) fraction_of_optimum: float The fraction of the MRF normalization: function expression profile normalization function condition: str, int or None The condition from the expression profile. If None (default), the first condition on the profile will be used. normalization: function The normalization function to convert the gene expression profile into reaction expression profile (default: max) Returns ------- GimmeResult References ---------- .. [1] Becker, S. a and Palsson, B. O. (2008). Context-specific metabolic networks are consistent with experiments. PLoS Computational Biology, 4(5), e1000082. doi:10.1371/journal.pcbi.1000082 """ assert isinstance(model, SolverBasedModel) assert isinstance(expression_profile, ExpressionProfile) assert isinstance(fraction_of_optimum, numbers.Number) assert isinstance(cutoff, numbers.Number) objective = model.objective if objective is None else objective objective_dist = fba(model, objective) if objective_dist is None else objective_dist assert isinstance(objective_dist, FluxDistributionResult) if objective.direction == "max": fix_obj_constraint = model.solver.interface.Constraint( model.objective.expression, lb=fraction_of_optimum * objective_dist.objective_value, name="required metabolic functionalities", ) else: fix_obj_constraint = model.solver.interface.Constraint( model.objective.expression, ub=fraction_of_optimum * objective_dist.objective_value, name="required metabolic functionalities", ) objective_terms = list() condition = expression_profile.conditions[0] if condition is None else condition not_measured_value = cutoff if not_measured_value is None else not_measured_value reaction_profile = expression_profile.to_reaction_dict(condition, model, not_measured_value, normalization) coefficients = {r: cutoff - exp if cutoff > exp else 0 for r, exp in six.iteritems(reaction_profile)} for rid, coefficient in six.iteritems(coefficients): reaction = model.reactions.get_by_id(rid) if coefficient > 0: objective_terms.append(coefficient * (reaction.forward_variable + reaction.reverse_variable)) with TimeMachine() as tm: gimme_objective = model.solver.interface.Objective(Add(*objective_terms), direction="min") tm( do=partial(setattr, model, "objective", gimme_objective), undo=partial(setattr, model, "objective", model.objective.expression), ) tm( do=partial(model.solver._add_constraint, fix_obj_constraint), undo=partial(model.solver._remove_constraints, [fix_obj_constraint]), ) solution = model.solve() return GimmeResult(solution.fluxes, solution.f, objective_dist.fluxes, reaction_profile, cutoff)
''' Created on 4 Dec 2018 @author: mate load in CD4 model, extract all proteins and save them to a new .csv ''' from cameo import load_model, fba model = load_model('models/CD4T1670.xml') print(model.reactions) new_solution = model.optimize() fba_result = fba(model) print(fba_result) print(fba_result.data_frame) print(len(fba_result.data_frame)) # print(model.reactions) for reactionO in model.reactions: for reactionI in reactionO.genes: print(reactionI) fba_result.display_on_map("RECON1.Carbohydrate metabolism")