rdkit.Chem.FeatMaps.FeatMapParser

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

# Source Code for Module rdkit.Chem.FeatMaps.FeatMapParser

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