示例#1
0
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])
示例#2
0
 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]
示例#3
0
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
示例#4
0
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])
示例#5
0
 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)
示例#6
0
 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)
示例#7
0
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()
示例#8
0
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
示例#9
0
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()
示例#10
0
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
示例#11
0
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
示例#12
0
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
示例#13
0
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
示例#14
0
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
示例#15
0
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