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