cobra.flux_analysis.variability — cobra 0.2.0 documentation

### Navigation

- index
- modules |
- cobra 0.2.0 documentation »
- Module code »

# Source code for cobra.flux_analysis.variability

    from __future__ import with_statement
    #cobra.flux_analysis.variablity.py
    #runs flux variablity analysis on a Model object.
    from math import floor,ceil
    from copy import deepcopy
    from ..core.Metabolite import Metabolite
    try:
        from ..external.ppmap import ppmap
        __parallel_mode_available = True
    except:
        __parallel_mode_available = False
    #TODO: Add in a ppmap section for running in parallel
    def flux_variability_analysis_wrapper(keywords):
        """Provides an interface to call flux_variability_analysis from ppmap

        """
        try:
            from cPickle import dump
        except:
            from pickle import dump
        import sys
        #Need to do a top level import because of how the parallel processes are called
        sys.path.insert(0, "../..")
        from cobra.flux_analysis.variability import flux_variability_analysis
        sys.path.pop(0)
        results_dict = {}
        new_objective = keywords.pop('new_objective')
        output_directory = None
        if 'output_directory' in keywords:
            output_directory = keywords.pop('output_directory')
        if not hasattr(new_objective, '__iter__'):
            new_objective = [new_objective]
        for the_objective in new_objective:
            the_result = results_dict[the_objective] = flux_variability_analysis(**keywords)
            if output_directory:
                with open('%s%s.pickle'%(output_directory,
                                         the_objective), 'w') as out_file:
                    dump(the_result, out_file)
        if len(new_objective) == 1:
            return the_result
        else:
            return results_dict

    def flux_variability_analysis(cobra_model, fraction_of_optimum=1.,
                                  objective_sense='maximize', the_reactions=None,
                                  allow_loops=True, solver='glpk',
                                  the_problem='return', tolerance_optimality=1e-6,
                                  tolerance_feasibility=1e-6, tolerance_barrier=1e-8,
                                  lp_method=1, lp_parallel=0, new_objective=None,
                                  relax_b=None, error_reporting=None,
                                  number_of_processes=1, copy_model=True):
        """Runs flux variability analysis on a cobra.Model object

        cobra_model: a Model object

        fraction_of_optimum: fraction of the optimal solution that must be realized

        the_reactions: list of reactions to run FVA on.  if None then run on all
        reactions in the Model

        allow_loops:  Not Implemented.  If false then run the simulations with the
        loop law method to remove loops.

        the_problem: If 'return' or an LP model object for the specified solver then
        the optimizations will be sped up by attempting to use a previous solution
        as a starting point to optimize the current problem.  Can reduce
        simulation time by over an order of magnitude.

        solver: 'glpk', 'gurobi', or 'cplex'.

        the_problem: a problem object for the corresponding solver, 'return', or
        a float representing the wt_solution

        number_of_processes: If greater than 1 then this function will attempt
        to parallelize the problem.  NOTE: Currently not functional

        returns a dictionary: {reaction.id: {'maximum': float, 'minimum': float}}

        TODO: update how Metabolite._bound is handled so we can set a range instead
        of just a single value.  This will be done in cobra.flux_analysis.solvers.

        """
        #Need to copy the model because we're updating reactions.  However,
        #we can always just remove them.
        if isinstance(the_problem, float):
            wt_solution = the_problem
            the_problem='return'
        else:
            wt_model = cobra_model
            wt_model.optimize(solver=solver,objective_sense='maximize',
                              tolerance_optimality=tolerance_optimality,
                              tolerance_feasibility=tolerance_feasibility,
                              tolerance_barrier=tolerance_barrier,
                              lp_method=lp_method, lp_parallel=lp_parallel,
                              the_problem=the_problem, new_objective=new_objective)
            wt_solution = wt_model.solution.f
        if copy_model:
            cobra_model = cobra_model.copy()
        if not the_reactions:
            the_reactions = cobra_model.reactions
        else:
            if hasattr(the_reactions[0], 'id'):
                #Because cobra_model = cobra_model.copy() any cobra.Reactions
                #from the input won't point to cobra_model
                the_reactions = [x.id for x in the_reactions]
            #
            the_reactions = map(cobra_model.reactions.get_by_id, the_reactions)
        #If parallel mode is called for then give it a try
        if number_of_processes > 1 and __parallel_mode_available:
            the_problem = wt_solution #Solver objects are not thread safe
            the_reactions = [x.id for x in the_reactions]
            parameter_dict = dict([(x, eval(x))
                                   for x in ['fraction_of_optimum',
                                             'objective_sense',
                                             'allow_loops',
                                             'solver',
                                             'the_problem',
                                             'tolerance_optimality',
                                             'tolerance_feasibility',
                                             'tolerance_barrier',
                                             'lp_method',
                                             'lp_parallel',
                                             'new_objective',
                                             'relax_b',
                                             'error_reporting']])
            #Might need to deepcopy when threading
            parameter_dict['cobra_model'] = cobra_model.copy()
            parameter_dict['copy_model'] = False
            parameter_list = []
            number_of_reactions = len(the_reactions)
            if number_of_reactions < number_of_processes:
                number_of_processes = number_of_reactions
            reactions_per_process = int(floor(number_of_reactions/number_of_processes))
            for i in range(number_of_processes):
                tmp_parameters = deepcopy(parameter_dict)
                tmp_parameters['the_reactions'] = the_reactions[:reactions_per_process]
                parameter_list.append(tmp_parameters)
                the_reactions = the_reactions[reactions_per_process:]
            #The remainder goes with the last processes
            parameter_list[-1]['the_reactions'] += the_reactions
            variability_dict = {}
            pp_pointer = ppmap(number_of_processes,
                               flux_variability_analysis_wrapper, parameter_list)

            [variability_dict.update(x) for x in list(pp_pointer)]
        else:
            #Basically, add a virtual metabolite that reflects the
            #objective coefficeints and the solution
            objective_metabolite = Metabolite('objective')
            if not copy_model:
                original_objectives = dict([(k, float(k.objective_coefficient))
                                            for k in cobra_model.reactions])

            [x.add_metabolites({objective_metabolite: x.objective_coefficient})
             for x in cobra_model.reactions if x.objective_coefficient != 0]

            #TODO: Kick back an error if cobra_model.solution.status is not optimal
            if objective_sense == 'maximize':
                objective_cutoff = floor(wt_solution/tolerance_optimality)*\
                                   tolerance_optimality*fraction_of_optimum
            else:
                objective_cutoff = ceil(wt_solution/tolerance_optimality)*\
                                   tolerance_optimality*fraction_of_optimum
            objective_metabolite._constraint_sense = 'E'
            objective_metabolite._bound = objective_cutoff
            #If objective_metabolite._model is None then we should cycle through
            #each reaction as the initial objective.
            if the_problem:
                the_problem = cobra_model.optimize(solver=solver,
                                                   objective_sense='maximize',
                                                   tolerance_optimality=tolerance_optimality,
                                                   tolerance_feasibility=tolerance_feasibility,
                                                   tolerance_barrier=tolerance_barrier,
                                                   lp_method=lp_method, lp_parallel=lp_parallel,
                                                   the_problem='return', relax_b=relax_b,
                                                   error_reporting=error_reporting)
            variability_dict = {}
            the_sense_dict = {'maximize': 'maximum',
                              'minimize': 'minimum'}
            basic_problem = the_problem
            #Adding in solver-specific code could improve the speed substantially.
            for the_reaction in the_reactions:
                tmp_dict = {}
                the_problem = basic_problem
                for the_sense, the_description in the_sense_dict.iteritems():
                    the_problem = cobra_model.optimize(solver=solver,
                                                       new_objective=the_reaction,
                                                       objective_sense=the_sense,
                                                       tolerance_optimality=tolerance_optimality,
                                                       tolerance_feasibility=tolerance_feasibility,
                                                       tolerance_barrier=tolerance_barrier,
                                                       lp_method=lp_method,
                                                       lp_parallel=lp_parallel,
                                                       the_problem=the_problem,
                                                       error_reporting=error_reporting,
                                                       update_problem_reaction_bounds=False)
                    tmp_dict[the_description] = cobra_model.solution.f
                variability_dict[the_reaction.id] = tmp_dict
            if not copy_model:
                [setattr(k, 'objective_coefficient', v)
                 for k, v in original_objectives.iteritems()]
                objective_metabolite.remove_from_model()
        return variability_dict

    def find_blocked_reactions(cobra_model, the_reactions=None, allow_loops=True,
                                solver='glpk', the_problem='return',
                               tolerance_optimality=1e-9,
                               open_exchanges=False):
        """Finds reactions that cannot carry a flux with the current
        exchange reaction settings for cobra_model, using flux variability
        analysis.

        """
        print 'This needs to be updated to deal with external boundaries'
        cobra_model = cobra_model.copy()
        blocked_reactions = []
        if not the_reactions:
            the_reactions = cobra_model.reactions
        if open_exchanges:
            print 'DEPRECATED: Move to using the Reaction.boundary attribute'
            exchange_reactions = [x for x in cobra_model.reactions
                                  if x.startswith('EX')]
            for the_reaction in exchange_reactions:
                if the_reaction.lower_bound >= 0:
                    the_reaction.lower_bound = -1000
                if the_reaction.upper_bound >= 0:
                    the_reaction.upper_bound = 1000
        flux_span_dict = flux_variability_analysis(cobra_model,
                                                   fraction_of_optimum = 0.,
                                                   the_reactions = the_reactions,
                                                   allow_loops = allow_loops,
                                                   solver = solver,
                                                   the_problem = the_problem,
                                                   tolerance_optimality = tolerance_optimality)
        blocked_reactions = [k for k, v in flux_span_dict.items()\
                              if max(map(abs,v.values())) < tolerance_optimality]
        return(blocked_reactions)

    def run_fva(solver='cplex'):
        """
        For debugging purposes only

        """
        from test import salmonella_pickle
        try:
            from cPickle import load
        except:
            from pickle import load
        with open(salmonella_pickle) as in_file:
            cobra_model = load(in_file)
        fva_out =  flux_variability_analysis(cobra_model,
                                             the_reactions=cobra_model.reactions,#[100:140],
                                             solver=solver,number_of_processes=1)

### Navigation

- index
- modules |
- cobra 0.2.0 documentation »
- Module code »