1#
2# Copyright (C) 2001-2006 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""" Calculation of Lipinski parameters for molecules
11
12"""
13from rdkit import Chem
14from rdkit.Chem import rdMolDescriptors
15
16# -----------------------------------
17# on import build the SMARTS patterns so we only have to do it once
18# -----------------------------------
19# The Daylight SMARTS expressions for
20# recognizing H-bond donors and acceptors in the Lipinski scheme.
21# HDonor     '[!#6;!H0;-0]'
22# HAcceptor  '[$([!#6;+0]);!$([F,Cl,Br,I]);
23#             !$([o,s,nX3]);!$([Nv5,Pv5,Sv4,Sv6])]'
24# Heteroatom '[B,N,O,P,S,F,Cl,Br,I]'
25# 2 definitions adapted from those in the Gobbi Paper
26#  NOTE: if you want traditional Lipinski numbers, you
27#  should use NOCounts (below) instead of HAcceptor
28#
29HDonorSmarts = Chem.MolFromSmarts('[$([N;!H0;v3]),$([N;!H0;+1;v4]),$([O,S;H1;+0]),$([n;H1;+0])]')
30# changes log for HAcceptorSmarts:
31#  v2, 1-Nov-2008, GL : fix amide-N exclusion; remove Fs from definition
32HAcceptorSmarts = Chem.MolFromSmarts('[$([O,S;H1;v2]-[!$(*=[O,N,P,S])]),' +
33                                     '$([O,S;H0;v2]),$([O,S;-]),$([N;v3;!$(N-*=!@[O,N,P,S])]),' +
34                                     '$([nH0,o,s;+0])]')
35
36HeteroatomSmarts = Chem.MolFromSmarts('[!#6;!#1]')
37#  NOTE: the Rotatable bond smarts here doesn't treat deuteriums (which are left in the graph
38#  and therefore contribute to the degree of a carbon) the same as hydrogens (which are removed
39#  from the graph). So the bond in [2H]C([2H])([2H])C([2H])([2H])[2H] *is* considered
40#  rotatable.
41RotatableBondSmarts = Chem.MolFromSmarts('[!$(*#*)&!D1]-&!@[!$(*#*)&!D1]')
42NHOHSmarts = Chem.MolFromSmarts('[#8H1,#7H1,#7H2,#7H3]')
43NOCountSmarts = Chem.MolFromSmarts('[#7,#8]')
44
45# # this little trick saves duplicated code
46# def _NumMatches(mol, smarts):
47#   return len(mol.GetSubstructMatches(smarts, uniquify=1))
48
49NumHDonors = lambda x: rdMolDescriptors.CalcNumHBD(x)
50NumHDonors.__doc__ = "Number of Hydrogen Bond Donors"
51NumHDonors.version = "1.0.0"
52_HDonors = lambda x, y=HDonorSmarts: x.GetSubstructMatches(y, uniquify=1)
53NumHAcceptors = lambda x: rdMolDescriptors.CalcNumHBA(x)
54NumHAcceptors.__doc__ = "Number of Hydrogen Bond Acceptors"
55NumHAcceptors.version = "2.0.0"
56_HAcceptors = lambda x, y=HAcceptorSmarts: x.GetSubstructMatches(y, uniquify=1)
57NumHeteroatoms = lambda x: rdMolDescriptors.CalcNumHeteroatoms(x)
58NumHeteroatoms.__doc__ = "Number of Heteroatoms"
59NumHeteroatoms.version = "1.0.0"
60_Heteroatoms = lambda x, y=HeteroatomSmarts: x.GetSubstructMatches(y, uniquify=1)
61NumRotatableBonds = lambda x: rdMolDescriptors.CalcNumRotatableBonds(x)
62NumRotatableBonds.__doc__ = "Number of Rotatable Bonds"
63NumRotatableBonds.version = "1.0.0"
64_RotatableBonds = lambda x, y=RotatableBondSmarts: x.GetSubstructMatches(y, uniquify=1)
65NOCount = lambda x: rdMolDescriptors.CalcNumLipinskiHBA(x)
66NOCount.__doc__ = "Number of Nitrogens and Oxygens"
67NOCount.version = "1.0.0"
68NHOHCount = lambda x: rdMolDescriptors.CalcNumLipinskiHBD(x)
69NHOHCount.__doc__ = "Number of NHs or OHs"
70NHOHCount.version = "2.0.0"
71
72RingCount = lambda x: rdMolDescriptors.CalcNumRings(x)
73RingCount.version = "1.0.0"
74
75
76def HeavyAtomCount(mol):
77  " Number of heavy atoms a molecule."
78  return mol.GetNumHeavyAtoms()
79
80
81HeavyAtomCount.version = "1.0.1"
82
83_bulkConvert = ("CalcFractionCSP3", "CalcNumAromaticRings", "CalcNumSaturatedRings",
84                "CalcNumAromaticHeterocycles", "CalcNumAromaticCarbocycles",
85                "CalcNumSaturatedHeterocycles", "CalcNumSaturatedCarbocycles",
86                "CalcNumAliphaticRings", "CalcNumAliphaticHeterocycles",
87                "CalcNumAliphaticCarbocycles")
88for txt in _bulkConvert:
89  _cfn = getattr(rdMolDescriptors, txt)
90  _fn = lambda x, y=_cfn: y(x)
91  try:
92    _fn.version = getattr(rdMolDescriptors, "_" + txt + "_version")
93  except AttributeError:
94    pass
95  _fn.__doc__ = _cfn.__doc__
96  nm = txt.replace("Calc", "")
97  locals()[nm] = _fn
98