rdkit.Chem.Descriptors

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

# Source Code for Module rdkit.Chem.Descriptors

      1  #
      2  # Copyright (C) 2001-2017 greg Landrum and Rational Discovery LLC
      3  #
      4  #   @@ All Rights Reserved @@
      5  #  This file is part of the RDKit.
      6  #  The contents are covered by the terms of the BSD license
      7  #  which is included in the file license.txt, found at the root
      8  #  of the RDKit source tree.
      9  #
     10  import collections
     11
     12  from rdkit import Chem
     13  from rdkit.Chem import rdMolDescriptors as _rdMolDescriptors
     14  from rdkit.Chem import rdPartialCharges, rdMolDescriptors
     15  import rdkit.Chem.ChemUtils.DescriptorUtilities as _du
     16  from rdkit.Chem.EState.EState import (MaxEStateIndex, MinEStateIndex,
     17                                        MaxAbsEStateIndex, MinAbsEStateIndex)
     18  from rdkit.Chem.QED import qed
     19
     20
     21 -def _isCallable(thing):
     22    return (hasattr(collections, 'Callable') and isinstance(thing, collections.Callable)) or \
     23                hasattr(thing, '__call__')
     24
     25
     26  _descList = []
     27
     28
     29 -def _setupDescriptors(namespace):
     30    global _descList, descList
     31    from rdkit.Chem import GraphDescriptors, MolSurf, Lipinski, Fragments, Crippen, Descriptors3D
     32    from rdkit.Chem.EState import EState_VSA
     33    mods = [GraphDescriptors, MolSurf, EState_VSA, Lipinski, Crippen, Fragments]
     34
     35    otherMods = [Chem]
     36
     37    for nm, thing in namespace.items():
     38      if nm[0] != '_' and _isCallable(thing):
     39        _descList.append((nm, thing))
     40
     41    others = []
     42    for mod in otherMods:
     43      tmp = dir(mod)
     44      for name in tmp:
     45        if name[0] != '_':
     46          thing = getattr(mod, name)
     47          if _isCallable(thing):
     48            others.append(name)
     49
     50    for mod in mods:
     51      tmp = dir(mod)
     52
     53      for name in tmp:
     54        if name[0] != '_' and name[-1] != '_' and name not in others:
     55          # filter out python reference implementations:
     56          if name[:2] == 'py' and name[2:] in tmp:
     57            continue
     58          if name == 'print_function':
     59            continue
     60          thing = getattr(mod, name)
     61          if _isCallable(thing):
     62            namespace[name] = thing
     63            _descList.append((name, thing))
     64    descList = _descList
     65
     66
     67  MolWt = lambda *x, **y: _rdMolDescriptors._CalcMolWt(*x, **y)
     68  MolWt.version = _rdMolDescriptors._CalcMolWt_version
     69  MolWt.__doc__ = """The average molecular weight of the molecule
     70
     71    >>> MolWt(Chem.MolFromSmiles('CC'))
     72    30.07
     73    >>> MolWt(Chem.MolFromSmiles('[NH4+].[Cl-]'))
     74    53.49...
     75
     76  """
     77
     78  HeavyAtomMolWt = lambda x: MolWt(x, True)
     79  HeavyAtomMolWt.__doc__ = """The average molecular weight of the molecule ignoring hydrogens
     80
     81    >>> HeavyAtomMolWt(Chem.MolFromSmiles('CC'))
     82    24.02...
     83    >>> HeavyAtomMolWt(Chem.MolFromSmiles('[NH4+].[Cl-]'))
     84    49.46
     85
     86  """
     87  HeavyAtomMolWt.version = "1.0.0"
     88
     89  ExactMolWt = lambda *x, **y: _rdMolDescriptors.CalcExactMolWt(*x, **y)
     90  ExactMolWt.version = _rdMolDescriptors._CalcExactMolWt_version
     91  ExactMolWt.__doc__ = """The exact molecular weight of the molecule
     92
     93    >>> ExactMolWt(Chem.MolFromSmiles('CC'))
     94    30.04...
     95    >>> ExactMolWt(Chem.MolFromSmiles('[13CH3]C'))
     96    31.05...
     97
     98  """
     99
    100
    101 -def NumValenceElectrons(mol):
    102    """ The number of valence electrons the molecule has
    103
    104    >>> NumValenceElectrons(Chem.MolFromSmiles('CC'))
    105    14
    106    >>> NumValenceElectrons(Chem.MolFromSmiles('C(=O)O'))
    107    18
    108    >>> NumValenceElectrons(Chem.MolFromSmiles('C(=O)[O-]'))
    109    18
    110    >>> NumValenceElectrons(Chem.MolFromSmiles('C(=O)'))
    111    12
    112
    113    """
    114    tbl = Chem.GetPeriodicTable()
    115    return sum(
    116      tbl.GetNOuterElecs(atom.GetAtomicNum()) - atom.GetFormalCharge() + atom.GetTotalNumHs()
    117      for atom in mol.GetAtoms())
    118
    119
    120  NumValenceElectrons.version = "1.1.0"
    121
    122
    123 -def NumRadicalElectrons(mol):
    124    """ The number of radical electrons the molecule has
    125      (says nothing about spin state)
    126
    127    >>> NumRadicalElectrons(Chem.MolFromSmiles('CC'))
    128    0
    129    >>> NumRadicalElectrons(Chem.MolFromSmiles('C[CH3]'))
    130    0
    131    >>> NumRadicalElectrons(Chem.MolFromSmiles('C[CH2]'))
    132    1
    133    >>> NumRadicalElectrons(Chem.MolFromSmiles('C[CH]'))
    134    2
    135    >>> NumRadicalElectrons(Chem.MolFromSmiles('C[C]'))
    136    3
    137
    138    """
    139    return sum(atom.GetNumRadicalElectrons() for atom in mol.GetAtoms())
    140
    141
    142  NumRadicalElectrons.version = "1.1.0"
    143
    144
    145 -def _ChargeDescriptors(mol, force=False):
    146    if not force and hasattr(mol, '_chargeDescriptors'):
    147      return mol._chargeDescriptors
    148    chgs = rdPartialCharges.ComputeGasteigerCharges(mol)
    149    minChg = 500.
    150    maxChg = -500.
    151    for at in mol.GetAtoms():
    152      chg = float(at.GetProp('_GasteigerCharge'))
    153      minChg = min(chg, minChg)
    154      maxChg = max(chg, maxChg)
    155    res = (minChg, maxChg)
    156    mol._chargeDescriptors = res
    157    return res
    158
    159
    160 -def MaxPartialCharge(mol, force=False):
    161    _, res = _ChargeDescriptors(mol, force)
    162    return res
    163
    164
    165  MaxPartialCharge.version = "1.0.0"
    166
    167
    168 -def MinPartialCharge(mol, force=False):
    169    res, _ = _ChargeDescriptors(mol, force)
    170    return res
    171
    172
    173  MinPartialCharge.version = "1.0.0"
    174
    175
    176 -def MaxAbsPartialCharge(mol, force=False):
    177    v1, v2 = _ChargeDescriptors(mol, force)
    178    return max(abs(v1), abs(v2))
    179
    180
    181  MaxAbsPartialCharge.version = "1.0.0"
    182
    183
    184 -def MinAbsPartialCharge(mol, force=False):
    185    v1, v2 = _ChargeDescriptors(mol, force)
    186    return min(abs(v1), abs(v2))
    187
    188
    189  MinAbsPartialCharge.version = "1.0.0"
    190
    191
    192 -def _FingerprintDensity(mol, func, *args, **kwargs):
    193    fp = func(*((mol,) + args), **kwargs)
    194    if hasattr(fp, 'GetNumOnBits'):
    195      val = fp.GetNumOnBits()
    196    else:
    197      val = len(fp.GetNonzeroElements())
    198    return float(val) / mol.GetNumHeavyAtoms()
    199
    200
    201  FpDensityMorgan1 = lambda x: _FingerprintDensity(x, _rdMolDescriptors.GetMorganFingerprint, 1)
    202  FpDensityMorgan2 = lambda x: _FingerprintDensity(x, _rdMolDescriptors.GetMorganFingerprint, 2)
    203  FpDensityMorgan3 = lambda x: _FingerprintDensity(x, _rdMolDescriptors.GetMorganFingerprint, 3)
    204  _du.setDescriptorVersion('1.0.0')(FpDensityMorgan1)
    205  _du.setDescriptorVersion('1.0.0')(FpDensityMorgan2)
    206  _du.setDescriptorVersion('1.0.0')(FpDensityMorgan3)
    207
    208  _setupDescriptors(locals())
    209
    210
    211 -class PropertyFunctor(rdMolDescriptors.PythonPropertyFunctor):
    212    """Creates a python based property function that can be added to the
    213    global property list.  To use, subclass this class and override the
    214    __call__ method.  Then create an instance and add it to the
    215    registry.  The __call__ method should return a numeric value.
    216
    217    Example:
    218
    219      class NumAtoms(Descriptors.PropertyFunctor):
    220        def __init__(self):
    221          Descriptors.PropertyFunctor.__init__(self, "NumAtoms", "1.0.0")
    222        def __call__(self, mol):
    223          return mol.GetNumAtoms()
    224
    225      numAtoms = NumAtoms()
    226      rdMolDescriptors.Properties.RegisterProperty(numAtoms)
    227    """
    228
    229 -  def __init__(self, name, version):
    230      rdMolDescriptors.PythonPropertyFunctor.__init__(self, self, name, version)
    231
    232 -  def __call__(self, mol):
    233      raise NotImplementedError("Please implement the __call__ method")
    234
    235
    236  # ------------------------------------
    237  #
    238  #  doctest boilerplate
    239  #
    240 -def _runDoctests(verbose=None):  # pragma: nocover
    241    import sys
    242    import doctest
    243    failed, _ = doctest.testmod(optionflags=doctest.ELLIPSIS, verbose=verbose)
    244    sys.exit(failed)
    245
    246
    247  if __name__ == '__main__':  # pragma: nocover
    248    _runDoctests()
    249