def __call__(self, model, solution, targets): biomass_flux = round(solution.fluxes[self.biomass], config.ndecimals) fva_res = flux_variability_analysis(model, reactions=[self.product], fraction_of_optimum=1) min_product_flux = round(fva_res["lower_bound"][self.product], config.ndecimals) if self.carbon_yield: product = model.reactions.get_by_id(self.product) if product.boundary: product_flux = min_product_flux * n_carbon(product) else: product_flux = min_product_flux * n_carbon(product) / 2 substrate_flux = 0 for substrate_id in self.substrates: substrate = model.reactions.get_by_id(substrate_id) if substrate.boundary: substrate_flux += abs( solution.fluxes[substrate_id]) * n_carbon(substrate) else: substrate_flux += abs(solution.fluxes[substrate_id] ) * n_carbon(substrate) / 2 substrate_flux = round(substrate_flux, config.ndecimals) else: product_flux = min_product_flux substrate_flux = sum( round(abs(solution.fluxes[s]), config.ndecimals) for s in self.substrates) try: return (biomass_flux * product_flux) / substrate_flux except ZeroDivisionError: return 0.0
def __call__(self, model, solution, targets): biomass_flux = round(solution.fluxes[self.biomass], config.ndecimals) fva_res = flux_variability_analysis(model, reactions=[self.product], fraction_of_optimum=1) min_product_flux = round(fva_res["lower_bound"][self.product], config.ndecimals) if self.carbon_yield: product = model.reactions.get_by_id(self.product) if product.boundary: product_flux = min_product_flux * n_carbon(product) else: product_flux = min_product_flux * n_carbon(product) / 2 substrate_flux = 0 for substrate_id in self.substrates: substrate = model.reactions.get_by_id(substrate_id) if substrate.boundary: substrate_flux += abs(solution.fluxes[substrate_id]) * n_carbon(substrate) else: substrate_flux += abs(solution.fluxes[substrate_id]) * n_carbon(substrate) / 2 substrate_flux = round(substrate_flux, config.ndecimals) else: product_flux = min_product_flux substrate_flux = sum(round(abs(solution.fluxes[s]), config.ndecimals) for s in self.substrates) try: return (biomass_flux * product_flux) / substrate_flux except ZeroDivisionError: return 0.0
def __call__(self, point): self._set_bounds(point[1]) return (point[1], flux_variability_analysis(self.model, reactions=self.included_reactions, remove_cycles=False, view=SequentialView()))
def analyze(self, measured_metabolites, filter_by_subsystem=False, add_constraints=False, without_transports=True): if add_constraints: self.increasing_metabolite_constraints(measured_metabolites) self.set_objective_coefficients(measured_metabolites, without_transports) reactions = None if filter_by_subsystem: reactions = self.filter_reaction_by_subsystems() self.solver.configuration.timeout = 10 * 60 try: results = flux_variability_analysis(self, reactions=reactions, fraction_of_optimum=1) except: logging.getLogger('timeout_errors').error('FVA timeout error') logging.getLogger('timeout_errors').error(self.solver.to_json()) raise TimeoutError('FVA timeout error') return results
def process_gene_knockout_solution(model, solution, simulation_method, simulation_kwargs, biomass, target, substrate, objective_function): """ Arguments --------- model: SolverBasedModel A constraint-based model solution: tuple The genes simulation_method: function See see cameo.flux_analysis.simulation simulation_kwargs: dict Keyword arguments to run the simulation method biomass: Reaction Cellular biomass reaction target: Reaction The strain design target substrate: Reaction The main carbon source uptake rate objective_function: cameo.strain_design.heuristic.evolutionary.objective_functions.ObjectiveFunction The objective function used for evaluation. Returns ------- list A list with: reactions, genes, size, fva_min, fva_max, target flux, biomass flux, yield, fitness """ with TimeMachine() as tm: genes = [model.genes.get_by_id(gid) for gid in solution] reactions = find_gene_knockout_reactions(model, solution) for reaction in reactions: reaction.knock_out(tm) reaction_ids = [r.id for r in reactions] flux_dist = simulation_method(model, reactions=objective_function.reactions, objective=biomass, **simulation_kwargs) tm(do=partial(setattr, model, "objective", biomass), undo=partial(setattr, model, "objective", model.objective)) fva = flux_variability_analysis(model, fraction_of_optimum=0.99, reactions=[target]) target_yield = flux_dist[target] / abs(flux_dist[substrate]) return [ tuple(reaction_ids), solution, len(solution), fva.lower_bound(target), fva.upper_bound(target), flux_dist[target], flux_dist[biomass], target_yield, objective_function(model, flux_dist, genes) ]
def process_reaction_swap_solution(model, solution, simulation_method, simulation_kwargs, biomass, target, substrate, objective_function, swap_pairs): """ Arguments --------- model: SolverBasedModel A constraint-based model solution: tuple - (reactions, knockouts) The output of a decoder simulation_method: function See see cameo.flux_analysis.simulation simulation_kwargs: dict Keyword arguments to run the simulation method biomass: Reaction Cellular biomass reaction target: Reaction The strain design target substrate: Reaction The main carbon source uptake rate objective_function: cameo.strain_design.heuristic.evolutionary.objective_functions.ObjectiveFunction The objective function used for evaluation. swap_pairs: The metabolites to swap Returns ------- list A list with: reactions, size, fva_min, fva_max, target flux, biomass flux, yield, fitness, [fitness, [fitness]] """ with TimeMachine() as tm: reactions = [model.reactions.get_by_id(rid) for rid in solution] for reaction in reactions: reaction.swap_cofactors(tm, swap_pairs) flux_dist = simulation_method(model, reactions=objective_function.reactions, objective=biomass, **simulation_kwargs) tm(do=partial(setattr, model, "objective", biomass), undo=partial(setattr, model, "objective", model.objective)) fva = flux_variability_analysis(model, fraction_of_optimum=0.99, reactions=[target]) target_yield = flux_dist[target] / abs(flux_dist[substrate]) return [ solution, fva.lower_bound(target), fva.upper_bound(target), flux_dist[target], flux_dist[biomass], target_yield, objective_function(model, flux_dist, reactions) ]
def test_result_is_correct(self): result = self.optknock.run(max_knockouts=1, target="EX_ac_lp_e_rp_", biomass="Biomass_Ecoli_core_N_lp_w_fsh_GAM_rp__Nmet2", max_results=1) production = result.production[0] knockouts = result.knockouts[0] for knockout in knockouts: self.model.reactions.get_by_id(knockout).knock_out() fva = cameo.flux_variability_analysis(self.model, fraction_of_optimum=1, remove_cycles=False, reactions=["EX_ac_lp_e_rp_"]) self.assertAlmostEqual(fva["upper_bound"][0], production)
def test_result_is_correct(self, cplex_optknock): model, optknock = cplex_optknock result = optknock.run(max_knockouts=1, target="EX_ac_lp_e_rp_", biomass="Biomass_Ecoli_core_N_lp_w_fsh_GAM_rp__Nmet2", max_results=1) production = result.production[0] knockouts = result.knockouts[0] for knockout in knockouts: model.reactions.get_by_id(knockout).knock_out() fva = cameo.flux_variability_analysis(model, fraction_of_optimum=1, remove_cycles=False, reactions=["EX_ac_lp_e_rp_"]) assert abs(fva["upper_bound"][0] - production) < 1e-6
def process_reaction_knockout_solution(model, solution, simulation_method, simulation_kwargs, biomass, target, substrate, objective_function): """ Arguments --------- model: cobra.Model A constraint-based model solution: tuple - (reactions, knockouts) The output of a decoder simulation_method: function See see cameo.flux_analysis.simulation simulation_kwargs: dict Keyword arguments to run the simulation method biomass: Reaction Cellular biomass reaction target: Reaction The strain design target substrate: Reaction The main carbon source uptake rate objective_function: cameo.strain_design.heuristic.evolutionary.objective_functions.ObjectiveFunction The objective function used for evaluation. Returns ------- list A list with: reactions, size, fva_min, fva_max, target flux, biomass flux, yield, fitness """ with model: reactions = [model.reactions.get_by_id(rid) for rid in solution] for reaction in reactions: reaction.knock_out() flux_dist = simulation_method(model, reactions=objective_function.reactions, objective=biomass, **simulation_kwargs) model.objective = biomass fva = flux_variability_analysis(model, fraction_of_optimum=0.99, reactions=[target]) target_yield = flux_dist[target] / abs(flux_dist[substrate]) return [ solution, len(solution), fva.lower_bound(target), fva.upper_bound(target), flux_dist[target], flux_dist[biomass], target_yield, objective_function(model, flux_dist, reactions) ]
def __call__(self, model, solution, decoded_representation): try: biomass_flux = round(solution.fluxes[self.biomass], config.ndecimals) with TimeMachine() as tm: for reaction in decoded_representation[0]: model.reaction_for(reaction).knock_out(tm) fva_res = flux_variability_analysis(model, reactions=[self.product], fraction_of_optimum=1) min_product_flux = fva_res["lower_bound"][self.product] substrate_flux = round(abs(solution.fluxes[self.substrate]), config.ndecimals) return round((biomass_flux * min_product_flux) / substrate_flux, config.ndecimals) except ZeroDivisionError: return 0.0
def process_knockout_solution(model, solution, simulation_method, simulation_kwargs, biomass, target, substrate, objective_functions, cache=None): """ Arguments --------- model: SolverBasedModel A constraint-based model solution: tuple - (reactions, knockouts) The output of a decoder simulation_method: function See see cameo.flux_analysis.simulation simulation_kwargs: dict Keyword arguments to run the simulation method biomass: Reaction Cellular biomass reaction target: Reaction The strain design target substrate: Reaction The main carbon source uptake rate objective_functions: list A list of cameo.strain_design.heuristic.evolutionary.objective_functions.ObjectiveFunction cache: ProblemCache A problem cache for performance improvment Returns ------- list A list with: reactions, knockouts, size, fva_min, fva_max, target flux, biomass flux, yield, fitness, [fitness, [fitness]] """ with TimeMachine() as tm: for ko in solution[0]: model.reactions.get_by_id(ko).knock_out(tm) reactions = reactions2filter(objective_functions) flux_dist = simulation_method(model, cache=cache, reactions=reactions, objective=biomass, **simulation_kwargs) tm(do=partial(setattr, model, "objective", biomass), undo=partial(setattr, model, "objective", model.objective)) fva = flux_variability_analysis(model, fraction_of_optimum=0.99, reactions=[target]) target_yield = flux_dist[target] / abs(flux_dist[substrate]) return [solution[0], solution[1], len(solution[1]), fva.lower_bound(target), fva.upper_bound(target), flux_dist[target], flux_dist[biomass], target_yield] + [of(model, flux_dist, solution) for of in objective_functions]
def process_reaction_swap_solution(model, solution, simulation_method, simulation_kwargs, biomass, target, substrate, objective_function, swap_pairs): """ Arguments --------- model: cobra.Model A constraint-based model solution: tuple - (reactions, knockouts) The output of a decoder simulation_method: function See see cameo.flux_analysis.simulation simulation_kwargs: dict Keyword arguments to run the simulation method biomass: Reaction Cellular biomass reaction target: Reaction The strain design target substrate: Reaction The main carbon source uptake rate objective_function: cameo.strain_design.heuristic.evolutionary.objective_functions.ObjectiveFunction The objective function used for evaluation. swap_pairs: The metabolites to swap Returns ------- list A list with: reactions, size, fva_min, fva_max, target flux, biomass flux, yield, fitness, [fitness, [fitness]] """ with model: reactions = [model.reactions.get_by_id(rid) for rid in solution] for reaction in reactions: swap_cofactors(reaction, model, swap_pairs) flux_dist = simulation_method(model, reactions=objective_function.reactions, objective=biomass, **simulation_kwargs) model.objective = biomass fva = flux_variability_analysis(model, fraction_of_optimum=0.99, reactions=[target]) target_yield = flux_dist[target] / abs(flux_dist[substrate]) return [solution, fva.lower_bound(target), fva.upper_bound(target), flux_dist[target], flux_dist[biomass], target_yield, objective_function(model, flux_dist, reactions)]
def process_gene_knockout_solution(model, solution, simulation_method, simulation_kwargs, biomass, target, substrate, objective_function): """ Arguments --------- model: cobra.Model A constraint-based model solution: tuple The genes simulation_method: function See see cameo.flux_analysis.simulation simulation_kwargs: dict Keyword arguments to run the simulation method biomass: Reaction Cellular biomass reaction target: Reaction The strain design target substrate: Reaction The main carbon source uptake rate objective_function: cameo.strain_design.heuristic.evolutionary.objective_functions.ObjectiveFunction The objective function used for evaluation. Returns ------- list A list with: reactions, genes, size, fva_min, fva_max, target flux, biomass flux, yield, fitness """ with model: genes = [model.genes.get_by_id(gid) for gid in solution] reactions = find_gene_knockout_reactions(model, solution) for reaction in reactions: reaction.knock_out() reaction_ids = [r.id for r in reactions] flux_dist = simulation_method(model, reactions=objective_function.reactions, objective=biomass, **simulation_kwargs) model.objective = biomass fva = flux_variability_analysis(model, fraction_of_optimum=0.99, reactions=[target]) target_yield = flux_dist[target] / abs(flux_dist[substrate]) return [tuple(reaction_ids), solution, len(solution), fva.lower_bound(target), fva.upper_bound(target), flux_dist[target], flux_dist[biomass], target_yield, objective_function(model, flux_dist, genes)]
def __call__(self, model, solution, targets): try: biomass_flux = round(solution.fluxes[self.biomass], config.ndecimals) with TimeMachine() as tm: for target in targets: target.knock_out(tm) fva_res = flux_variability_analysis(model, reactions=[self.product], fraction_of_optimum=1) min_product_flux = fva_res["lower_bound"][self.product] substrate_flux = round(abs(solution.fluxes[self.substrate]), config.ndecimals) return round((biomass_flux * min_product_flux) / substrate_flux, config.ndecimals) except ZeroDivisionError: return 0.0
def find_mutant_growth_rate(model, relative_bounds, original_bounds=None, skip_essential=False, solve_method=cameo.fba, essential_reactions=None, **simulation_kwargs): """ Calculates the fluxes for a model where bounds have been modified. :param model: SolverBasedModel :param relative_bounds: A dictionary of relative bounds that will be applied to the bounds of each reaction :original_bounds: A pandas dataframe (as output by cameo.flux_variability_analysis) containing initial bounds. If None, an FVA will be run to determine them. :param skip_essential: Reaction bounds will not be modified if relative bound is less than this parameter. Set to False or None to disable skipping. """ with TimeMachine() as tm: # Make sure bounds are reset for reaction in model.reactions: tm(do=int, undo=partial(setattr, reaction, "upper_bound", reaction.upper_bound)) tm(do=int, undo=partial(setattr, reaction, "lower_bound", reaction.lower_bound)) # Find essential reactions if skip_essential: if essential_reactions is None: essential_reactions = model.essential_reactions() # Perform FVA if original_bounds is None: fva_result = cameo.flux_variability_analysis( model, fraction_of_optimum=1.0, remove_cycles=False) fva_result["lower_bound"] = fva_result["lower_bound"].round(6) fva_result["upper_bound"] = fva_result["upper_bound"].round(6) else: fva_result = original_bounds # Set initial bounds for reaction_id in fva_result.index: reaction = model.reactions.get_by_id(reaction_id) if fva_result["upper_bound"][reaction_id] >= 0: reaction.upper_bound = round_fva_bound( fva_result["upper_bound"][reaction_id], config.ndecimals) if fva_result["lower_bound"][reaction_id] <= 0: reaction.lower_bound = round_fva_bound( fva_result["lower_bound"][reaction_id], config.ndecimals) # Modify bounds for reaction_id in relative_bounds: reaction = model.reactions.get_by_id(convert_reaction(reaction_id)) if skip_essential and reaction in essential_reactions and round( relative_bounds[reaction_id], config.ndecimals) <= skip_essential: #print "Skipped "+reaction_id continue if convert_reaction(reaction_id) not in fva_result.index: raise Warning("Reaction " + reaction_id + " is not in the specified original bounds") reaction.lower_bound *= relative_bounds[reaction_id] reaction.upper_bound *= relative_bounds[reaction_id] # Solve mutated model #solution = model.solve() solution = solve_method(model, **simulation_kwargs) return solution
def run(self, surface_only=True, improvements_only=True, view=None): """Run the differential flux variability analysis. Parameters ---------- surface_only : bool, optional If only the surface of the n-dimensional production envelope should be scanned (defaults to True). improvements_only : bool, optional If only grid points should should be scanned that constitute and improvement in production over the reference state (defaults to True). view : SequentialView or MultiprocessingView or ipython.cluster.DirectView, optional A parallelization view (defaults to SequentialView). Returns ------- pandas.Panel A pandas Panel containing a results DataFrame for every grid point scanned. """ with TimeMachine() as tm: # Make sure that the design_space_model is initialized to its original state later for variable in self.variables: reaction = self.design_space_model.reactions.get_by_id(variable) tm(do=int, undo=partial(setattr, reaction, 'lower_bound', reaction.lower_bound)) tm(do=int, undo=partial(setattr, reaction, 'upper_bound', reaction.upper_bound)) target_reaction = self.design_space_model.reactions.get_by_id(self.objective) tm(do=int, undo=partial(setattr, target_reaction, 'lower_bound', target_reaction.lower_bound)) tm(do=int, undo=partial(setattr, target_reaction, 'upper_bound', target_reaction.upper_bound)) if view is None: view = config.default_view else: view = view included_reactions = [reaction.id for reaction in self.reference_model.reactions if reaction.id not in self.exclude] self.reference_flux_ranges = flux_variability_analysis(self.reference_model, reactions=included_reactions, view=view, remove_cycles=False).data_frame self._init_search_grid(surface_only=surface_only, improvements_only=improvements_only) progress = ProgressBar(len(self.grid)) func_obj = _DifferentialFvaEvaluator(self.design_space_model, self.variables, self.objective, included_reactions) results = list(progress(view.imap(func_obj, self.grid.iterrows()))) solutions = dict((tuple(point.iteritems()), fva_result.data_frame) for (point, fva_result) in results) reference_intervals = self.reference_flux_ranges[['lower_bound', 'upper_bound']].values for sol in six.itervalues(solutions): intervals = sol[['lower_bound', 'upper_bound']].values gaps = [self._interval_gap(interval1, interval2) for interval1, interval2 in my_zip(reference_intervals, intervals)] sol['gaps'] = gaps if self.normalize_ranges_by is not None: for sol in six.itervalues(solutions): normalized_intervals = sol[['lower_bound', 'upper_bound']].values / sol.lower_bound[ self.normalize_ranges_by] normalized_gaps = [self._interval_gap(interval1, interval2) for interval1, interval2 in my_zip(reference_intervals, normalized_intervals)] sol['normalized_gaps'] = normalized_gaps for df in six.itervalues(solutions): ko_selection = df[(df.lower_bound == 0) & (df.upper_bound == 0) & (self.reference_flux_ranges.lower_bound != 0) & self.reference_flux_ranges.upper_bound != 0] df['KO'] = False df.loc[ko_selection.index]['KO'] = True for df in six.itervalues(solutions): flux_reversal_selection = df[((self.reference_flux_ranges.upper_bound < 0) & (df.lower_bound > 0) | ((self.reference_flux_ranges.lower_bound > 0) & (df.upper_bound < 0)))] df['flux_reversal'] = False df.loc[flux_reversal_selection.index]['flux_reversal'] = True for df in six.itervalues(solutions): flux_reversal_selection = df[((self.reference_flux_ranges.lower_bound <= 0) & (df.lower_bound > 0)) | ( (self.reference_flux_ranges.upper_bound >= 0) & (df.upper_bound <= 0))] df['suddenly_essential'] = False df.loc[flux_reversal_selection.index]['suddenly_essential'] = True # solutions['reference_flux_ranges'] = self.reference_flux_ranges return DifferentialFVAResult(pandas.Panel(solutions), self.envelope, self.variables, self.objective)
def run(self, surface_only=True, improvements_only=True, view=None): """Run the differential flux variability analysis. Parameters ---------- surface_only : bool, optional If only the surface of the n-dimensional production envelope should be scanned (defaults to True). improvements_only : bool, optional If only grid points should should be scanned that constitute and improvement in production over the reference state (defaults to True). view : SequentialView or MultiprocessingView or ipython.cluster.DirectView, optional A parallelization view (defaults to SequentialView). Returns ------- pandas.Panel A pandas Panel containing a results DataFrame for every grid point scanned. """ with TimeMachine() as tm: # Make sure that the design_space_model is initialized to its original state later for variable in self.variables: reaction = self.design_space_model.reactions.get_by_id( variable) tm(do=int, undo=partial(setattr, reaction, 'lower_bound', reaction.lower_bound)) tm(do=int, undo=partial(setattr, reaction, 'upper_bound', reaction.upper_bound)) target_reaction = self.design_space_model.reactions.get_by_id( self.objective) tm(do=int, undo=partial(setattr, target_reaction, 'lower_bound', target_reaction.lower_bound)) tm(do=int, undo=partial(setattr, target_reaction, 'upper_bound', target_reaction.upper_bound)) if view is None: view = config.default_view else: view = view included_reactions = [ reaction.id for reaction in self.reference_model.reactions if reaction.id not in self.exclude ] self.reference_flux_ranges = flux_variability_analysis( self.reference_model, reactions=included_reactions, view=view, remove_cycles=False).data_frame self._init_search_grid(surface_only=surface_only, improvements_only=improvements_only) progress = ProgressBar(len(self.grid)) func_obj = _DifferentialFvaEvaluator(self.design_space_model, self.variables, self.objective, included_reactions) results = list(progress(view.imap(func_obj, self.grid.iterrows()))) solutions = dict((tuple(point.iteritems()), fva_result.data_frame) for (point, fva_result) in results) reference_intervals = self.reference_flux_ranges[[ 'lower_bound', 'upper_bound' ]].values for sol in six.itervalues(solutions): intervals = sol[['lower_bound', 'upper_bound']].values gaps = [ self._interval_gap(interval1, interval2) for interval1, interval2 in my_zip(reference_intervals, intervals) ] sol['gaps'] = gaps if self.normalize_ranges_by is not None: for sol in six.itervalues(solutions): normalized_intervals = sol[[ 'lower_bound', 'upper_bound' ]].values / sol.lower_bound[self.normalize_ranges_by] normalized_gaps = [ self._interval_gap(interval1, interval2) for interval1, interval2 in my_zip(reference_intervals, normalized_intervals) ] sol['normalized_gaps'] = normalized_gaps for df in six.itervalues(solutions): ko_selection = df[(df.lower_bound == 0) & (df.upper_bound == 0) & (self.reference_flux_ranges.lower_bound != 0) & self.reference_flux_ranges.upper_bound != 0] df['KO'] = False df.loc[ko_selection.index]['KO'] = True for df in six.itervalues(solutions): flux_reversal_selection = df[( (self.reference_flux_ranges.upper_bound < 0) & (df.lower_bound > 0) | ((self.reference_flux_ranges.lower_bound > 0) & (df.upper_bound < 0)))] df['flux_reversal'] = False df.loc[flux_reversal_selection.index]['flux_reversal'] = True for df in six.itervalues(solutions): flux_reversal_selection = df[( (self.reference_flux_ranges.lower_bound <= 0) & (df.lower_bound > 0)) | ( (self.reference_flux_ranges.upper_bound >= 0) & (df.upper_bound <= 0))] df['suddenly_essential'] = False df.loc[flux_reversal_selection.index]['suddenly_essential'] = True # solutions['reference_flux_ranges'] = self.reference_flux_ranges return DifferentialFVAResult(pandas.Panel(solutions), self.envelope, self.variables, self.objective)
def find_initial_bounds_from_c13(model, c13_path, activity_level, reference=None): """ :param model: :param c13_path: :param activity_level: :return: Reference flux distribution result and initial_bounds """ # Reactions to skip exchanges = [reac.id for reac in model.exchanges] skip_reacs = exchanges + ["ATPM", "Ec_biomass_iJO1366_core_53p95M"] c13_bounds = pd.DataFrame.from_csv(c13_path) if reference is None: with TimeMachine() as tm: for r_id in c13_bounds.index: lower = round(c13_bounds["lower_bound"][r_id], 6) upper = round(c13_bounds["upper_bound"][r_id], 6) r = model.reactions.get_by_id(r_id) tm(do=partial(setattr, r, "lower_bound", lower), undo=partial(setattr, r, "lower_bound", r.lower_bound)) tm(do=partial(setattr, r, "upper_bound", upper), undo=partial(setattr, r, "upper_bound", r.upper_bound)) reference = cameo.pfba(model) with TimeMachine() as tm: for r_id in c13_bounds.index: if r_id in skip_reacs: continue lower = round(c13_bounds["lower_bound"][r_id], 6) upper = round(c13_bounds["upper_bound"][r_id], 6) reac = model.reactions.get_by_id(r_id) if lower <= 0: tm(do=partial(setattr, reac, "lower_bound", lower / activity_level), undo=partial(setattr, reac, "lower_bound", reac.lower_bound)) if upper >= 0: tm(do=partial(setattr, reac, "upper_bound", upper / activity_level), undo=partial(setattr, reac, "upper_bound", reac.upper_bound)) biomass = model.reactions.Ec_biomass_iJO1366_core_53p95M #tm(do=partial(setattr, r, "upper_bound", reference["Ec_biomass_iJO1366_core_53p95M"]), # undo=partial(setattr, r, "upper_bound", biomass.upper_bound)) wt_bounds = cameo.flux_variability_analysis( model, fraction_of_optimum=1, remove_cycles=False).data_frame wt_bounds["lower_bound"] = wt_bounds["lower_bound"].round(6) wt_bounds["upper_bound"] = wt_bounds["upper_bound"].round(6) for r_id in c13_bounds.index: if r_id in skip_reacs: continue lower = round(c13_bounds["lower_bound"][r_id], 6) upper = round(c13_bounds["upper_bound"][r_id], 6) if lower <= 0: wt_bounds.loc[r_id, "lower_bound"] = lower / activity_level if upper >= 0: wt_bounds.loc[r_id, "upper_bound"] = upper / activity_level wt_result = reference return wt_result, wt_bounds