Chem.Features.ShowFeats

Package Chem :: Package Features :: Module ShowFeats |
[hide private]
[frames] | no frames]

# Source Code for Module Chem.Features.ShowFeats

      1  # $Id: ShowFeats.py 491 2007-07-27 08:13:04Z landrgr1 $
      2  #
      3  # Created by Greg Landrum Aug 2006
      4  #
      5  #
      6  _version = "0.3.1"
      7
      8
      9  _usage="""
     10     ShowFeats [optional args] <filenames>
     11
     12    if "-" is provided as a filename, data will be read from stdin (the console)
     13
     14  Optional arguments:
     15     -x "list":     specify a comma-separated list of feature types to be excluded from
     16                    the visualization
     17
     18     -f "fdef":
     19       or
     20     --fdef="fdef": specify the name of the fdef file.
     21
     22     --sd:
     23       or
     24     --sdf:         expect the input to be one or more SD files (otherwise mol files
     25                    are expected)
     26
     27     --nodirs:      do not calculate and display feature directions
     28
     29     --noheads:     do not put heads on the feature-direction arrows (only cylinders
     30                    will be drawn)
     31
     32     --noclear:     do not clear PyMol before starting
     33
     34     --write:       print out the feature locations in a form suitable for reading by
     35                    FeatureScorePoses.sh
     36
     37     --noMols:      only show features, not molecules
     38
     39     --verbose:     print the names of the molecules to the console as they are processed. This can make
     40                    the output from the --write option more readable when processing SD files.
     41
     42
     43  """
     44
     45  _welcomeMessage="This is ShowFeats version %s"%(_version)
     46
     47
     48  import math
     49  #set up the logger:
     50  import RDLogger as logging
     51  logger = logging.logger()
     52  logger.setLevel(logging.INFO)
     53
     54  import Geometry
     55  from Chem.Features import FeatDirUtilsRD as FeatDirUtils
     56
     57  _featColors = {
     58    'Donor':(0,1,1),
     59    'Acceptor':(1,0,1),
     60    'NegIonizable':(1,0,0),
     61    'PosIonizable':(0,0,1),
     62    'ZnBinder':(1,.5,.5),
     63    'Aromatic':(1,.8,.2),
     64    'LumpedHydrophobe':(.5,.25,0),
     65    'Hydrophobe':(.5,.25,0),
     66    }
     67
     68 -def _getVectNormal(v,tol=1e-4):
     69    if math.fabs(v.x)>tol:
     70      res = Geometry.Point3D(v.y,-v.x,0)
     71    elif math.fabs(v.y)>tol:
     72      res = Geometry.Point3D(-v.y,v.x,0)
     73    elif math.fabs(v.z)>tol:
     74      res = Geometry.Point3D(1,0,0)
     75    else:
     76      raise ValueError,'cannot find normal to the null vector'
     77    res.Normalize()
     78    return res
     79
     80  _canonArrowhead=None
     81 -def _buildCanonArrowhead(headFrac,nSteps,aspect):
     82    global _canonArrowhead
     83    startP = RDGeometry.Point3D(0,0,headFrac)
     84    _canonArrowhead=[startP]
     85
     86    scale = headFrac*aspect
     87    baseV = RDGeometry.Point3D(scale,0,0)
     88    _canonArrowhead.append(baseV)
     89
     90    twopi = 2*math.pi
     91    for i in range(1,nSteps):
     92      v = RDGeometry.Point3D(scale*math.cos(i*twopi),scale*math.sin(i*twopi),0)
     93      _canonArrowhead.append(v)
     94
     95
     96  _globalArrowCGO=[]
     97  _globalSphereCGO=[]
     98  # taken from pymol's cgo.py
     99  BEGIN=2
    100  END=3
    101  TRIANGLE_FAN=6
    102  COLOR=6
    103  VERTEX=4
    104  NORMAL=5
    105  SPHERE=7
    106  CYLINDER=9
    107  ALPHA=25
    108
    109 -def _cgoArrowhead(viewer,tail,head,radius,color,label,headFrac=0.3,nSteps=10,aspect=.5):
    110    global _globalArrowCGO
    111    delta = head-tail
    112    normal = _getVectNormal(delta)
    113    delta.Normalize()
    114
    115    dv = head-tail
    116    dv.Normalize()
    117    dv *= headFrac
    118    startP = head
    119
    120    normal*=headFrac*aspect
    121
    122    cgo = [BEGIN,TRIANGLE_FAN,
    123           COLOR,color[0],color[1],color[2],
    124            NORMAL,dv.x,dv.y,dv.z,
    125           VERTEX,head.x+dv.x,head.y+dv.y,head.z+dv.z]
    126    base = [BEGIN,TRIANGLE_FAN,
    127            COLOR,color[0],color[1],color[2],
    128            NORMAL,-dv.x,-dv.y,-dv.z,
    129            VERTEX,head.x,head.y,head.z]
    130    v = startP+normal
    131    cgo.extend([NORMAL,normal.x,normal.y,normal.z])
    132    cgo.extend([VERTEX,v.x,v.y,v.z])
    133    base.extend([VERTEX,v.x,v.y,v.z])
    134    for i in range(1,nSteps):
    135      v = FeatDirUtils.ArbAxisRotation(360./nSteps*i,delta,normal)
    136      cgo.extend([NORMAL,v.x,v.y,v.z])
    137      v += startP
    138      cgo.extend([VERTEX,v.x,v.y,v.z])
    139      base.extend([VERTEX,v.x,v.y,v.z])
    140
    141    cgo.extend([NORMAL,normal.x,normal.y,normal.z])
    142    cgo.extend([VERTEX,startP.x+normal.x,startP.y+normal.y,startP.z+normal.z])
    143    base.extend([VERTEX,startP.x+normal.x,startP.y+normal.y,startP.z+normal.z])
    144    cgo.append(END)
    145    base.append(END)
    146    cgo.extend(base)
    147
    148    #viewer.server.renderCGO(cgo,label)
    149    _globalArrowCGO.extend(cgo)
    150
    151 -def ShowArrow(viewer,tail,head,radius,color,label,transparency=0,includeArrowhead=True):
    152    global _globalArrowCGO
    153    if transparency:
    154      _globalArrowCGO.extend([ALPHA,1-transparency])
    155    else:
    156      _globalArrowCGO.extend([ALPHA,1])
    157    _globalArrowCGO.extend([CYLINDER,tail.x,tail.y,tail.z,
    158                            head.x,head.y,head.z,
    159                            radius*.10,
    160                            color[0],color[1],color[2],
    161                            color[0],color[1],color[2],
    162                            ])
    163
    164    if includeArrowhead:
    165      _cgoArrowhead(viewer,tail,head,radius,color,label)
    166
    167
    168 -def ShowMolFeats(mol,factory,viewer,radius=0.5,confId=-1,showOnly=True,
    169                   name='',transparency=0.0,colors=None,excludeTypes=[],
    170                   useFeatDirs=True,featLabel=None,dirLabel=None,includeArrowheads=True,
    171                   writeFeats=False,showMol=True,featMapFile=False):
    172    global _globalSphereCGO
    173    if not name:
    174      if mol.HasProp('_Name'):
    175        name =  mol.GetProp('_Name')
    176      else:
    177        name = 'molecule'
    178    if not colors:
    179      colors = _featColors
    180
    181    if showMol:
    182      viewer.ShowMol(mol,name=name,showOnly=showOnly,confId=confId)
    183
    184    molFeats=factory.GetFeaturesForMol(mol)
    185    if not featLabel:
    186      featLabel='%s-feats'%name
    187      viewer.server.resetCGO(featLabel)
    188    if not dirLabel:
    189      dirLabel=featLabel+"-dirs"
    190      viewer.server.resetCGO(dirLabel)
    191
    192    for i,feat in enumerate(molFeats):
    193      family=feat.GetFamily()
    194      if family in excludeTypes:
    195        continue
    196      pos = feat.GetPos(confId)
    197      color = colors.get(family,(.5,.5,.5))
    198      nm = '%s(%d)'%(family,i+1)
    199
    200      if transparency:
    201        _globalSphereCGO.extend([ALPHA,1-transparency])
    202      else:
    203        _globalSphereCGO.extend([ALPHA,1])
    204      _globalSphereCGO.extend([COLOR,color[0],color[1],color[2],
    205                               SPHERE,pos.x,pos.y,pos.z,
    206                               radius])
    207      if writeFeats:
    208        aidText = ' '.join([str(x+1) for x in feat.GetAtomIds()])
    209        print '%s\t%.3f\t%.3f\t%.3f\t1.0\t# %s'%(family,pos.x,pos.y,pos.z,aidText)
    210
    211      if featMapFile:
    212        print >>featMapFile,"  family=%s pos=(%.3f,%.3f,%.3f) weight=1.0"%(family,pos.x,pos.y,pos.z),
    213
    214      if useFeatDirs:
    215        ps = []
    216        if family=='Aromatic':
    217          ps,fType = FeatDirUtils.GetAromaticFeatVects(mol.GetConformer(confId),
    218                                                                 feat.GetAtomIds(),pos,
    219                                                                 scale=1.0)
    220        elif family=='Donor':
    221          aids = feat.GetAtomIds()
    222          if len(aids)==1:
    223            if len(mol.GetAtomWithIdx(aids[0]).GetNeighbors())==1:
    224              ps,fType = FeatDirUtils.GetDonor1FeatVects(mol.GetConformer(confId),
    225                                                         aids,scale=1.0)
    226            elif len(mol.GetAtomWithIdx(aids[0]).GetNeighbors())==2:
    227              ps,fType = FeatDirUtils.GetDonor2FeatVects(mol.GetConformer(confId),
    228                                                         aids,scale=1.0)
    229            elif len(mol.GetAtomWithIdx(aids[0]).GetNeighbors())==3:
    230              ps,fType = FeatDirUtils.GetDonor3FeatVects(mol.GetConformer(confId),
    231                                                         aids,scale=1.0)
    232        elif family=='Acceptor':
    233          aids = feat.GetAtomIds()
    234          if len(aids)==1:
    235            if len(mol.GetAtomWithIdx(aids[0]).GetNeighbors())==1:
    236              ps,fType = FeatDirUtils.GetAcceptor1FeatVects(mol.GetConformer(confId),
    237                                                            aids,scale=1.0)
    238            elif len(mol.GetAtomWithIdx(aids[0]).GetNeighbors())==2:
    239              ps,fType = FeatDirUtils.GetAcceptor2FeatVects(mol.GetConformer(confId),
    240                                                         aids,scale=1.0)
    241            elif len(mol.GetAtomWithIdx(aids[0]).GetNeighbors())==3:
    242              ps,fType = FeatDirUtils.GetAcceptor3FeatVects(mol.GetConformer(confId),
    243                                                         aids,scale=1.0)
    244
    245        for tail,head in ps:
    246          ShowArrow(viewer,tail,head,radius,color,dirLabel,
    247                    transparency=transparency,includeArrowhead=includeArrowheads)
    248          if featMapFile:
    249            vect = head-tail
    250            print >>featMapFile,'dir=(%.3f,%.3f,%.3f)'%(vect.x,vect.y,vect.z),
    251
    252      if featMapFile:
    253        aidText = ' '.join([str(x+1) for x in feat.GetAtomIds()])
    254        print >>featMapFile,'# %s'%(aidText)
    255
    256
    257
    258
    259  # --- ----  --- ----  --- ----  --- ----  --- ----  --- ----
    260  import sys,os,getopt
    261  import RDConfig
    262  from optparse import OptionParser
    263  parser=OptionParser(_usage,version='%prog '+_version)
    264
    265  parser.add_option('-x','--exclude',default='',
    266                    help='provide a list of feature names that should be excluded')
    267  parser.add_option('-f','--fdef',default=os.path.join(RDConfig.RDDataDir,'Novartis1.fdef'),
    268                    help='provide the name of the feature definition (fdef) file.')
    269  parser.add_option('--noDirs','--nodirs',dest='useDirs',default=True,action='store_false',
    270                    help='do not draw feature direction indicators')
    271  parser.add_option('--noHeads',dest='includeArrowheads',default=True,action='store_false',
    272                    help='do not draw arrowheads on the feature direction indicators')
    273  parser.add_option('--noClear','--noClear',dest='clearAll',default=False,action='store_true',
    274                    help='do not clear PyMol on startup')
    275  parser.add_option('--noMols','--nomols',default=False,action='store_true',
    276                    help='do not draw the molecules')
    277  parser.add_option('--writeFeats','--write',default=False,action='store_true',
    278                    help='print the feature information to the console')
    279  parser.add_option('--featMapFile','--mapFile',default='',
    280                    help='save a feature map definition to the specified file')
    281  parser.add_option('--verbose',default=False,action='store_true',
    282                    help='be verbose')
    283
    284  if __name__=='__main__':
    285    import Chem
    286    from Chem import AllChem
    287    from Chem.PyMol import MolViewer
    288
    289    options,args = parser.parse_args()
    290    if len(args)<1:
    291      parser.error('please provide either at least one sd or mol file')
    292
    293    try:
    294      v = MolViewer()
    295    except:
    296      logger.error('Unable to connect to PyMol server.\nPlease run ~landrgr1/extern/PyMol/launch.sh to start it.')
    297      sys.exit(1)
    298    if options.clearAll:
    299      v.DeleteAll()
    300
    301
    302    try:
    303      fdef = file(options.fdef,'r').read()
    304    except IOError:
    305      logger.error('ERROR: Could not open fdef file %s'%options.fdef)
    306      sys.exit(1)
    307
    308    factory = AllChem.BuildFeatureFactoryFromString(fdef)
    309
    310    if options.writeFeats:
    311       print '# Family   \tX    \tY   \tZ   \tRadius\t # Atom_ids'
    312
    313    if options.featMapFile:
    314      if options.featMapFile=='-':
    315        options.featMapFile=sys.stdout
    316      else:
    317        options.featMapFile=file(options.featMapFile,'w+')
    318      print >>options.featMapFile,'# Feature map generated by ShowFeats v%s'%_version
    319      print >>options.featMapFile,"ScoreMode=All"
    320      print >>options.featMapFile,"DirScoreMode=Ignore"
    321      print >>options.featMapFile,"BeginParams"
    322      for family in factory.GetFeatureFamilies():
    323        print >>options.featMapFile,"   family=%s width=1.0 radius=3.0"%family
    324      print >>options.featMapFile,"EndParams"
    325      print >>options.featMapFile,"BeginPoints"
    326
    327    i = 1
    328    for midx,molN in enumerate(args):
    329      if molN!='-':
    330        featLabel='%s_Feats'%molN
    331      else:
    332        featLabel='Mol%d_Feats'%(midx+1)
    333
    334      v.server.resetCGO(featLabel)
    335      # this is a big of kludgery to work around what seems to be a pymol cgo bug:
    336      v.server.sphere((0,0,0),.01,(1,0,1),featLabel)
    337      dirLabel=featLabel+"-dirs"
    338
    339      v.server.resetCGO(dirLabel)
    340      # this is a big of kludgery to work around what seems to be a pymol cgo bug:
    341      v.server.cylinder((0,0,0),(.01,.01,.01),.01,(1,0,1),dirLabel)
    342
    343      if molN != '-':
    344        try:
    345          ms = Chem.SDMolSupplier(molN)
    346        except:
    347          logger.error('Problems reading input file: %s'%molN)
    348          ms = []
    349      else:
    350        ms = Chem.SDMolSupplier()
    351        ms.SetData(sys.stdin.read())
    352
    353      for m in ms:
    354        nm = 'Mol_%d'%(i)
    355        if m.HasProp('_Name'):
    356          nm += '_'+m.GetProp('_Name')
    357        if options.verbose:
    358          if m.HasProp('_Name'):
    359            print "#Molecule: %s"%m.GetProp('_Name')
    360          else:
    361            print "#Molecule: %s"%nm
    362        ShowMolFeats(m,factory,v,transparency=0.25,excludeTypes=options.exclude,name=nm,
    363                     showOnly=False,
    364                     useFeatDirs=options.useDirs,
    365                     featLabel=featLabel,dirLabel=dirLabel,
    366                     includeArrowheads=options.includeArrowheads,
    367                     writeFeats=options.writeFeats,showMol=not options.noMols,
    368                     featMapFile=options.featMapFile)
    369        i += 1
    370        if not i%100:
    371          logger.info("Done %d poses"%i)
    372      if ms:
    373        v.server.renderCGO(_globalSphereCGO,featLabel,1)
    374        if options.useDirs:
    375          v.server.renderCGO(_globalArrowCGO,dirLabel,1)
    376
    377    if options.featMapFile:
    378      print >>options.featMapFile,"EndPoints"
    379
    380
    381    sys.exit(0)
    382