Chem.FeatMaps.FeatMapParser

Package Chem :: Package FeatMaps :: Module FeatMapParser |
[hide private]
[frames] | no frames]

# Source Code for Module Chem.FeatMaps.FeatMapParser

      1  # $Id: FeatMapParser.py 746 2008-07-07 13:21:24Z glandrum $
      2  #
      3  # Copyright (C) 2006 Greg Landrum
      4  #
      5  #   @@ All Rights Reserved  @@
      6  #
      7  import Geometry
      8  from Chem import ChemicalFeatures
      9  from Chem.FeatMaps import FeatMaps,FeatMapPoint
     10  import re
     11
     12  """
     13
     14  ScoreMode=All
     15  DirScoreMode=Ignore
     16
     17  BeginParams
     18    family=Aromatic radius=2.5 width=1.0 profile=Gaussian
     19    family=Acceptor radius=1.5
     20  EndParams
     21
     22  # optional
     23  BeginPoints
     24    family=Acceptor pos=(1.0, 0.0, 5.0) weight=1.25 dir=(1, 1, 0)
     25    family=Aromatic pos=(0.0,1.0,0.0) weight=2.0 dir=(0,0,1) dir=(0,0,-1)
     26    family=Acceptor pos=(1.0,1.0,2.0) weight=1.25
     27  EndPoints
     28
     29  """
     30
     31 -class FeatMapParseError(ValueError):
     32    pass
     33
     34 -class FeatMapParser(object):
     35    data=None
     36 -  def __init__(self,file=None,data=None):
     37      if file:
     38        self.data=file.readlines()
     39      elif data:
     40        self.SetData(data)
     41      self._lineNum=0
     42
     43 -  def SetData(self,data):
     44      if isinstance(data,str):
     45        self.data=data.split('\n')
     46      else:
     47        self.data=data
     48      self._lineNum=0
     49
     50 -  def _NextLine(self):
     51      txt = ''
     52      while 1:
     53        try:
     54          l = self.data[self._lineNum].split('#')[0].strip()
     55        except IndexError:
     56          break
     57        self._lineNum+=1
     58        if l:
     59          txt += l
     60          if l[-1]!='\\':
     61            break
     62      return txt
     63
     64 -  def Parse(self,featMap=None):
     65      if featMap is None:
     66        featMap = FeatMaps.FeatMap()
     67
     68      l = self._NextLine().strip()
     69      while l:
     70        splitL = l.split('=')
     71        if len(splitL)==1:
     72          keyword=splitL[0].strip().lower()
     73          if keyword=='beginpoints':
     74            pts=self.ParseFeatPointBlock()
     75            for pt in pts:
     76              featMap.AddFeatPoint(pt)
     77          elif keyword=='beginparams':
     78            featMap.params=self.ParseParamBlock()
     79          else:
     80            raise FeatMapParseError,'Unrecognized keyword %s on line %d'%(keyword,self._lineNum)
     81        else:
     82          keyword = splitL[0].strip().lower()
     83          val = splitL[1].strip()
     84          if keyword=='scoremode':
     85            try:
     86              featMap.scoreMode=getattr(FeatMaps.FeatMapScoreMode,val)
     87            except AttributeError:
     88              raise FeatMapParseError,'ScoreMode %s not recognized on line %d'%(val,self._lineNum)
     89          elif keyword=='dirscoremode':
     90            try:
     91              featMap.dirScoreMode=getattr(FeatMaps.FeatDirScoreMode,val)
     92            except AttributeError:
     93              raise FeatMapParseError,'DirScoreMode %s not recognized on line %d'%(val,self._lineNum)
     94          else:
     95            raise FeatMapParseError,'Unrecognized keyword %s on line %d'%(keyword,self._lineNum)
     96        l = self._NextLine().strip()
     97      return featMap
     98
     99 -  def ParseParamBlock(self):
    100      paramLineSplitter = re.compile(r'([a-zA-Z]+) *= *(\S+)')
    101      params = {}
    102
    103      l = self._NextLine()
    104      while l and l!='EndParams':
    105        param = FeatMaps.FeatMapParams()
    106        vals=paramLineSplitter.findall(l)
    107        for name,val in vals:
    108          name = name.lower()
    109          if name=='family':
    110            family=val
    111          elif name=='radius':
    112            param.radius=float(val)
    113          elif name=='width':
    114            param.width=float(val)
    115          elif name=='profile':
    116            try:
    117              param.featProfile=getattr(param.FeatProfile,val)
    118            except AttributeError:
    119              raise FeatMapParseError,'Profile %s not recognized on line %d'%(val,self._lineNum)
    120          else:
    121            raise FeatMapParseError,'FeatMapParam option %s not recognized on line %d'%(name,self._lineNum)
    122        params[family]=param
    123        l = self._NextLine()
    124
    125      if l!='EndParams':
    126        raise FeatMapParseError('EndParams line not found')
    127
    128      return params
    129
    130 -  def _parsePoint(self,txt):
    131      txt = txt.strip()
    132      startP=0
    133      endP=len(txt)
    134      if txt[0]=='(':
    135        startP += 1
    136      if txt[-1]==')':
    137        endP -= 1
    138      txt = txt[startP:endP]
    139      splitL = txt.split(',')
    140      if len(splitL) != 3:
    141        raise ValueError,'Bad location string'
    142      vs = [float(x) for x in splitL]
    143      pt = Geometry.Point3D(vs[0],vs[1],vs[2])
    144      return pt
    145
    146
    147 -  def ParseFeatPointBlock(self):
    148      featLineSplitter = re.compile(r'([a-zA-Z]+) *= *')
    149      feats = []
    150
    151      l = self._NextLine()
    152      while l and l!='EndPoints':
    153        vals=featLineSplitter.split(l)
    154        while vals.count(''): vals.remove('')
    155        p = FeatMapPoint.FeatMapPoint()
    156
    157        i=0
    158        while i<len(vals):
    159          name = vals[i].lower()
    160          if name=='family':
    161            i+=1
    162            val = vals[i].strip()
    163            p.SetFamily(val)
    164          elif name=='weight':
    165            i+=1
    166            val = float(vals[i])
    167            p.weight = val
    168          elif name=='pos':
    169            i+=1
    170            val = vals[i]
    171            pos = self._parsePoint(val)
    172            p.SetPos(pos)
    173          elif name=='dir':
    174            i+=1
    175            val = vals[i]
    176            pos = self._parsePoint(val)
    177            p.featDirs.append(pos)
    178          else:
    179            raise FeatMapParseError,'FeatPoint option %s not recognized on line %d'%(name,self._lineNum)
    180          i+=1
    181        feats.append(p)
    182        l = self._NextLine()
    183      return feats
    184  #------------------------------------
    185  #
    186  #  doctest boilerplate
    187  #
    188 -def _test():
    189    import doctest,sys
    190    return doctest.testmod(sys.modules["__main__"])
    191
    192  if __name__ == '__main__':
    193    import sys
    194    failed,tried = _test()
    195    sys.exit(failed)
    196