Hi Giovanni,
I while ago I wrote this code in Python to enumerate all/undefined chiral centers in a
given molecule.
It works fairly well, although, you may want to check your structures if you're generating
3D coordinates, since at least the stable version of OpenBabel (2.3.2) has some issues
with chiral centers in (multiple?)rings.
S
On 09/08/2016 12:48 AM, Giovanni Cincilla wrote:
Hi everybody,
Starting from a certain molecule with possibly undefined sp3 stereocenters
(R/S) is it possible to enumerate with OpenBabel all the possible
stereisomers as different molecules?
Any help is appreciated. Thanks
Gio
--
View this message in context:
http://forums.openbabel.org/How-to-enumerate-all-possible-stereoisomers-of-a-molecule-with-a-not-defined-stereocenter-tp4659459.html
Sent from the General discussion mailing list archive at Nabble.com.
------------------------------------------------------------------------------
_______________________________________________
OpenBabel-discuss mailing list
OpenBabel-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openbabel-discuss
--
Stefano Forli, PhD
Assistant Professor of ISCB
Molecular Graphics Laboratory
Dept. of Integrative Structural
and Computational Biology, MB-112A
The Scripps Research Institute
10550 North Torrey Pines Road
La Jolla, CA 92037-1000, USA.
tel: +1 (858)784-2055
fax: +1 (858)784-2860
email: fo...@scripps.edu
http://www.scripps.edu/~forli/
import itertools
class ChiralEnumerator:
""" chirality generator
initialized with a molecule provides a generator
that can be used to enumerate isomers of a molecule
mol : obmol
chiralityType : 'all' = generate all enantiomers for any chiral center
'undefined' = generate enantiomers for undefined chiral centers
'off' = disable enantiomer generation
maxIter : maximum number of enantiomers to generate
verbose : print status of generation
"""
def __init__(self, mol, chiralityType='all', maxIter=50, verbose=True):
""" """
self.verbose = verbose
self.mol = mol
self.maxIter = maxIter
self.chiralityType = chiralityType
self.active = False
self._stop = False
self._iterations = 0
self.labels = [ 'R', 'S'] # note: this is arbitrary!
self.chiralSet = []
if self.mol.IsChiral() and (not self.chiralityType=='off'):
self.chiral = []
self.chiralDefined = []
self.blacklist = self.findBlacklistCenters()
self.facade = ob.OBStereoFacade(self.mol)
# find which atoms are to be considered chiral
for a in ob.OBMolAtomIter(self.mol):
idx = a.GetIdx()#-1
if self.facade.HasTetrahedralStereo(idx) and not idx in self.blacklist:
self.chiral.append( idx )
ts = self.facade.GetTetrahedralStereo(idx)
config = ts.GetConfig()
if config.specified:
self.chiralDefined.append(idx)
else:
config.specified = True
ts.SetConfig(config)
if len(self.chiral) > 0:
self.active = True
msg = ('[ChiralEnumerator] chirality Implicit[%d] Explicit[%d]'
'' % (len(self.chiral), len(self.chiralDefined)))
self.vprint(msg)
if self.chiralityType == 'all':
self.chiralAccepted = self.chiral
msg = ('[ChiralEnumerator] chiral set ALL [%d] atoms' % len(self.chiralAccepted))
elif self.chiralityType == 'undefined':
self.chiralAccepted = set(self.chiral) - set(self.chiralDefined)
msg = ('[ChiralEnumerator] chiral set UNDEFINED [%d] atoms' % len(self.chiralAccepted))
self.vprint(msg)
self.chiralSet = []
tmp = {}
for idx in self.chiralAccepted:
ref1 = self.facade.GetTetrahedralStereo(idx).GetConfig().refs
ref2 = ( ref1[1], ref1[0], ref1[2] )
self.chiralSet.append((ref1, ref2))
self.chiralSet = list( itertools.product( *self.chiralSet) )
self.vprint("\n\n\n[ChiralEnumerator]: %d chiral centers accepted" % len(self.chiralSet) )
def __iter__(self):
"""" """
return self
def next(self):
""" """
if self._iterations >= self.maxIter:
self._stop = True
if self._stop:
raise StopIteration
if not self.active:
self._stop = True
return self.mol
else:
#if True:
try:
refs = self.chiralSet.pop()
msg = ('[enumchiral] |%s| enantiomer to be generated' % str(refs)) # (%s)'
#'' % (','.join([self.labels[x-1] for x in refs ]), refs))
self.vprint(msg)
self._iterations += 1
for idx, aIdx in enumerate(self.chiralAccepted):
ts = self.facade.GetTetrahedralStereo(aIdx)
config = ts.GetConfig()
config.refs = ( refs[idx][0], refs[idx][1], refs[idx][2])
x = ts.SetConfig(config)
#print ""
canonic = ob.OBMol()
obc = ob.OBConversion()
obc.SetInAndOutFormats('smi', 'can')
can = obc.WriteString(self.mol)
self.vprint("CANONICAL SMILE ENANTIOMER: %s"% can.strip())
obc.ReadString(canonic, can)
return canonic
except IndexError:
raise StopIteration
def vprint(self, string, addnewline=True, flush=False, rewind=False):
""" debugging printing"""
if not self.verbose:
return
msg = ''
if rewind:
msg += '\r'
msg += "VERBOSE: %s" % string
if not addnewline:
print msg,
else:
print msg
if flush:
sys.stdout.flush()
def findBlacklistCenters(self):
""" identify unwanted patterns (adamantane, for now) to avoid combinatorial
enumeration of its chiral centers
"""
pattern = [ 'C1C3CC2CC(CC1C2)C3']
m = ob.OBSmartsPattern()
for p in pattern:
m.Init(p)
found = m.Match(self.mol)
if found:
if self.verbose:
print "[findBlacklistCenters]: found unwanted!", p
return [ x for x in m.GetUMapList() ][0]
return ()
if __name__ == '__main__':
import sys, os
import pybel
ob = pybel.ob
name, ext = os.path.splitext(sys.argv[1])
ext = ext[1:].lower()
for pmol in pybel.readfile(ext, sys.argv[1]):
mol = pmol.OBMol
for chiral in ChiralEnumerator(mol, chiralityType='all',
maxIter = 50, verbose = False):
s = pybel.Molecule(chiral)
print s.strip()
------------------------------------------------------------------------------
_______________________________________________
OpenBabel-discuss mailing list
OpenBabel-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openbabel-discuss