00001 import Base
00002 import Tags
00003 from ECEquivs import ECEquivs
00004
00005
00006 DefaultFile = "reactions.dat"
00007
00008 from Parser.lexer import t_Irrev, t_BackIrrev, t_Rever
00009
00010
00011 DirecMap = {
00012 'IRREVERSIBLE-RIGHT-TO-LEFT' : t_BackIrrev,
00013 'PHYSIOL-RIGHT-TO-LEFT' : t_BackIrrev,
00014 'LEFT-TO-RIGHT' : t_Rever,
00015 'REVERSIBLE' : t_Rever,
00016 'RIGHT-TO-LEFT' : t_BackIrrev,
00017 'IRREVERSIBLE-LEFT-TO-RIGHT' : t_Irrev,
00018 'PHYSIOL-LEFT-TO-RIGHT' : t_Irrev
00019 }
00020
00021 DefaultDirec = DirecMap['LEFT-TO-RIGHT']
00022
00023
00024 class Record(Base.Record):
00025 ParentFields=[Tags.EnzReac]
00026 ChildFields = [Tags.Left, Tags.Right, Tags.InPath]
00027 RecordClass="Reaction"
00028 def __init__(self, id,BadCoeffs=[],**kwargs):
00029 Base.Record.__init__(
00030 self,
00031 id,
00032 **kwargs)
00033 self.lhs = []
00034 self.rhs = []
00035 self[Tags.Left] = []
00036 self[Tags.Right] = []
00037
00038 self.CoeffDic={}
00039 self.CurMet = ""
00040 self.BadCoeffs =BadCoeffs
00041
00042 def __AddLeft__(self, met):
00043 self.CoeffDic[met] = -1
00044 self.lhs.append(met)
00045
00046 def __AddRight__(self, met):
00047 self.CoeffDic[met] = 1
00048 self.rhs.append(met)
00049
00050 def __AddCoeff__(self, k):
00051 self.CoeffDic[self.CurMet] *= int(k)
00052
00053 def NewTag(self, tag, val):
00054
00055 if tag == Tags.Left:
00056 self.CurMet=val
00057 self.__AddLeft__(val)
00058 elif tag == Tags.Right:
00059 self.CurMet=val
00060 self.__AddRight__(val)
00061 elif tag == Tags.Coeff:
00062 try:
00063 self.__AddCoeff__(val)
00064 except:
00065 self.BadCoeffs.append(self)
00066 Base.Record.NewTag(self,tag,val)
00067
00068
00069
00070 def strhs(self, side):
00071 if side ==[]:
00072 return "NOTHING"
00073 met = side[0]
00074 coeff = abs(self.CoeffDic[met])
00075 if coeff == 1:
00076 rv = '"'+met+'"'
00077 else:
00078 rv = str(coeff) + ' "' + met+'"'
00079
00080 for met in side[1:]:
00081 coeff = abs(self.CoeffDic[met])
00082 if coeff ==1:
00083 rv +=' + "' + met +'"'
00084 else:
00085 rv += " + " + str(coeff) + ' "' + met +'"'
00086 return rv
00087
00088 def AsScrumPy(self,Prep=""):
00089
00090 Name = "".join(['"',Prep,self.UID,'":'])
00091 RevCom = ""
00092 Indent = " "*4
00093
00094 if self.lhs==[] or self.rhs==[]:
00095 print "Warning :", self.UID, " has missing reactants(s)"
00096
00097 lhs = self.strhs(self.lhs)
00098 rhs = self.strhs(self.rhs)
00099 Direc = DefaultDirec
00100
00101 if self.has_key(Tags.ReacDir):
00102 Rev = self[Tags.ReacDir][0]
00103 RevCom= "".join([Indent,"#",Rev])
00104 if DirecMap.has_key(Rev):
00105 Direc = DirecMap[Rev]
00106 else:
00107 print " ".join(["!! Warning:", Name, "has unknown", Tags.ReacDir, "using", Direc, "!!"] )
00108
00109
00110 Stoich = "".join([Indent, lhs, Direc, rhs])
00111 Kins = Indent + "~"
00112
00113 return "\n".join([Name, Stoich, Kins, RevCom, "\n"])
00114
00115
00116 def __str__(self):
00117 keys = self.keys()
00118 keys.remove(Tags.UID)
00119 rv = Base.Field2Str(Tags.UID, self[Tags.UID])
00120 for k in keys:
00121 if k not in [Tags.Coeff, Tags.Right,Tags.Left]:
00122 rec = self[k]
00123 for r in rec:
00124 rv += Base.Field2Str(k, r)
00125
00126 for left in self[Tags.Left]:
00127 rv += Base.Field2Str(Tags.Left, left)
00128 if self.CoeffDic.has_key(left):
00129 rv += Base.Field2Str(Tags.Coeff, self.CoeffDic[left])
00130
00131 for right in self[Tags.Right]:
00132 rv += Base.Field2Str(Tags.Right, right)
00133 if self.CoeffDic.has_key(right):
00134 rv += Base.Field2Str(Tags.Coeff, self.CoeffDic[right])
00135
00136 try:
00137 cat = Base.TabStrFormat("Catalyses", self.strhs(self.lhs) + " -> " + self.strhs(self.rhs))
00138 except:
00139 cat = ""
00140 return rv + cat
00141
00142 def AtomSto(self, side):
00143 """pre: side == Tags.Left' || side == Tags.Right
00144 post: AtomSto => dictionary of atomic stoichiometry of l or r hs """
00145
00146 rv = {}
00147 if not self.has_key(side):
00148 return rv
00149 for comp in self[side]:
00150 if comp[0] == "|":
00151 c2=comp[1:-1]
00152 self.CoeffDic[c2]=self.CoeffDic[comp]
00153 comp=c2
00154 if self.Org.Compound.has_key(comp):
00155 atoms = self.Org.Compound[comp].EmpForm
00156 coeff = abs(self.CoeffDic[comp])
00157 for k in atoms.keys():
00158 if rv.has_key(k):
00159 rv[k] += coeff *atoms[k]
00160 else:
00161 rv[k] = coeff*atoms[k]
00162 else:
00163
00164 rv ["Missing "+ comp] = 1
00165 return rv
00166
00167
00168 def NetBal(self):
00169 BalDic = self.AtomSto(Tags.Left)
00170 right = self.AtomSto(Tags.Right)
00171 for k in right.keys():
00172 if BalDic.has_key(k):
00173 BalDic[k] -= right[k]
00174 else:
00175 BalDic[k] = -right[k]
00176 return BalDic
00177
00178 def ImBal(self):
00179 bal = self.NetBal()
00180 for met in bal.keys():
00181 if bal[met]==0:
00182 del bal[met]
00183 return bal
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 class DB(Base.DB):
00194 def __init__(self,
00195 path=Base.DefaultPath,
00196 file=DefaultFile,
00197 RecClass=Record,
00198 **kwargs):
00199
00200
00201 BadCoeffs = []
00202
00203 Base.DB.__init__(
00204 self,
00205 path,
00206 file,
00207 RecClass=Record,
00208 BadCoeffs = BadCoeffs,
00209 **kwargs
00210 )
00211
00212 self.ECNos = {}
00213 self.BadCoeffs = BadCoeffs
00214 for reac in self.values():
00215 if reac.has_key(Tags.EC):
00216 ec = reac[Tags.EC][0]
00217 if self.ECNos.has_key(ec):
00218 self.ECNos[ec].append(reac)
00219 else:
00220 self.ECNos[ec] = [reac]
00221
00222 self.ExtraReacs = {}
00223 if '# MetaCyc\n' in self.Comments:
00224 self.ExtraReacs = DB(path=path, file="ExtraReacs.dat")
00225
00226
00227 def __getitem__(self,k):
00228
00229 try:
00230 return Base.DB.__getitem__(self,k)
00231 except:
00232 try:
00233 return self.ECNos[k]
00234 except:
00235 try:
00236 return self.ECNos[ECEquivs[k]]
00237 except:
00238 try:
00239 return self.ExtraReacs[k]
00240 except: return []
00241
00242
00243 def has_key(self, k):
00244
00245 return len(self[k]) != 0
00246
00247
00248 def GoodBadBals(self):
00249 """ pre: True
00250 post: returns (good,bad) dictionaries of reactions wich do/not balance"""
00251
00252
00253 rv = ({},{})
00254 for k in self.keys():
00255 dic = 0
00256 bal = self[k].NetBal()
00257 for v in bal.values():
00258 if v != 0:
00259 dic = 1
00260 break
00261 rv[dic][k] = bal
00262 return rv
00263