00001 import sys
00002 from ScrumPy.Util.Tree import Tree
00003 from ScrumPy.Util import Set,Sci,Seq
00004 import StoMat
00005
00006
00007 def ListToName(l):
00008 l.sort()
00009 return "_".join(l)
00010
00011 class Smholder:
00012 def __init__(self, sm, xsm):
00013 self.sm = sm
00014 self.smexterns = xsm
00015
00016
00017 class PartialMode:
00018 def __init__(self, sm,Balances = [],Uses = [],Irrev=False):
00019
00020 names = sm.cnames[:]
00021 names.sort()
00022 self.Name = "_".join(names)
00023 self.sm = sm
00024 self.Balances = Balances
00025 self.Irrev = Irrev
00026 self.Uses = Uses
00027
00028
00029 def DefinedSto(self):
00030 return len(self.sm.cnames)==1
00031
00032 def __str__(self):
00033 return ", ".join(
00034 (
00035 self.Name,
00036 str(self.Substrates()),
00037 str(self.Products())
00038 )
00039 )
00040
00041 def __repr__(self):
00042 return self.Name
00043
00044 def Substrates(self):
00045 rv = []
00046 for reac in self.sm.cnames:
00047 rv = Set.Union(rv,self.sm.InvolvedWith(reac,lambda x: x<0).keys())
00048 return rv
00049
00050
00051 def Products(self):
00052 rv = []
00053 for reac in self.sm.cnames:
00054 rv = Set.Union(rv,self.sm.InvolvedWith(reac,lambda x: x>0).keys())
00055 return rv
00056
00057
00058 def Reactants(self):
00059 return self.sm.rnames[:]
00060
00061
00062 def CombinedSM(self, Other, UseMets=[]):
00063
00064 cols = self.sm.cnames + Other.sm.cnames
00065
00066 rv = StoMat.StoMat(Conv=self.sm.Conv,rnames=UseMets,cnames=cols)
00067 for srcsm in self.sm,Other.sm:
00068 rows = Set.Intersect(srcsm.rnames, UseMets)
00069 for row in rows:
00070 for col in srcsm.cnames:
00071 rv[row,col]=srcsm[row,col]
00072 return rv
00073
00074 def SubSysModes(self, Other):
00075
00076 sys.stderr.write( "Subsys modes\n")
00077
00078 sReactants= self.Reactants()
00079 oReactants =Other.Reactants()
00080 Interns = Set.Intersect(sReactants, oReactants)
00081 if len(Interns)==0:
00082 return []
00083 AllMets = Set.Union(sReactants, oReactants)
00084 Intsm = self.CombinedSM(Other, Interns)
00085 Extsm = self.CombinedSM(Other, AllMets)
00086
00087 Subtree = ReacTree(Smholder(Intsm,Extsm))
00088 Subtree.ElModes()
00089
00090 print "Subsys modes end"
00091 return Subtree.ems.values() + Subtree.ParModes.values()
00092
00093
00094
00095 def CombinedWith(self, Other):
00096 if Set.DoesIntersect(self.Balances, Other.Reactants()) or Set.DoesIntersect(self.Reactants(), Other.Balances):
00097 return []
00098
00099
00100
00101 sReactants = self.Reactants()
00102 oReactants = Other.Reactants()
00103 Interns = Set.Intersect(sReactants, oReactants)
00104 Externs = Set.Difference(sReactants,oReactants)
00105 Balances = Set.Union(self.Balances, Other.Balances)
00106 LeafReacs = Set.Union(self.Uses,Other.Uses)
00107
00108 print "Combining", self.Name, Other.Name, "sharing", Interns
00109 UnDefSto = True
00110
00111 if Interns != []:
00112
00113
00114
00115 Intsm = self.CombinedSM(Other, Interns)
00116 print "intsm\n", Intsm,"\n"
00117 k = Intsm.NullSpace()
00118 print "k\n", k,"\n"
00119 if k != None:
00120 kdim = len(k.cnames)
00121 UnDefSto = False
00122 Extsm = self.CombinedSM(Other, Externs)
00123 if Externs !=[]:
00124 stoich = Sci.mul(Extsm,k).tolist()
00125 Extsm.cnames = k.cnames
00126 Extsm.rows = stoich
00127 print "extsm orig\n", Extsm
00128 name = ListToName(self.sm.cnames + Other.sm.cnames)
00129 if kdim == 1:
00130 Extsm.cnames = [name]
00131 else:
00132 Extsm.cnames = []
00133 for cn in k.NamesNonZeroesInCols():
00134 Extsm.cnames.append(ListToName(cn))
00135 Balances = Set.Union(Balances, Intsm.rnames)
00136
00137 if UnDefSto:
00138 Extsm = self.CombinedSM(Other,Externs+Interns)
00139 Extsm.ZapZeroes()
00140 if UnDefSto: sys.stderr.write("!! ")
00141 print "final sto", Extsm
00142 return [PartialMode(Extsm,Balances,LeafReacs)]
00143
00144
00145
00146
00147
00148 class ReacTree(Tree):
00149 def __init__(self, Model=None,*args,**kwargs):
00150 Tree.__init__(self,*args,**kwargs)
00151 self.Model = Model
00152 if Model != None:
00153 self.FromNJStr(self.Model.sm.ReactionNJTree(),Constructor=ReacTree)
00154 self.SetModelData()
00155
00156
00157 def __str__(self):
00158 if self.IsLeaf():
00159 return str(self.UserData)
00160 return Tree.__str__(self)
00161
00162
00163 def SetModelData(self,bid=0):
00164 if self.Parent !=None:
00165 self.Model = self.Parent.Model
00166 self.bid = bid
00167 else:
00168 self.bid=1
00169
00170 self.strbid = str(bid)
00171
00172 chbid=0
00173 for ch in self.Children:
00174 ch.SetModelData(self.bid*2+chbid)
00175 chbid+=1
00176
00177
00178
00179 def HasLeaf(self, name):
00180 return Tree.HasLeaf(self,name,lambda leaf,name: leaf.UserData==name)
00181
00182
00183
00184 def Reactions(self):
00185 """ pre: True
00186 post: list of reactions in this tree """
00187
00188 try:
00189 return self.__reactions
00190 except:
00191 if self.IsLeaf():
00192 self.__reactions = [self.UserData]
00193 else:
00194 self.__reactions = []
00195 for l in self.AllLeaves():
00196 self.__reactions.extend(l.Reactions())
00197 return self.__reactions
00198
00199
00200 def Metabolites(self):
00201
00202 try:
00203 return self.__metabolites
00204 except:
00205 self.__metabolites = []
00206 for reac in self.Reactions():
00207 mets = self.Model.smexterns.InvolvedWith(reac).keys()
00208 self.__metabolites= Set.Union(self.__metabolites,mets)
00209 return self.__metabolites
00210
00211
00212
00213 def ExtMetabolites(self,Globals=True):
00214 """pre: True
00215 post: list of internal metabolites used by self external to the model or used by non-descendent nodes """
00216
00217 mets = self.Metabolites()
00218 if self.IsLeaf():
00219 return mets
00220 root = self.Root()
00221 rv = []
00222 for met in mets:
00223 subtree =root.Uses([met])
00224 if not (subtree == self or subtree.IsSub(self)):
00225 rv.append(met)
00226 elif Globals and met in self.Model.sm.Externs:
00227 rv.append(met)
00228 return rv
00229
00230
00231
00232 def Contains(self,Reactions=[]):
00233 """ pre: self.HasLeaves(Reactions), len(Reactions)>1
00234 post: minimal subtree containing Reactions"""
00235
00236
00237 if self[0].HasLeaf(Reactions[0]):
00238 ch = self[0]
00239 elif self[1].HasLeaf(Reactions[0]):
00240 ch = self[1]
00241 else:
00242 return self
00243
00244 for r in Reactions[1:]:
00245 if not ch.HasLeaf(r):
00246 return self
00247 return ch.Contains(Reactions)
00248
00249
00250 def Uses(self,Metabolites=[]):
00251 """pre: Metabolite is used by at least one reaction under self
00252 post: minimal subtree of reactions using Metabolite """
00253
00254 reacs = []
00255 for met in Metabolites:
00256 reacs.extend(self.Model.smexterns.InvolvedWith(met).keys())
00257 return self.Root().Contains(reacs)
00258
00259
00260
00261
00262 def GetDoneParents(self):
00263 """ pre: True
00264 post: list of nodes for whom all children have a stoichiometry matrix """
00265
00266
00267 if self.DoneModes:
00268 return []
00269 if self[0].DoneModes and self[1].DoneModes:
00270 return [self]
00271
00272
00273 return self[0].GetDoneParents() + self[1].GetDoneParents()
00274
00275
00276
00277
00278 def PromoteCombinations(self):
00279
00280 pms0 = self[0].ParModes
00281 pms1 = self[1].ParModes
00282 pms = self.ParModes
00283 ems = self.Root().ems
00284 Externs = self.Model.sm.Externs
00285
00286 for reac0 in pms0.keys():
00287 pm0 = pms0[reac0]
00288 for reac1 in pms1.keys():
00289 modes = []
00290 pm1 = pms1[reac1]
00291 if not pm0.DefinedSto() or not pm1.DefinedSto():
00292 if len(Set.Union(pm0.Uses,pm1.Uses)) < len(self.Model.sm.cnames):
00293 modes = pm0.SubSysModes(pm1)
00294 else:
00295 modes = pm1.CombinedWith(pm0)
00296
00297 for pmnew in modes:
00298 if Set.IsSubset(pmnew.Reactants(), Externs):
00299 dest = ems
00300 sys.stderr.write("Elementary " + pmnew.Name +"\n")
00301 else:
00302 dest = pms
00303 dest[pmnew.Name] = pmnew
00304
00305
00306
00307 def PromoteChildren(self):
00308
00309 ParModes = self.ParModes
00310 ExtMets = self.ExtMetabolites()
00311 print ExtMets
00312
00313 for ch in self[0],self[1]:
00314 chpms = ch.ParModes
00315 for reac in chpms.keys():
00316 chpm = chpms[reac]
00317 mets = chpm.Reactants()
00318
00319 if Set.DoesIntersect(mets, ExtMets):
00320 ParModes[reac] = ch.ParModes[reac]
00321
00322
00323
00324 def CalcModes(self):
00325
00326 print
00327 if self.IsRoot(): print "Root"
00328
00329 self.ParModes = {}
00330 self.ElType = self.Model.sm.Conv
00331
00332 self.PromoteChildren()
00333 self.PromoteCombinations()
00334
00335 self.DoneModes=True
00336
00337
00338
00339
00340 def ElModes(self):
00341 """ pre: self.IsRoot()
00342 post: return pair of matrices sto, mo - stoichiometry matrix and reaction matrix of elmodes """
00343
00344 self.ems = {}
00345 sm = self.Model.smexterns
00346
00347 def SetFlags(self):
00348 if self.IsLeaf():
00349 self.DoneModes=True
00350 else:
00351 self.DoneModes=False
00352 SetFlags(self[0])
00353 SetFlags(self[1])
00354
00355 SetFlags(self)
00356
00357 for l in self.AllLeaves():
00358 reac = str(l)
00359 l.ParModes={reac:
00360 PartialMode(
00361 sm.SubSys([reac]),
00362 Irrev = sm.IsIrrev(reac),
00363 Uses= [reac]
00364 )
00365 }
00366
00367 while not self.DoneModes:
00368 for lp in self.GetDoneParents():
00369 lp.CalcModes()
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386