00001 """
00002 Classes and functions dealing with enzyme subsets
00003 Main user interface is class EssDic
00004 functions before this are private(ish) helpers for EssDic
00005 functions following are public
00006 """
00007
00008
00009
00010
00011
00012 import sys
00013 from Util import DynMatrix,Set,Seq,Types
00014 from Structural import StoMat
00015
00016
00017 def EssList(m,k=None):
00018 """ pre: m = ScrumPy.Model()
00019 k = None || k = m.sm.NullSpace()
00020 post: list subsets, each subset is a list of (name, value) tuples
00021 first item is (possibly empty) subset of dead reactions
00022 """
00023
00024 if k == None:
00025 k = m.sm.NullSpace()
00026 else:
00027 k = k.Copy()
00028
00029 k.ZapZeroes()
00030 One = k.Conv(1)
00031 deads = Set.Complement(m.sm.cnames, k.rnames)
00032 ess = [map(lambda x:(x,One), deads)]
00033
00034 while len(k) !=0:
00035 ss = [(k.rnames[0],One)]
00036 row = k[0]
00037 k.DelRow(0)
00038 for r in k.rnames[:]:
00039 ap = Seq.AreParallel(k[r],row)
00040 if ap[0]:
00041 ss.append((r,ap[1]))
00042 k.DelRow(r)
00043 ess.append(ss)
00044
00045 return ess
00046
00047
00048 def EssMtx(m,essl = None):
00049 """ pre: m = ScrumPy.Model()
00050 essl == None || EssAsList(m)
00051 post: matrix of enz subsets """
00052
00053 essl = EssList(m)[1:]
00054 rle = range(len(essl))
00055 ssnames = map(lambda x: "Ess_"+str(x), rle)
00056 rnames = m.sm.cnames[:]
00057 rv = StoMat.StoMat(rnames = rnames, cnames = ssnames)
00058 for ssi in rle:
00059 ss = essl[ssi]
00060 for reac,val in ss:
00061 rv[reac,ssi] = val
00062 return rv
00063
00064
00065
00066 class EssDic(dict):
00067 """ Dictionary subclass mapping enzyme subsets to reactions and vice-versa
00068 pretty much anything useful with subsets should be done via this class
00069 """
00070
00071 def __init__(self,m,essl=None):
00072 """ pre: m = ScrumPy.Model
00073 essl = None || essl = EssList(m)
00074 (only use essl for development/debugging purposes)
00075 post: OK. will write messages on sys.stderr if inconsistent irreversibility
00076 specifications found, but will not act on this
00077 """
00078
00079 if essl == None:
00080 essl = EssList(m)
00081
00082 self.Model = m
00083 self.ReacRevProps = dict(m.sm.RevProps)
00084 self.RevProps = {}
00085 self.Rev ={}
00086 self.Inconsistants = []
00087
00088 self._AddSS("DeadReacs",essl[0])
00089 n = 1
00090 for ss in essl[1:]:
00091 if len(ss)==1:
00092 name = ss[0][0]
00093 else:
00094 name = "Ess_"+str(n)
00095 n+= 1
00096 self._AddSS(name,ss)
00097
00098
00099 def _AddSS(self,key,ss):
00100 """ Private """
00101
00102 val = {}
00103 rev = True
00104 for s in ss:
00105 reac = s[0]
00106 val[reac] = s[1]
00107 self.Rev[reac] = key
00108 if self.ReacRevProps[reac] != StoMat.t_Rever:
00109 rev = False
00110
00111 self[key]= val
00112 if rev:
00113 self.RevProps[key] = StoMat.t_Rever
00114 else:
00115 self.RevProps[key] = StoMat.t_Irrev
00116 self.RevCheck(key)
00117
00118
00119
00120
00121 def RevCheck(self, key):
00122
00123 def WrongWay(ss):
00124 for reac in ss:
00125 coeff = ss[reac]
00126 revcrit = self.ReacRevProps[reac]
00127 if (coeff < 0 and revcrit == StoMat.t_Irrev) or (
00128 coeff > 0 and revcrit == StoMat.t_BackIrrev):
00129 return True
00130 return False
00131
00132
00133 ss = self[key]
00134
00135 if WrongWay(ss):
00136 for reac in ss.keys():
00137 ss[reac] *= -1
00138
00139 if WrongWay(ss):
00140 sys.stderr.write("!\n! Inconsistent irreversible reactions in subset "+ key + "\n")
00141 sys.stderr.write("! " + str(ss.keys()) + "\n!\n")
00142 self.Inconsistants.append(key)
00143
00144
00145 def RevCheckOld(self, key):
00146 """ pre: self.has_key(key) (privateish)
00147 post: checks for irreversible reactions in self[key],
00148 ensures correct sign of coeffs, and marks as irrev if irreversible,
00149 reports inconsistent irreversbility in self[key]
00150 """
00151
00152 subset = self[key]
00153 irrevs = []
00154 negate = False
00155
00156 for reac in subset.keys():
00157 if reac in self.Model.sm.Irrevs:
00158 irrevs.append(reac)
00159 if subset[reac] <0:
00160 negate = True
00161
00162 if negate:
00163 for reac in subset.keys():
00164 subset[reac] *= -1
00165
00166 error = False
00167 for reac in irrevs:
00168 if subset[reac] < 0:
00169 error = True
00170
00171 if error:
00172 sys.stderr.write("!\n! Inconsistent irreversible reactions in subset "+ key + "\n")
00173 sys.stderr.write("! " + str(subset.keys()) + "\n!\n")
00174 self.Inconsistants.append(key)
00175 del self.Irrevs[key]
00176
00177
00178
00179
00180
00181 def ReacToSS(self,reac):
00182 """ pre: reac present in the model
00183 post: name of subset of which reac is a member
00184 """
00185 return self.Rev[reac]
00186
00187
00188
00189 def SameSS(self,reac):
00190 """ pre: self.ReacToSS(reac)
00191 post: return the names of reactions in the same subset (including reac)
00192 """
00193 return self[self.ReacToSS(reac)].keys()
00194
00195
00196
00197
00198 def ToMtx(self,ExclDeadIncs=False):
00199 """ pre: True
00200 post: subsets in matrix form, ExclDeadIncs => don't include dead or inconsistant subsets in the matrix
00201 """
00202
00203 rnames = self.Model.sm.cnames[:]
00204 ssnames = self.keys()
00205 if ExclDeadIncs:
00206 for i in self.Inconsistants+["DeadReacs"]:
00207 ssnames.remove(i)
00208
00209 rv = StoMat.StoMat(rnames = rnames, cnames =ssnames)
00210 for ssn in ssnames:
00211 ss = self[ssn]
00212 for reac in ss.keys():
00213 rv[reac,ssn] = self[ssn][reac]
00214 rv.RevProps = dict(self.ReacRevProps)
00215
00216 return rv
00217
00218
00219 def CondensedSMs(self):
00220 """ pre: True
00221 post: (self.ToMtx(), Condensed Internal SM, Condensed External SM) """
00222
00223
00224 ssm = self.ToMtx(True)
00225 m = self.Model
00226 sm = m.sm.Mul(ssm)
00227 sm.ZapZeroes()
00228
00229 sm.RevProps = dict(self.RevProps)
00230 smx = m.smexterns.Mul(ssm)
00231 smx.ZapZeroes()
00232 smx.RevProps = dict(self.RevProps)
00233
00234 return ssm, sm, smx
00235
00236
00237
00238 def SaveCondensedModel(self,fname=None):
00239 """ pre: fname != None => fname can be opened for writing
00240 else: current working directory is writable
00241 post: current model is in condensed form saved as a ScrumPy file
00242 with a cPickled self.
00243 as fname_Condensed and fname_Condensed_esd.pic
00244 if fname was None model.fname will be used
00245 """
00246
00247 m = self.Model
00248
00249 mfname = fname or m.FileName + "_Condensed"
00250 out = open(mfname,"w")
00251 print "Saving condensed model", mfname
00252
00253 smx = m.smexterns.Mul(self.ToMtx(True))
00254
00255
00256 smx.RevProps = self.RevProps()
00257 for c in range(len(smx.cnames)):
00258 cname = smx.cnames[c]
00259 if len(self[cname])>1:
00260 reac = "_".join([cname]+self[cname].keys())
00261 smx.RevProps[reac] = self.RevProps[cname]
00262 smx.cnames[c] = reac
00263
00264 smx.ToScrumPy(out,Externs=self.Model.Externals())
00265
00266
00267
00268 def ToList(self):
00269
00270 keys = self.keys()
00271 keys.remove("DeadReacs")
00272 rv = [self["DeadReacs"].items()]
00273 for k in keys:
00274 rv.append(map(lambda x:x[0],self[k].items()))
00275 return rv
00276
00277 def SaveFile(self, FileName=None):
00278 """ pre: FileName != None => open(FileName,"w") will succeed
00279 post: self saved as Pickle to FileName if given
00280 or to self.Model.FileName +" _esd.pic" if FileName != None"""
00281
00282 print "Don't use 'SaveFile()'"
00283 return
00284
00285 if FileName == None:
00286 FileName = self.Model.FileName + "_esd.pic"
00287
00288 model = self.Model
00289 self.Model = self.Model.FileName
00290
00291 for v in self.values():
00292 for k in v.keys():
00293 v[k] = str(v[k])
00294
00295 out = open(FileName,"w")
00296 pickle.dump(self,out)
00297
00298 self.Model = model
00299
00300 for v in self.values():
00301 for k in v.keys():
00302 v[k] = Types.ArbRat(v[k])
00303
00304
00305
00306 def IsIrrev(self,ss):
00307 """ pre: True
00308 post: self.IsIrrev(ss) => ss is irreversible
00309 """
00310 return self.RevProps[ss] != StoMat.t_Rever
00311
00312
00313 def Irrev_ss(self):
00314 """ pre: True
00315 post: list of irreversible subsets
00316 """
00317 return map(lambda reac:self.RevProps[reac], filter(self.IsIrrev, self.keys()))
00318
00319
00320
00321 def EsdFromFile(FileName, LoadModel=False):
00322 """ pre: Esd.SaveFile(FileName)
00323 post: loads and returns previously saved esd
00324 LoadModel => model is loaded too
00325 """
00326
00327 inp = open(FileName)
00328 rv = pickle.load(inp)
00329
00330
00331 for v in rv.values():
00332 for k in v.keys():
00333 v[k] = Types.ArbRat(v[k])
00334
00335
00336 if LoadModel:
00337 rv.Model = ScrumPy.Model(rv.Model)
00338 return rv
00339