Chem.SATIS

Package Chem :: Module SATIS |
[hide private]
[frames] | no frames]

# Source Code for Module Chem.SATIS

      1  # $Id: SATIS.py 2 2006-05-06 22:54:39Z glandrum $
      2  #
      3  # Copyright (C) 2001-2006 greg Landrum and Rational Discovery LLC
      4  #
      5  #   @@ All Rights Reserved  @@
      6  #
      7  """  Functionality for SATIS typing atoms
      8
      9  """
     10  import Chem
     11
     12  _debug = 0
     13
     14  #
     15  #  These are SMARTS patterns for the special cases used in
     16  #  SATIS typing.
     17  #
     18  aldehydePatt = Chem.MolFromSmarts('[CD2]=[OD1]')
     19  ketonePatt = Chem.MolFromSmarts('[CD3]=[OD1]')
     20  amidePatt = Chem.MolFromSmarts('[CD3](=[OD1])-[#7]')
     21  esterPatt = Chem.MolFromSmarts('C(=[OD1])-O-[#6]')
     22  carboxylatePatt = Chem.MolFromSmarts('C(=[OD1])-[OX1]')
     23  carboxylPatt = Chem.MolFromSmarts('C(=[OD1])-[OX2]')
     24
     25  specialCases = ((carboxylatePatt,97),
     26                  (esterPatt,96),
     27                  (carboxylPatt,98),
     28                  (amidePatt,95),
     29                  (ketonePatt,94),
     30                  (aldehydePatt,93))
     31
     32
     33 -def SATISTypes(mol,neighborsToInclude=4):
     34    """ returns SATIS codes for all atoms in a molecule
     35
     36     The SATIS definition used is from:
     37     J. Chem. Inf. Comput. Sci. _39_ 751-757 (1999)
     38
     39     each SATIS code is a string consisting of _neighborsToInclude_ + 1
     40     2 digit numbers
     41
     42     **Arguments**
     43
     44       - mol: a molecule
     45
     46       - neighborsToInclude (optional): the number of neighbors to include
     47         in the SATIS codes
     48
     49     **Returns**
     50
     51       a list of strings nAtoms long
     52
     53    """
     54    global specialCases
     55
     56    nAtoms = mol.GetNumAtoms()
     57    atomicNums = [0]*nAtoms
     58    atoms = mol.GetAtoms()
     59    for i in xrange(nAtoms):
     60      atomicNums[i] = atoms[i].GetAtomicNum()
     61
     62    nSpecialCases = len(specialCases)
     63    specialCaseMatches = [None]*nSpecialCases
     64    for i,(patt,idx) in enumerate(specialCases):
     65      if mol.HasSubstructMatch(patt):
     66        specialCaseMatches[i] = mol.GetSubstructMatches(patt)
     67      else:
     68        specialCaseMatches[i] = ()
     69
     70    codes = [None]*nAtoms
     71    for i in range(nAtoms):
     72      code = [99]*(neighborsToInclude+1)
     73      atom = atoms[i]
     74      atomIdx = atom.GetIdx()
     75      code[0] = min(atom.GetAtomicNum(),99)
     76      bonds = atom.GetBonds()
     77      nBonds = len(bonds)
     78      otherIndices = [-1]*nBonds
     79      if _debug: print code[0],
     80      for j in range(nBonds):
     81        otherIndices[j] = bonds[j].GetOtherAtom(atom).GetIdx()
     82        if _debug: print otherIndices[j],
     83      if _debug: print
     84      otherNums = [atomicNums[x] for x in otherIndices] + \
     85                  [1]*atom.GetTotalNumHs()
     86      otherNums.sort()
     87
     88      nOthers = len(otherNums)
     89      if nOthers > neighborsToInclude:
     90        otherNums.reverse()
     91        otherNums = otherNums[:neighborsToInclude]
     92        otherNums.reverse()
     93        for j in range(neighborsToInclude):
     94          code[j+1] = min(otherNums[j],99)
     95      else:
     96        for j in range(nOthers):
     97          code[j+1] = min(otherNums[j],99)
     98        if nOthers < neighborsToInclude and code[0] in [6,8]:
     99          found = 0
    100          for j in range(nSpecialCases):
    101            for matchTuple in specialCaseMatches[j]:
    102              if atomIdx in matchTuple:
    103                code[-1] = specialCases[j][1]
    104                found = 1
    105                break
    106            if found:
    107              break
    108
    109      codes[i] = ''.join(['%02d'%(x) for x in code])
    110    return codes
    111
    112  if __name__ == '__main__':
    113    smis = ['CC(=O)NC','CP(F)(Cl)(Br)(O)',
    114            'O=CC(=O)C','C(=O)OCC(=O)O','C(=O)[O-]']
    115    for smi in smis:
    116      print smi
    117      m = Chem.MolFromSmiles(smi)
    118      codes = SATISTypes(m)
    119      print codes
    120