1111 logging .WARNING #INFO
1212) # When debugging - set this to INFO then change needed messages below from DEBUG to INFO
1313
14- # Base class for FBA packages
15- class ObjectivePkg (BaseFBAPkg ):
16- def __init__ (self , model ):
17- BaseFBAPkg .__init__ (self , model , "objective builder" , {}, {})
18- self .objective_cache = {}
19- self .objective_string_cache = {}
14+ class ObjectiveTerm :
15+ def __init__ (self , variable , coefficient ,direction = "" ):
16+ self .coefficient = coefficient
17+ self .variable = variable
18+ self .direction = direction
2019
21- def build_package (self ,objective_string ,objective_name = None ,cache_current_objective_name = None ):
22- #Saving unmodified objective string
23- if objective_name == None :
24- objective_name = objective_string
25- #Caching objective and objective string
26- self .objective_string_cache [objective_name ] = objective_string
27- #Caching the current objective if a name was specified
28- if cache_current_objective_name != None :
29- self .objective_cache [cache_current_objective_name ] = self .model .objective
30- #Creating empty objective - always max
31- self .objective_cache [objective_name ] = self .model .problem .Objective (Zero , direction = "max" )
32- #Parsing objective string of form: MAX{(1)bio1|(1)rxn00001_c0}
33- obj_coef = dict ()
34- #Checking if there is a directionality in the objective
20+ @staticmethod
21+ def from_string (term_string ):
22+ coefficient = 1
23+ variable = None
24+ direction = ""
25+ #Checking for coefficient
26+ if term_string [0 :1 ] == "(" :
27+ array = term_string .split (")" )
28+ coefficient = float (array [0 ][1 ])
29+ term_string = array [1 ]
30+ #Checking for a +/- on term
31+ if term_string [0 :1 ] == "+" or term_string [0 :1 ] == "-" :
32+ variable = term_string [1 :]
33+ direction = term_string [0 :1 ]
34+ else :
35+ variable = term_string
36+ direction = ""
37+ return ObjectiveTerm (variable , coefficient , direction )
38+
39+ def to_string (self ):
40+ return "(" + str (self .coefficient )+ ")" + self .direction + self .variable
41+
42+
43+ #Class for defining an objective function in a modelseedpy model.
44+ class ObjectiveData :
45+ def __init__ (self , terms , sign = 1 ):
46+ self .sign = sign
47+ self .terms = terms
48+
49+ @staticmethod
50+ def from_string (objective_string ):
3551 sign = 1
52+ terms = []
3653 if objective_string [0 :3 ] == "MAX" :
3754 objective_string = objective_string [4 :- 1 ]#Clearing out the directionality MAX{}
3855 elif objective_string [0 :3 ] == "MIN" :
3956 sign = - 1
4057 objective_string = objective_string [4 :- 1 ]#Clearing out the directionality MIN{}
41- #Building dictionary of variable names
42- varnames = {}
43- for variable in self .model .solver .variables :
44- varnames [variable .name ] = variable
45- #Parsing the main body of the objective string
46- terms = objective_string .split ("|" )
47- for term in terms :
48- coef = 1
49- #Checking for coefficient
50- if term [0 :1 ] == "(" :
51- array = term .split (")" )
52- coef = float (array [0 ][1 ])
53- term = array [1 ]
54- #Applying the directionality sign
55- coef = coef * sign
56- #Checking for a +/- on term
57- if term [0 :1 ] == "+" or term [0 :1 ] == "-" :
58- rxnid = term [1 :]
59- if rxnid not in self .model .reactions :
60- logger .warning (rxnid + " in objective strin not found in model." )
61- else :
62- rxnobj = self .model .reactions .get_by_id (rxnid )
63- if term [0 :1 ] == "+" :
64- obj_coef [rxnobj .forward_variable ] = coef
65- elif term [0 :1 ] == "-" :
66- obj_coef [rxnobj .reverse_variable ] = coef
67- #Checking if the term is just a reaction ID
68- elif term in self .model .reactions :
69- rxnobj = self .model .reactions .get_by_id (term )
70- obj_coef [rxnobj .forward_variable ] = coef
71- obj_coef [rxnobj .reverse_variable ] = - 1 * coef
72- elif term in varnames :
73- obj_coef [varnames [term ]] = coef
74- self .model .objective = self .objective_cache [objective_name ]
75- self .model .objective .set_linear_coefficients (obj_coef )
76- print (self .model .objective )
58+ term_strings = objective_string .split ("|" )
59+ for term_string in term_strings :
60+ term = ObjectiveTerm .from_string (term_string )
61+ terms .append (term )
62+ return ObjectiveData (terms , sign )
63+
64+ def to_string (self ):
65+ objective_string = ""
66+ if self .sign == 1 :
67+ objective_string += "MAX{"
68+ else :
69+ objective_string += "MIN{"
70+ for term in self .terms :
71+ objective_string += term .to_string ()+ "|"
72+ objective_string = objective_string [:- 1 ] + "}"
73+ return objective_string
7774
75+ def to_cobrapy_objective (self , model ):
76+ #Creating empty objective
77+ objective = model .problem .Objective (Zero , direction = "max" )
78+ #Parsing the terms
79+ coefficients = {}
80+ for term in self .terms :
81+ if term .variable in model .reactions :
82+ coef = term .coefficient * self .sign
83+ rxnobj = model .reactions .get_by_id (term .variable )
84+ if term .direction == "+" :
85+ coefficients [rxnobj .forward_variable ] = coef
86+ elif term .direction == "-" :
87+ coefficients [rxnobj .reverse_variable ] = coef
88+ else :
89+ coefficients [rxnobj .forward_variable ] = coef
90+ coefficients [rxnobj .reverse_variable ] = - 1 * coef
91+ else :
92+ logger .warning ("Reaction " + term .variable + " not found in model" )
93+ model .objective = objective
94+ objective .set_linear_coefficients (coefficients )
95+ return objective
96+
97+ # Base class for FBA packages
98+ class ObjectivePkg (BaseFBAPkg ):
99+ def __init__ (self , model ):
100+ BaseFBAPkg .__init__ (self , model , "objective builder" , {}, {})
101+ self .original_model_objective = None
102+ self .objective_name = None
103+ self .objective_data = None
104+ self .objective_data_cache = {}
105+
106+ def build_package (self ,objective_or_string ,objective_name = None ,set_objective = True ):
107+ #Caching the current objective
108+ self .original_model_objective = self .model .objective
109+ #check if input is a string or an ObjectiveData object
110+ if isinstance (objective_or_string , str ):
111+ self .objective_data = ObjectiveData .from_string (objective_or_string )
112+ elif isinstance (objective_or_string , ObjectiveData ):
113+ self .objective_data = objective_or_string
114+ else :
115+ raise TypeError ("Input must be a string or an ObjectiveData object" )
116+ #Setting default objective name if not provided
117+ self .objective_name = objective_name
118+ if objective_name == None :
119+ self .objective_name = self .objective_data .to_string ()
120+ #Caching objective with name
121+ self .objective_data_cache [self .objective_name ] = self .objective_data
122+ #Creating the objective in the model
123+ if set_objective :
124+ self .objective_data_cache [self .objective_name ].to_cobrapy_objective (self .model )
125+ return objective_name
126+
78127 def restore_objective (self ,name ):
79- if name in self .objective_cache :
80- self .model .objective = self .objective_cache [name ]
128+ self .original_model_objective = self .model .objective
129+ if name in self .objective_data_cache :
130+ self .model .objective = self .objective_data_cache [name ].to_cobrapy_objective (self .model )
81131 else :
82132 logger .warning ("Objective " + name + " not found in cache" )
0 commit comments