class TimeMachineTestCase(unittest.TestCase): def setUp(self): self.tm = TimeMachine() def test_one_change_list(self): l = [1, 2, 3, 4] self.tm(do=partial(l.append, 5), undo=l.pop) self.assertEqual(l, [1, 2, 3, 4, 5]) self.tm.reset() self.assertEqual(l, [1, 2, 3, 4]) def test_str_handles_different_types_of_stored_operations(self): def normal_function(): pass partial_function = partial(str, 1) self.tm(do=normal_function, undo=partial_function) self.assertEqual(self.tm.__str__().split('\n')[2:-1], ["undo: " + str(str) + " (1,) {}", 'redo: normal_function']) def test_with_statement(self): l = [1, 2, 3, 4] with TimeMachine() as tm: tm(do=partial(l.append, 33), undo=partial(l.pop)) tm(do=partial(l.append, 66), undo=partial(l.pop)) tm(do=partial(l.append, 99), undo=partial(l.pop)) self.assertEqual(l, [1, 2, 3, 4])
def test_one_change_list(self): tm = TimeMachine() l = [1, 2, 3, 4] tm(do=partial(l.append, 5), undo=l.pop) assert l == [1, 2, 3, 4, 5] tm.reset() assert l == [1, 2, 3, 4]
def _fbid_fva(model, knockouts, view): tm = TimeMachine() for reaction in model.reactions: if reaction.reversibility: tm(do=partial(setattr, reaction, 'lower_bound', -1), undo=partial(setattr, reaction, 'lower_bound', reaction.lower_bound)) tm(do=partial(setattr, reaction, 'upper_bound', 1), undo=partial(setattr, reaction, 'upper_bound', reaction.upper_bound)) else: tm(do=partial(setattr, reaction, 'lower_bound', 0), undo=partial(setattr, reaction, 'lower_bound', reaction.lower_bound)) tm(do=partial(setattr, reaction, 'upper_bound', 1), undo=partial(setattr, reaction, 'upper_bound', reaction.upper_bound)) wt_fva = flux_variability_analysis(model, view) for reaction in knockouts: tm(do=partial(setattr, reaction, 'upper_bound', 0), undo=partial(setattr, reaction, 'upper_bound', reaction.upper_bound)) tm(do=partial(setattr, reaction, 'lower_bound', 0), undo=partial(setattr, reaction, 'lower_bound', reaction.lower_bound)) mt_fva = flux_variability_analysis(model, view) perturbation = 0 for reaction in model.reactions: if wt_fva[reaction.id] != 0 and mt_fva[reaction.id] == 0: perturbation += 1 tm.reset() return perturbation
class TimeMachineTestCase(unittest.TestCase): def setUp(self): self.tm = TimeMachine() def test_one_change_list(self): l = [1, 2, 3, 4] self.tm(do=partial(l.append, 5), undo=l.pop) self.assertEqual(l, [1, 2, 3, 4, 5]) self.tm.reset() self.assertEqual(l, [1, 2, 3, 4]) def test_str_handles_different_types_of_stored_operations(self): def normal_function(): pass partial_function = partial(str, 1) self.tm(do=normal_function, undo=partial_function) if six.PY2: self.assertEqual( self.tm.__str__().split('\n')[2:-1], ["undo: <type 'str'> (1,) None", 'redo: normal_function']) elif six.PY3: self.assertEqual( self.tm.__str__().split('\n')[2:-1], ["undo: <class 'str'> (1,) None", 'redo: normal_function']) def test_with_statement(self): l = [1, 2, 3, 4] with TimeMachine() as tm: tm(do=partial(l.append, 33), undo=partial(l.pop)) tm(do=partial(l.append, 66), undo=partial(l.pop)) tm(do=partial(l.append, 99), undo=partial(l.pop)) self.assertEqual(l, [1, 2, 3, 4])
def _production_envelope_inner(self, point): tm = TimeMachine() try: for (reaction, coordinate) in zip(self.variable_reactions, point): tm(do=partial(setattr, reaction, 'lower_bound', coordinate), undo=partial(setattr, reaction, 'lower_bound', reaction.lower_bound)) tm(do=partial(setattr, reaction, 'upper_bound', coordinate), undo=partial(setattr, reaction, 'upper_bound', reaction.upper_bound)) interval = [] tm(do=int, undo=partial(setattr, self.model.objective, 'direction', self.model.objective.direction)) self.model.objective.direction = 'min' try: solution = self.model.solve().f except Infeasible: solution = 0 interval.append(solution) self.model.objective.direction = 'max' try: solution = self.model.solve().f except Infeasible: solution = 0 interval.append(solution) finally: tm.reset() return point + tuple(interval)
def reaction_component_production(model, reaction): tm = TimeMachine() for metabolite in reaction.metabolites: test = Reaction("EX_%s_temp" % metabolite.id) test._metabolites[metabolite] = -1 # hack frozen set from cobrapy to be able to add a reaction metabolite._reaction = set(metabolite._reaction) tm(do=partial(model.add_reactions, [test]), undo=partial(model.remove_reactions, [test])) tm(do=partial(setattr, model, "objective", test.id), undo=partial(setattr, model, "objective", model.objective)) try: print(metabolite.id, "= ", model.solve().f) except SolveError: print(metabolite, " cannot be produced (reactions: %s)" % metabolite.reactions) finally: tm.reset()
def draw_knockout_result(model, map_name, simulation_method, knockouts, *args, **kwargs): tm = TimeMachine() try: for reaction in model._ids_to_reactions(knockouts): tm(do=partial(setattr, reaction, 'lower_bound', 0), undo=partial(setattr, reaction, 'lower_bound', reaction.lower_bound)) tm(do=partial(setattr, reaction, 'upper_bound', 0), undo=partial(setattr, reaction, 'upper_bound', reaction.upper_bound)) solution = simulation_method(model, *args, **kwargs).x_dict tm.reset() return Builder(map_name, reaction_data=solution) except Exception as e: tm.reset() raise e
def reaction_component_production(model, reaction): tm = TimeMachine() for metabolite in reaction.metabolites: test = Reaction("EX_%s_temp" % metabolite.id) test._metabolites[metabolite] = -1 # hack frozen set from cobrapy to be able to add a reaction metabolite._reaction = set(metabolite._reaction) tm(do=partial(model.add_reactions, [test]), undo=partial(model.remove_reactions, [test])) tm(do=partial(setattr, model, 'objective', test.id), undo=partial(setattr, model, 'objective', model.objective)) try: print(metabolite.id, "= ", model.solve().f) except SolveError: print(metabolite, " cannot be produced (reactions: %s)" % metabolite.reactions) finally: tm.reset()
def gene_knockout_growth( gene_id, model, threshold=10 ** -6, simulation_method=fba, normalize=True, biomass=None, biomass_flux=None, *args, **kwargs ): if biomass_flux is None: s = model.solve() biomass_flux = s.f if "reference" not in kwargs: kwargs["reference"] = s.x_dict gene = model.genes.get_by_id(gene_id) knockouts = find_gene_knockout_reactions(model, [gene]) tm = TimeMachine() for reaction in knockouts: tm( do=partial(setattr, reaction, "lower_bound", 0), undo=partial(setattr, reaction, "lower_bound", reaction.lower_bound), ) tm( do=partial(setattr, reaction, "upper_bound", 0), undo=partial(setattr, reaction, "upper_bound", reaction.upper_bound), ) try: s = simulation_method(model, *args, **kwargs) f = s.get_primal_by_id(biomass) if f >= threshold: if normalize: f = f / biomass_flux else: f = 0 except SolveError: f = float("nan") finally: tm.reset() return f
def gene_knockout_growth(gene_id, model, threshold=10**-6, simulation_method=fba, normalize=True, biomass=None, biomass_flux=None, *args, **kwargs): if biomass_flux is None: s = model.solve() biomass_flux = s.f if 'reference' not in kwargs: kwargs['reference'] = s.x_dict gene = model.genes.get_by_id(gene_id) knockouts = find_gene_knockout_reactions(model, [gene]) tm = TimeMachine() for reaction in knockouts: tm(do=partial(setattr, reaction, 'lower_bound', 0), undo=partial(setattr, reaction, 'lower_bound', reaction.lower_bound)) tm(do=partial(setattr, reaction, 'upper_bound', 0), undo=partial(setattr, reaction, 'upper_bound', reaction.upper_bound)) try: s = simulation_method(model, *args, **kwargs) f = s.get_primal_by_id(biomass) if f >= threshold: if normalize: f = f / biomass_flux else: f = 0 except SolveError: f = float('nan') finally: tm.reset() return f
def _cycle_free_fva(model, reactions=None, sloppy=True, sloppy_bound=666): """Cycle free flux-variability analysis. (http://cran.r-project.org/web/packages/sybilcycleFreeFlux/index.html) Parameters ---------- model : SolverBasedModel reactions : list List of reactions whose flux-ranges should be determined. sloppy : boolean, optional If true, only fluxes v with abs(v) > sloppy_bound are checked to be futile cycles (defaults to True). sloppy_bound : int, optional The threshold bound used by sloppy (defaults to the number of the beast). """ cycle_count = 0 try: original_objective = copy(model.objective) if reactions is None: reactions = model.reactions else: reactions = model._ids_to_reactions(reactions) fva_sol = OrderedDict() for reaction in reactions: fva_sol[reaction.id] = dict() model.objective = reaction model.objective.direction = 'min' try: solution = model.solve() except Unbounded: fva_sol[reaction.id]['lower_bound'] = -numpy.inf continue except Infeasible: fva_sol[reaction.id]['lower_bound'] = 0 continue except Exception as e: raise e bound = solution.f if sloppy and abs(bound) < sloppy_bound: fva_sol[reaction.id]['lower_bound'] = bound else: logger.debug('Determine if {} with bound {} is a cycle'.format(reaction.id, bound)) v0_fluxes = solution.x_dict v1_cycle_free_fluxes = remove_infeasible_cycles(model, v0_fluxes) if abs(v1_cycle_free_fluxes[reaction.id] - bound) < 10 ** -6: fva_sol[reaction.id]['lower_bound'] = bound else: logger.debug('Cycle detected: {}'.format(reaction.id)) cycle_count += 1 v2_one_cycle_fluxes = remove_infeasible_cycles(model, v0_fluxes, fix=[reaction.id]) tm = TimeMachine() for key, v1_flux in six.iteritems(v1_cycle_free_fluxes): if v1_flux == 0 and v2_one_cycle_fluxes[key] != 0: knockout_reaction = model.reactions.get_by_id(key) tm(do=partial(setattr, knockout_reaction, 'lower_bound', 0.), undo=partial(setattr, knockout_reaction, 'lower_bound', knockout_reaction.lower_bound)) tm(do=partial(setattr, knockout_reaction, 'upper_bound', 0.), undo=partial(setattr, knockout_reaction, 'upper_bound', knockout_reaction.lower_bound)) model.objective.direction = 'min' try: solution = model.solve() except Unbounded: fva_sol[reaction.id]['lower_bound'] = -numpy.inf except Infeasible: fva_sol[reaction.id]['lower_bound'] = 0 else: fva_sol[reaction.id]['lower_bound'] = solution.f finally: tm.reset() for reaction in reactions: model.objective = reaction model.objective.direction = 'max' try: solution = model.solve() except Unbounded: fva_sol[reaction.id]['upper_bound'] = numpy.inf continue except Infeasible: fva_sol[reaction.id]['upper_bound'] = 0 continue except Exception as e: raise e else: bound = solution.f if sloppy and abs(bound) < sloppy_bound: fva_sol[reaction.id]['upper_bound'] = bound else: logger.debug('Determine if {} with bound {} is a cycle'.format(reaction.id, bound)) v0_fluxes = solution.x_dict v1_cycle_free_fluxes = remove_infeasible_cycles(model, v0_fluxes) if abs(v1_cycle_free_fluxes[reaction.id] - bound) < 10 ** -6: fva_sol[reaction.id]['upper_bound'] = v0_fluxes[reaction.id] else: logger.debug('Cycle detected: {}'.format(reaction.id)) cycle_count += 1 v2_one_cycle_fluxes = remove_infeasible_cycles(model, v0_fluxes, fix=[reaction.id]) tm = TimeMachine() for key, v1_flux in six.iteritems(v1_cycle_free_fluxes): if v1_flux == 0 and v2_one_cycle_fluxes[key] != 0: knockout_reaction = model.reactions.get_by_id(key) tm(do=partial(setattr, knockout_reaction, 'lower_bound', 0.), undo=partial(setattr, knockout_reaction, 'lower_bound', knockout_reaction.lower_bound)) tm(do=partial(setattr, knockout_reaction, 'upper_bound', 0.), undo=partial(setattr, knockout_reaction, 'upper_bound', knockout_reaction.lower_bound)) model.objective.direction = 'max' try: solution = model.solve() except Unbounded: fva_sol[reaction.id]['upper_bound'] = numpy.inf except Infeasible: fva_sol[reaction.id]['upper_bound'] = 0 else: fva_sol[reaction.id]['upper_bound'] = solution.f finally: tm.reset() df = pandas.DataFrame.from_dict(fva_sol, orient='index') lb_higher_ub = df[df.lower_bound > df.upper_bound] assert (( lb_higher_ub.lower_bound - lb_higher_ub.upper_bound) < 1e-6).all() # Assert that these cases really only numerical artifacts df.lower_bound[lb_higher_ub.index] = df.upper_bound[lb_higher_ub.index] finally: model.objective = original_objective return df
def _cycle_free_fva(model, reactions=None, sloppy=True, sloppy_bound=666): """Cycle free flux-variability analysis. (http://cran.r-project.org/web/packages/sybilcycleFreeFlux/index.html) Parameters ---------- model : SolverBasedModel reactions : list List of reactions whose flux-ranges should be determined. sloppy : boolean, optional If true, only fluxes v with abs(v) > sloppy_bound are checked to be futile cycles (defaults to True). sloppy_bound : int, optional The threshold bound used by sloppy (defaults to the number of the beast). """ cycle_count = 0 try: original_objective = copy(model.objective) if reactions is None: reactions = model.reactions else: reactions = model._ids_to_reactions(reactions) fva_sol = OrderedDict() for reaction in reactions: fva_sol[reaction.id] = dict() model.objective = reaction model.objective.direction = 'min' try: solution = model.solve() except Unbounded: fva_sol[reaction.id]['lower_bound'] = -numpy.inf continue except Infeasible: fva_sol[reaction.id]['lower_bound'] = 0 continue except Exception as e: raise e bound = solution.f if sloppy and abs(bound) < sloppy_bound: fva_sol[reaction.id]['lower_bound'] = bound else: logger.debug('Determine if {} with bound {} is a cycle'.format( reaction.id, bound)) v0_fluxes = solution.x_dict v1_cycle_free_fluxes = remove_infeasible_cycles( model, v0_fluxes) if abs(v1_cycle_free_fluxes[reaction.id] - bound) < 10**-6: fva_sol[reaction.id]['lower_bound'] = bound else: logger.debug('Cycle detected: {}'.format(reaction.id)) cycle_count += 1 v2_one_cycle_fluxes = remove_infeasible_cycles( model, v0_fluxes, fix=[reaction.id]) tm = TimeMachine() for key, v1_flux in six.iteritems(v1_cycle_free_fluxes): if v1_flux == 0 and v2_one_cycle_fluxes[key] != 0: knockout_reaction = model.reactions.get_by_id(key) tm(do=partial(setattr, knockout_reaction, 'lower_bound', 0.), undo=partial(setattr, knockout_reaction, 'lower_bound', knockout_reaction.lower_bound)) tm(do=partial(setattr, knockout_reaction, 'upper_bound', 0.), undo=partial(setattr, knockout_reaction, 'upper_bound', knockout_reaction.lower_bound)) model.objective.direction = 'min' try: solution = model.solve() except Unbounded: fva_sol[reaction.id]['lower_bound'] = -numpy.inf except Infeasible: fva_sol[reaction.id]['lower_bound'] = 0 else: fva_sol[reaction.id]['lower_bound'] = solution.f finally: tm.reset() for reaction in reactions: model.objective = reaction model.objective.direction = 'max' try: solution = model.solve() except Unbounded: fva_sol[reaction.id]['upper_bound'] = numpy.inf continue except Infeasible: fva_sol[reaction.id]['upper_bound'] = 0 continue except Exception as e: raise e else: bound = solution.f if sloppy and abs(bound) < sloppy_bound: fva_sol[reaction.id]['upper_bound'] = bound else: logger.debug( 'Determine if {} with bound {} is a cycle'.format( reaction.id, bound)) v0_fluxes = solution.x_dict v1_cycle_free_fluxes = remove_infeasible_cycles( model, v0_fluxes) if abs(v1_cycle_free_fluxes[reaction.id] - bound) < 10**-6: fva_sol[reaction.id]['upper_bound'] = v0_fluxes[ reaction.id] else: logger.debug('Cycle detected: {}'.format(reaction.id)) cycle_count += 1 v2_one_cycle_fluxes = remove_infeasible_cycles( model, v0_fluxes, fix=[reaction.id]) tm = TimeMachine() for key, v1_flux in six.iteritems( v1_cycle_free_fluxes): if v1_flux == 0 and v2_one_cycle_fluxes[key] != 0: knockout_reaction = model.reactions.get_by_id( key) tm(do=partial(setattr, knockout_reaction, 'lower_bound', 0.), undo=partial(setattr, knockout_reaction, 'lower_bound', knockout_reaction.lower_bound)) tm(do=partial(setattr, knockout_reaction, 'upper_bound', 0.), undo=partial(setattr, knockout_reaction, 'upper_bound', knockout_reaction.lower_bound)) model.objective.direction = 'max' try: solution = model.solve() except Unbounded: fva_sol[reaction.id]['upper_bound'] = numpy.inf except Infeasible: fva_sol[reaction.id]['upper_bound'] = 0 else: fva_sol[reaction.id]['upper_bound'] = solution.f finally: tm.reset() df = pandas.DataFrame.from_dict(fva_sol, orient='index') lb_higher_ub = df[df.lower_bound > df.upper_bound] assert ( (lb_higher_ub.lower_bound - lb_higher_ub.upper_bound) < 1e-6 ).all() # Assert that these cases really only numerical artifacts df.lower_bound[lb_higher_ub.index] = df.upper_bound[lb_higher_ub.index] finally: model.objective = original_objective return df