Source code for cobra.core.Model

#cobra.core.Model.py
#TODO: Improve copy time.  Perhaps use references for metabolites in
#reactions.
#Here we're dealing with the fact that numpy isn't supported in jython
#and we've made some numjy modules that use the cern.colt matrices to
#mimic the used numpy behavior.
from warnings import warn
from copy import deepcopy
from ..solvers import optimize
from .Object import Object
from .Reaction import Reaction
from .Metabolite import Metabolite
from .Formula import Formula
from .DictList import DictList
#*********************************************************************************
#
#TODO: Implement self.reactions[:]._boundary and use

# Note, there are some issues with using a gene as opposed to a protein in the
#nomenclature; this will be addressed after the first iteration of cleaning.
#
# Note, when a reaction is added to the Model it will no longer keep personal
#instances of it's Metabolites, it will reference Model.metabolites to improve
#performance.  When doing this, take care to monitor the metabolite coefficients.
#Do the same for Model.reactions[:].genes and Model.genes
#
#*********************************************************************************

#######################
#BEGIN Class Model
#
[docs]class Model(Object): """Model is a class for analyzing metabolic models with the COBRA toolbox developed in the Palsson Lab at UCSD. Make all of the objects (Reaction, Metabolite, ...) to make OOP easier. """ def __setstate__(self, state): """Make sure all cobra.Objects in the model point to the model TODO: Make sure that the genes and metabolites referenced by the reactions.(genes|metabolites) point to the model's genes and metabolites. """ self.__dict__.update(state) [[setattr(x, '_model', self) for x in self.__dict__[y]] for y in ['reactions', 'genes', 'metabolites']] def __init__(self, description=None): if isinstance(description, Model): self.__dict__ = description.__dict__ else: Object.__init__(self, description) self.description = self.id self._trimmed = False #This might get changed to a dict of #gene:[reactions in which the gene participates] self._trimmed_genes = None #This will be integrated with _trimmed self._trimmed_reactions = None #as will this self.legacy_format = False #DEPRECATED #Allow the creation of an empty object which will facilitate development #of SBML parsers and other development issues. self.genes = DictList() self.reactions = DictList() #A list of cobra.Reactions self.metabolites = DictList() #A list of cobra.Metabolites #genes based on their ids {Gene.id: Gene} self.compartments = {} def __add__(self, other_model): """Adds two models. + The issue of reactions being able to exists in multiple Models now arises, the same for metabolites and such. This might be a little difficult as a reaction with the same name / id in two models might have different coefficients for their metabolites due to pH and whatnot making them different reactions. """ new_model = self.copy() new_reactions = deepcopy(other_model.reactions) new_model.add_reactions(new_reactions) new_model.id = self.id + '_' + other_model.id return new_model def __iadd__(self, other_model): """Adds a Model to this model += The issue of reactions being able to exists in multiple Models now arises, the same for metabolites and such. This might be a little difficult as a reaction with the same name / id in two models might have different coefficients for their metabolites due to pH and whatnot making them different reactions. """ new_reactions = deepcopy(other_model.reactions) self.add_reactions(new_reactions) self.id = self.id + '_' + other_model.id return self
[docs] def copy(self, print_time=False): """Provides a partial 'deepcopy' of the Model. All of the Metabolite, Gene, and Reaction objects are created anew but in a faster fashion than deepcopy print_time: Boolean used for debugging """ the_copy = Object.guided_copy(self) the_copy.metabolites = None the_copy.reactions = None the_copy.compartments = deepcopy(self.compartments) if print_time: from time import time start_time = time() the_metabolites = DictList([x.guided_copy(the_copy) for x in self.metabolites]) if print_time: print 'Metabolite guided copy: %1.4f'%(time() - start_time) start_time = time() the_genes = DictList([x.guided_copy(the_copy) for x in self.genes]) if print_time: print 'Gene guided copy: %1.4f'%(time() - start_time) start_time = time() #TODO: See if we can use the DictList objects instead metabolite_dict = dict([(k.id, k) for k in the_metabolites]) gene_dict = dict([(k.id, k) for k in the_genes]) the_reactions = DictList([x.guided_copy(the_copy, the_metabolites._object_dict, the_genes._object_dict) for x in self.reactions]) if print_time: print 'Reaction guided copy: %1.4f'%(time() - start_time) the_copy.reactions = the_reactions the_copy.genes = the_genes the_copy.metabolites = the_metabolites return the_copy
[docs] def add_metabolites(self, metabolite_list): """Will add a list of metabolites to the the object, if they do not exist and then expand the stochiometric matrix metabolite_list: A list of :class:`~cobra.core.Metabolite` objects """ if not hasattr(metabolite_list, '__iter__'): metabolite_list = [metabolite_list] #First check whether the metabolites exist in the model metabolite_list = [x for x in metabolite_list if x.id not in self.metabolites] [setattr(x, '_model', self) for x in metabolite_list] self.metabolites += metabolite_list
def _update_reaction(self, reaction): """Updates everything associated with the reaction.id of reaction. reaction: A cobra.Reaction object, or a list of these objects. """ warn("WARNING: To be modified. It will be faster to use properties of the DictList " +\ "self.reactions to find a reaction and update the matrices " +\ "This function is only used after the Model has been " +\ "converted to matrices. It is typically faster to access the objects" +\ "in the Model directly. This function will eventually moved to another" +\ "module for advanced users due to the potential for mistakes.") if not hasattr(reaction, '__iter__'): reaction = [reaction] for the_reaction in reaction: if the_reaction.id not in self.reactions: print the_reaction.id + ' is not in the model\n' continue reaction_index = self.reactions.index(the_reaction.id) self.reactions[reaction_index] = the_reaction
[docs] def update(self): """Non functional. Model.update is moved to ArrayBasedModel. Please use the to_array_based_model property to create an ArrayBasedModel. """ raise Exception("Model.update is moved to ArrayBasedModel. Please use \n" "the to_array_based_model property to create an ArrayBasedModel.")
[docs] def add_reaction(self, reaction): """Will add a cobra.Reaction object to the model, if reaction.id is not in self.reactions. reaction: A :class:`~cobra.core.Reaction` object """ self.add_reactions(reaction)
[docs] def add_reactions(self, reaction_list): """Will add a cobra.Reaction object to the model, if reaction.id is not in self.reactions. reaction_list: A :class:`~cobra.core.Reaction` object or a list of them """ #Only add the reaction if one with the same ID is not already #present in the model. if type(reaction_list) not in [tuple, list, set, DictList]: reaction_list = [reaction_list] #TODO: Use the DictList properties reactions_in_model = set([x.id for x in reaction_list]).intersection([x.id for x in self.reactions]) if len(reactions_in_model) > 0: print '%i of %i reaction(s) %s already in the model'%(len(reactions_in_model), len(reaction_list), repr(reactions_in_model)) return #TODO: Consider using DictList's here, just make sure that the items get appended #to self.metabolites, self.genes metabolite_dict = {} gene_dict = {} [metabolite_dict.update(dict([(y.id, y) for y in x._metabolites])) for x in reaction_list] new_metabolites = [metabolite_dict[x] for x in set(metabolite_dict).difference(self.metabolites._dict)] if new_metabolites: self.add_metabolites(new_metabolites) [gene_dict.update(dict([(y.id, y) for y in x._genes])) for x in reaction_list] new_genes = [gene_dict[x] for x in set(gene_dict).difference(self.genes._dict)] if new_genes: self.genes += DictList(new_genes) [setattr(x, '_model', self) for x in new_genes] #This might slow down performance #Make sure each reaction knows that it is now part of a Model and uses #metabolites in the Model and genes in the Model for the_reaction in reaction_list: the_reaction._model = self the_reaction._metabolites = dict([(self.metabolites.get_by_id(k.id), v) for k, v in the_reaction._metabolites.items()]) the_reaction._genes = dict([(self.genes.get_by_id(k.id), v) for k, v in the_reaction._genes.items()]) #Make sure the metabolites and genes are aware of the reaction the_reaction._update_awareness() #Add the reactions to the Model self.reactions += reaction_list
[docs] def to_array_based_model(self, deepcopy_model=False): """Makes a :class:`~cobra.core.ArrayBasedModel` from a cobra.Model which may be used to perform linear algebra operations with the stoichiomatric matrix. deepcopy_model: Boolean. If False then the ArrayBasedModel points to the Model """ from .ArrayBasedModel import ArrayBasedModel return ArrayBasedModel(self, deepcopy_model=deepcopy_model)
[docs] def optimize(self, new_objective=None, objective_sense='maximize', the_problem=None, solver='glpk', error_reporting=None, quadratic_component=None, tolerance_optimality=1e-6, tolerance_feasibility=1e-6, tolerance_barrier=1e-10, **kwargs): """Optimize self for self._objective_coefficients or new_objective. NOTE: Only the most commonly used parameters are presented here. Additional parameters for cobra.solvers may be available and specified with the appropriate keyword=value. new_objective: Reaction, String, or Integer referring to a reaction in cobra_model.reactions to set as the objective. Currently, only supports single objective coeffients. Will expand to include mixed objectives. objective_sense: 'maximize' or 'minimize' the_problem: None or a problem object for the specific solver that can be used to hot start the next solution. solver: 'glpk', 'gurobi', or 'cplex' error_reporting: None or True to disable or enable printing errors encountered when trying to find the optimal solution. quadratic_component: None or scipy.sparse.dok of dim(len(cobra_model.reactions),len(cobra_model.reactions)) If not None: Solves quadratic programming problems for cobra_models of the form: cobra_model = ArrayBasedModel(cobra_model) minimize: 0.5 * x' * quadratic_component * x + cobra_model._objective_coefficients' * x such that, cobra_model._lower_bounds <= x <= cobra_model._upper_bounds cobra_model._S * x (cobra_model._constraint_sense) cobra_model._b #See cobra.flux_analysis.solvers for more info on the following parameters. Also, refer to your solver's manual tolerance_optimality: Solver tolerance for optimality. tolerance_feasibility: Solver tolerance for feasibility. tolerance_barrier: Solver tolerance for barrier method lp_method: Solver method to solve the problem #End solver parameters **kwargs: See additional parameters for your specific solver module in cobra.solvers """ the_solution = optimize(self, solver=solver, new_objective=new_objective, objective_sense=objective_sense, the_problem=the_problem, error_reporting=error_reporting, quadratic_component=quadratic_component, tolerance_optimality=tolerance_optimality, tolerance_feasibility=tolerance_feasibility, tolerance_barrier=tolerance_barrier, **kwargs) return the_solution
def _update_metabolite_formula(self, metabolite_name, metabolite_formula): """Associate metabolite_formula with all self.metabolite_names that match metabolite_name. metabolite_name: A string from self.metabolite_names metabolite_formula: A string specifying the chemical formula for metabolite_name. TODO: This should be moved to a separate module """ if not isinstance(the_formula, Formula): the_formula = Formula(the_formula) for the_metabolite in self.metabolites: if the_metabolite.name == metabolite_name: the_metabolite.formula = the_formula
[docs] def remove_reactions(self, the_reactions): """ the_reactions: instance or list of cobra.Reactions or strings of self.reactions[:].id. """ if not hasattr(the_reactions, '__iter__') or \ hasattr(the_reactions, 'id'): the_reactions = [the_reactions] if hasattr(the_reactions[0], 'id'): the_reactions = [x.id for x in the_reactions] reactions_to_delete = [] for the_reaction in the_reactions: try: the_reaction = self.reactions[self.reactions.index(the_reaction)] the_reaction.remove_from_model(self) except: print '%s not in %s'%(the_reaction, self) # #END Class Model #####################