• Main Page
  • Namespaces
  • Classes
  • Files
  • File List

/home/mark/model/software/ScrumPy/ScrumPy/Structural/StoMat.py

00001 
00002 
00003 """
00004 
00005 ScrumPy -- Metabolic Modelling with Python
00006 
00007 Copyright Mark Poolman 1995 - 2002
00008 
00009  This file is part of ScrumPy.
00010 
00011     ScrumPy is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     ScrumPy is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU General Public License for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with ScrumPy; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025 """
00026 
00027 import sys, types
00028 
00029 from Util import DynMatrix, Seq,Set,Sci,Format, Types
00030 # NB "types" is the standard module, "Types" contains some local type defs
00031 
00032 from Parser.lexer import t_Rever, t_Irrev, t_BackIrrev
00033 from Parser.Parser import Sto
00034 # TODO: Parser.Sto and ModelDesc need a module of their own
00035 
00036 # Exceptions
00037 NoSuchMet = "No such metabolite"
00038 NoSuchreac = "No such reaction"
00039 DupReac = "Duplicate reaction"
00040 
00041 class StoMat(DynMatrix.matrix):
00042 
00043     def __init__(self, r=0, c=0, **kwargs):
00044 
00045         DynMatrix.matrix.__init__(self,r,c, **kwargs)
00046         self.RevProps = {}
00047         self.Externs = []
00048         #self.Irrevs = self.GetIrrevs()
00049 
00050 
00051         # TODO: StoMat needs a proper copy constructer
00052 
00053 
00054     def DelRow(self, r):
00055 
00056         if type(r) == types.IntType:
00057             r = self.rnames[r]
00058 
00059         if r in self.Externs:
00060             self.Externs.remove(r)
00061 
00062         DynMatrix.matrix.DelRow(self,r)
00063 
00064 
00065     def DelReac(self, c):
00066 
00067         if type(c) == types.IntType:
00068             c = self.cnames[c]
00069 
00070         del self.RevProps[c]
00071         DynMatrix.matrix.DelCol(self,c)
00072 
00073 
00074     def DeQuote(self):
00075 
00076         DynMatrix.matrix.DeQuote(self)
00077 
00078         revpropdq = {}   # reversibility property dictionary dequited
00079         for k in self.RevProps:
00080             revpropdq[self.QuoteD[k]] = self.RevProps[k]
00081         self.RevProps = revpropdq
00082 
00083         xnamesd = map(Format.StripQuote,self.Externs) # have to externs by hand
00084         for n in range(len(xnamesd)):                 # as internal sms won't otherwise
00085             self.QuoteD[xnamesd[n]] = self.Externs[n] # have Externs in QuoteD
00086             self.QuoteD[self.Externs[n]] = xnamesd[n]
00087         self.Externs = xnamesd
00088 
00089 
00090     def ReQuote(self):
00091 
00092         revpropdq = {}
00093         for k in self.RevProps:
00094             revpropdq[self.QuoteD[k]] = self.RevProps[k]
00095         self.RevProps = revpropdq
00096         self.Externs = map(lambda x:self.QuoteD[x], self.Externs)
00097         DynMatrix.matrix.ReQuote(self)
00098 
00099 
00100 
00101     def MakeExtern(self, name):
00102 
00103         self.DelRow(name)
00104         self.Externs.append(name)
00105 
00106     def GetIrrevs(self):
00107        return filter(lambda reac: self.RevProps[reac] != t_Rever,  self.cnames)
00108 
00109     def MakeIrrev(self,name):
00110 
00111         self.RevProps[name] = t_Irrev
00112 
00113 
00114     def MakeRevers(self,name):
00115 
00116         self.RevProps[name] = t_Rever
00117 
00118 
00119     def InvolvedWith(self, name, crit=None):
00120         if crit==None:
00121             def crit(x):
00122                 return x!=0
00123 
00124 
00125         if name in  self.cnames:
00126             list = self.GetCol(name)
00127             namelist = self.rnames
00128         elif name in self.rnames:
00129             list = self.GetRow(name)
00130             namelist = self.cnames
00131         else:
00132             print "name ", name, "not found"
00133             list = []
00134 
00135         rv = {}
00136         for idx in range(len(list)):
00137 
00138             if crit( list[idx]):
00139                 rv[namelist[idx]] = self.Conv(list[idx])
00140 
00141         return (rv)
00142 
00143 
00144     def Products(self, Reaction):
00145         return self.InvolvedWith(Reaction, lambda x: x>0).keys()
00146 
00147     def Substrates(self, Reaction):
00148         return self.InvolvedWith(Reaction, lambda x: x<0).keys()
00149 
00150     def Reactants(self, Reaction):
00151         """ List of reactant names involved with Reaction """
00152         return self.InvolvedWith(Reaction).keys()
00153 
00154     def Transporters(self):
00155         rv = {}
00156         for met in self.Externs:
00157             rv.update(self.InvolvedWith(met))
00158         return rv.keys()
00159 
00160 
00161     def OrphanMets(self):
00162 
00163         rv = []
00164 
00165         for met in self.rnames:
00166             if len(self.InvolvedWith(met))==1:
00167                 rv.append(met)
00168 
00169         return rv
00170 
00171 
00172     def Delete(self, name):
00173         if name in self.cnames:
00174             self.DelReac(name)
00175             for name in self.rnames:                 # ugly, find nicer way
00176                 if Seq.AllEq(self.GetRow(name), 0):
00177                     self.DelRow(name)
00178         elif name in self.rnames:
00179             self.DelRow(name)
00180             for name in self.cnames:
00181                 if Seq.AllEq(self.GetCol(name), 0):
00182                     self.DelReac(name)
00183         else:
00184             print "can't find ", name
00185 
00186 
00187     def NewReaction(self, reac, StoDic,RevProp=t_Rever):
00188 
00189         if reac in self.cnames:
00190             raise DupReac
00191 
00192         self.NewCol(name=reac)
00193         for met in StoDic.keys():
00194             if not met in self.rnames:
00195                 self.NewRow(name=met)
00196             self[met,reac]=StoDic[met]
00197 
00198         self.RevProps[reac] = RevProp
00199 
00200 
00201     def SetSto(self, reac,  Sto,  reset = False):
00202         """ pre: reac in self.cnames, Sto = Parser.Sto(...)"""
00203 
00204         if reset:
00205             self.MulCol(reac, k=0)
00206 
00207         for met in Sto.lhs:
00208             coeff = met[0]
00209             name = met[1]
00210             self[name,reac] = coeff
00211             self[name,reac] *= -1 # cos coeff is a string until it gets into self
00212 
00213         for met in Sto.rhs:
00214             coeff = met[0]
00215             name = met[1]
00216             self[name,reac] = coeff
00217 
00218         self.RevProps[reac] = Sto.Revers
00219 
00220 
00221 
00222     def FirstReaction(self, Name, lhs, rhs, Revers):
00223 
00224         print "Deprecated FirstReaction() ?"
00225         self.cnames.append(Name)
00226         for tup in lhs:
00227             if tup[0] in self.rnames:
00228                  raise "Duplicate Metabolite"
00229             self.rnames.append(tup[0])
00230             self.rows.append([self.Conv(-tup[1])])
00231 
00232         for tup in rhs:
00233             if tup[0] in self.rnames:
00234                  raise "DuplicateMetabolite"
00235             self.rnames.append(tup[0])
00236             self.rows.append([self.Conv(tup[1])])
00237 
00238         if not Revers:
00239                 self.MakeIrrev(Name)
00240 
00241 
00242     def AddReaction(self, Name, lhs, rhs, Revers=1):
00243 
00244         sys.stderr.write("Deprecated: AddReaction - Use NewReaction\n")
00245         raise "Deprecated method", "AddReaction"
00246 
00247 
00248     def Copy(self, *args,**kwargs):
00249 
00250         rv =  DynMatrix.matrix.Copy(self,*args, **kwargs)
00251         rv.RevProps = dict(self.RevProps)
00252 
00253         rv.Externs = self.Externs[:]
00254 
00255         return rv
00256 
00257 
00258     def ReacToStr(self,reac):
00259 
00260         def d2l(d):
00261             rv = []
00262             for k in d.keys():
00263                 rv.append(" ".join((str(d[k]),k)))
00264             return rv
00265 
00266         substs = self.InvolvedWith(reac, lambda x: x<0)
00267         for k in substs.keys():
00268             substs[k] *= -1
00269         substs = d2l(substs)
00270 
00271 
00272         prods = d2l(self.InvolvedWith(reac, lambda x: x>0))
00273 
00274         sep = self.RevProps[reac].join((" "," "))
00275 
00276 
00277         rv = reac+":\n\t" + " + ".join(substs) + sep + " + ".join(prods) + "\n\t~\n"
00278 
00279         if len(substs) ==0 or len(prods)==0:
00280             print reac, "missing substrate or product !"
00281             rv = "#"+ "\n#".join(rv.split("\n"))+"\n"
00282 
00283         return rv
00284 
00285     def IntegiseReacs(self):
00286         for reac in self.cnames:
00287             col = self.GetCol(reac)
00288             if Seq.AllEq(col, 0):
00289                 self.DelCol(reac)
00290             else:
00291                 #Seq.Normalise(col,KeepSign=False)
00292                 self.SetCol(reac, Seq.Integise(col))
00293 
00294 
00295     def NiceOrder(self):
00296 
00297         txs = self.Transporters()
00298         interns = Set.Complement(self.cnames,txs)
00299         txs.sort()
00300         interns.sort()
00301         self.ColReorder(txs+interns)
00302 
00303 
00304     def ElTypeAsScrumPy(self):
00305        
00306         return Types.TypeToDirective[type(self.Conv(1))]
00307 
00308 
00309 
00310 
00311     def ToScrumPy(self, file=None, FirstLine="Structural()\n",Externs=None, NiceOrder=False):
00312 
00313         if self.IsDeQuoted():
00314             FirstLine += "DeQuote()\n"
00315             self.ReQuote()
00316             rv = self.ToScrumPy(file, FirstLine,Externs, NiceOrder)
00317             self.DeQuote()
00318             return rv
00319 
00320         if Externs==None:
00321             Externs=self.Externs[:]
00322 
00323         for ex in Externs[:]:
00324             if ex.upper()[:2] == "X_":
00325                 Externs.remove(ex)
00326 
00327         self2 = self.Copy()
00328 
00329         self2.ZapZeroes()
00330 
00331         if self.Conv != Types.ArbRat:
00332             FirstLine += "ElType("+self.ElTypeAsScrumPy() + ")\n"
00333         if NiceOrder:
00334             self2.NiceOrder()
00335 
00336         Header = FirstLine
00337         Body = "\n"
00338         if len(Externs) >0:
00339             Header += "External("+ ", ".join(Externs)+")\n\n"
00340         for reac in self.cnames:
00341             if len(self2.InvolvedWith(reac))==0:
00342                 Header += "# Empty Reaction : "+ reac + "\n"
00343             else:
00344                 Body += self2.ReacToStr(reac)
00345 
00346         rv = Header + Body
00347         if file != None:
00348             if not hasattr(file,"write"):
00349                 file = open(file,"w")
00350             file.write(rv)
00351         else:
00352             return rv
00353 
00354 
00355 
00356 
00357     def IsIrrev(self,name):
00358         return  self.RevProps[name] != t_Rever
00359 
00360     def Connectedness(self, met):
00361         return Seq.NumOfMatches(self[met], lambda x: x != 0)
00362 
00363     def Unbals(self):
00364         " return list of mets that do not have >0 producer and >0 consumer "
00365 
00366         rv = []
00367 
00368         for m in self.rnames:
00369             row = self[m]
00370             if not (Seq.HasMatches(row, lambda x: x>0) and Seq.HasMatches(row, lambda x: x<0)):
00371                 rv.append(m)
00372         return rv
00373 
00374 
00375     def SubSys(self, reacs):
00376 
00377         if self.IsDeQuoted():
00378             self.ReQuote()
00379             reacsq  = []
00380             for reac in reacs:
00381                 reacq = '"'+reac+'"'
00382                 if reacq in self.cnames:
00383                     reacsq.append(reacq)
00384                 else:
00385                     reacsq.append(reac)
00386 
00387             rv = self.SubSys(reacsq)
00388             rv.DeQuote()
00389             self.DeQuote()
00390 
00391         else:
00392 
00393             rv = StoMat(rnames=self.rnames, cnames=reacs,Conv=self.Conv)
00394 
00395             for reac in reacs:
00396                 stod = self.InvolvedWith(reac)
00397                 for met in stod:
00398                     rv[met,reac] = stod[met]
00399 
00400             rv.ZapZeroes()
00401             rv.Externs = Set.Intersect(rv.rnames,self.Externs)
00402             for reac in rv.cnames:
00403                 rv.RevProps[reac] = self.RevProps[reac]
00404 
00405             # TODO - rnamesq etc. no longer needed ? check and remove
00406 
00407             if self.IsDeQuoted():
00408                 for atr in "rnamesq",  "cnamesq", "Externsq", "Irrevsq":
00409                     setattr(rv, atr, map(self.FindQuoted, getattr(self, atr[:-1])))
00410 
00411 
00412         return rv
00413 
00414 
00415 
00416 
00417     def FindIsoforms(self):
00418         stodic = {}
00419         for reac in self.cnames:
00420             strsto = str(self.InvolvedWith(reac))
00421             if stodic.has_key(strsto):
00422                 stodic[strsto].append(reac)
00423             else:
00424                 stodic[strsto] = [reac]
00425         rv = []
00426         for reac in stodic.values():
00427             if len(reac)>1:
00428                 rv.append(reac)
00429 
00430         return rv
00431 
00432 
00433 
00434 
00435     def OrthSubSysts(self,tol=1e-6):
00436         """ a list of lists of reaction names of the orthogonal subsystems in self,
00437         The first, possibly empty, list contains the dead reactions """
00438 
00439         k = self.OrthNullSpace()
00440         dead = []
00441         for reac in k.rnames[:]:
00442             if max(map(abs, k[reac])) <tol:
00443                 dead.append(reac)
00444                 k.DelRow(reac)
00445 
00446         rv = [dead]
00447                 
00448         while len(k.rnames) >0:
00449            ref = k.rnames[0]
00450            curss = [ref]
00451 
00452            for reac in k.rnames[1:]:
00453                if not Sci.AreOrthogonal(k[ref],k[reac],tol):
00454                    curss.append(reac)
00455                    k.DelRow(reac)
00456 
00457            k.DelRow(ref)
00458            rv.append(curss)
00459         return rv
00460 
00461 
00462     def ReactionNJTree(self):
00463         k = self.OrthNullSpace()
00464         t = k.RowDiffMtx(Sci.Theta).ToNJTree()
00465         t.Consolidate(thresh= 1e-8)
00466         return t
00467 
00468     def AdjMtx(self):
00469         """ The integer adjacency matrix of self """
00470 
00471         rv = DynMatrix.matrix(Conv = int, rnames = self.rnames, cnames = self.cnames)
00472         for met in self.rnames:
00473             reacs = self.InvolvedWith(met).keys()
00474             for r in reacs:
00475                 for neighbour in self.InvolvedWith(r).keys():
00476                     rv[r,neighbour] = 1
00477         return rv
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 
00493 

Generated on Tue Sep 4 2012 15:38:02 for ScrumPy by  doxygen 1.7.1