mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-05 22:04:27 +08:00
327 lines
11 KiB
Python
Executable File
327 lines
11 KiB
Python
Executable File
import os
|
|
import sys
|
|
import unittest
|
|
from multiprocessing import Process, Value
|
|
from time import sleep
|
|
|
|
from rdkit import Chem, RDConfig
|
|
from rdkit.Chem import ChemicalForceFields, rdMolTransforms
|
|
|
|
|
|
class OptSafe:
|
|
|
|
def __init__(self):
|
|
self.minInfLoop = """minInfLoop
|
|
RDKit 3D
|
|
|
|
7 5 0 0 0 0 0 0 0 0999 V2000
|
|
1.7321 -0.5000 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.8660 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0000 -0.5000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.5000 -1.3660 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.8660 -1.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.5000 0.3660 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
3.2321 -0.5000 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 1 0 0 0 0
|
|
2 3 1 0 0 0 0
|
|
3 4 1 0 0 0 0
|
|
3 5 1 0 0 0 0
|
|
3 6 1 0 0 0 0
|
|
M CHG 2 3 1 7 -1
|
|
M END"""
|
|
|
|
def uffOptFunc(self, v, mol):
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(mol)
|
|
try:
|
|
ff.Minimize()
|
|
except RuntimeError:
|
|
pass
|
|
v.value = True
|
|
return
|
|
|
|
def mmffOptFunc(self, v, mol):
|
|
mp = ChemicalForceFields.MMFFGetMoleculeProperties(mol)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(mol, mp)
|
|
try:
|
|
ff.Minimize()
|
|
except RuntimeError:
|
|
pass
|
|
v.value = True
|
|
return
|
|
|
|
def opt(self, mol, optFunc):
|
|
OPT_SLEEP_SEC = 0.2
|
|
MAX_OPT_SLEEP_SEC = 3
|
|
v = Value('b', False)
|
|
optProcess = Process(target=optFunc, args=(v, mol))
|
|
optProcess.start()
|
|
s = 0.0
|
|
while ((s < MAX_OPT_SLEEP_SEC) and (not v.value)):
|
|
s += OPT_SLEEP_SEC
|
|
sleep(OPT_SLEEP_SEC)
|
|
if (not v.value):
|
|
sys.stderr.write('Killing Minimize() or it will loop indefinitely\n')
|
|
optProcess.terminate()
|
|
optProcess.join()
|
|
return bool(v.value)
|
|
|
|
|
|
class TestCase(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
self.molB = """butane
|
|
RDKit 3D
|
|
butane
|
|
17 16 0 0 0 0 0 0 0 0999 V2000
|
|
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.4280 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.7913 -0.2660 0.9927 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.9040 1.3004 -0.3485 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.5407 2.0271 0.3782 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.5407 1.5664 -1.3411 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
3.3320 1.3004 -0.3485 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
3.6953 1.5162 -1.3532 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
3.8080 0.0192 0.0649 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
3.4447 -0.7431 -0.6243 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
3.4447 -0.1966 1.0697 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
4.8980 0.0192 0.0649 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
3.6954 2.0627 0.3408 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.7913 -0.7267 -0.7267 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.3633 0.7267 0.7267 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.3633 -0.9926 0.2660 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.3633 0.2660 -0.9926 H 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 1 0 0 0 0
|
|
1 15 1 0 0 0 0
|
|
1 16 1 0 0 0 0
|
|
1 17 1 0 0 0 0
|
|
2 3 1 0 0 0 0
|
|
2 4 1 0 0 0 0
|
|
2 14 1 0 0 0 0
|
|
4 5 1 0 0 0 0
|
|
4 6 1 0 0 0 0
|
|
4 7 1 0 0 0 0
|
|
7 8 1 0 0 0 0
|
|
7 9 1 0 0 0 0
|
|
7 13 1 0 0 0 0
|
|
9 10 1 0 0 0 0
|
|
9 11 1 0 0 0 0
|
|
9 12 1 0 0 0 0
|
|
M END"""
|
|
|
|
def testUFFMinInfLoop(self):
|
|
os = OptSafe()
|
|
m = Chem.MolFromMolBlock(os.minInfLoop)
|
|
self.assertTrue(m)
|
|
ok = False
|
|
try:
|
|
ok = os.opt(m, os.uffOptFunc)
|
|
except RuntimeError:
|
|
ok = True
|
|
pass
|
|
self.assertTrue(ok)
|
|
|
|
def testUFFDistanceConstraints(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(m)
|
|
self.assertTrue(ff)
|
|
ff.UFFAddDistanceConstraint(1, 3, False, 2.0, 2.0, 1.0e5)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
dist = rdMolTransforms.GetBondLength(conf, 1, 3)
|
|
self.assertTrue(dist > 1.99)
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(m)
|
|
self.assertTrue(ff)
|
|
ff.UFFAddDistanceConstraint(1, 3, True, -0.2, 0.2, 1.0e5)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
dist = rdMolTransforms.GetBondLength(conf, 1, 3)
|
|
self.assertTrue(dist > 1.79)
|
|
|
|
def testUFFAngleConstraints(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(m)
|
|
self.assertTrue(ff)
|
|
ff.UFFAddAngleConstraint(1, 3, 6, False, 90.0, 90.0, 100.0)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
angle = rdMolTransforms.GetAngleDeg(conf, 1, 3, 6)
|
|
self.assertAlmostEqual(angle, 90, delta=0.1)
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(m)
|
|
self.assertTrue(ff)
|
|
ff.UFFAddAngleConstraint(1, 3, 6, True, -10.0, 10.0, 100.0)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
angle = rdMolTransforms.GetAngleDeg(conf, 1, 3, 6)
|
|
self.assertAlmostEqual(angle, 100, delta=0.1)
|
|
|
|
def testUFFTorsionConstraints(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
conf = m.GetConformer()
|
|
rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, 15.0)
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(m)
|
|
self.assertTrue(ff)
|
|
ff.UFFAddTorsionConstraint(1, 3, 6, 8, False, 10.0, 20.0, 100.0)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8)
|
|
self.assertAlmostEqual(dihedral, 20, delta=0.1)
|
|
rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, -30.0)
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(m)
|
|
self.assertTrue(ff)
|
|
ff.UFFAddTorsionConstraint(1, 3, 6, 8, True, -10.0, 8.0, 100.0)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8)
|
|
self.assertAlmostEqual(dihedral, -40, delta=0.1)
|
|
rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, -10.0)
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(m)
|
|
self.assertTrue(ff)
|
|
ff.UFFAddTorsionConstraint(1, 3, 6, 8, False, -10.0, 8.0, 1.0e6)
|
|
r = ff.Minimize(500)
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8)
|
|
self.assertAlmostEqual(dihedral, -10, delta=0.1)
|
|
|
|
def testUFFPositionConstraints(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(m)
|
|
self.assertTrue(ff)
|
|
conf = m.GetConformer()
|
|
p = conf.GetAtomPosition(1)
|
|
ff.UFFAddPositionConstraint(1, 0.3, 1.0e5)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
q = conf.GetAtomPosition(1)
|
|
self.assertTrue((p - q).Length() < 0.3)
|
|
|
|
def testUFFFixedAtoms(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
ff = ChemicalForceFields.UFFGetMoleculeForceField(m)
|
|
self.assertTrue(ff)
|
|
conf = m.GetConformer()
|
|
fp = conf.GetAtomPosition(1)
|
|
ff.AddFixedPoint(1)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
fq = conf.GetAtomPosition(1)
|
|
self.assertTrue((fp - fq).Length() < 0.01)
|
|
|
|
def testMMFFMinInfLoop(self):
|
|
os = OptSafe()
|
|
m = Chem.MolFromMolBlock(os.minInfLoop)
|
|
self.assertTrue(m)
|
|
ok = False
|
|
try:
|
|
ok = os.opt(m, os.mmffOptFunc)
|
|
except RuntimeError:
|
|
ok = True
|
|
pass
|
|
self.assertTrue(ok)
|
|
|
|
def testMMFFDistanceConstraints(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
mp = ChemicalForceFields.MMFFGetMoleculeProperties(m)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp)
|
|
self.assertTrue(ff)
|
|
ff.MMFFAddDistanceConstraint(1, 3, False, 2.0, 2.0, 1.0e5)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
dist = rdMolTransforms.GetBondLength(conf, 1, 3)
|
|
self.assertTrue(dist > 1.99)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp)
|
|
self.assertTrue(ff)
|
|
ff.MMFFAddDistanceConstraint(1, 3, True, -0.2, 0.2, 1.0e5)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
dist = rdMolTransforms.GetBondLength(conf, 1, 3)
|
|
self.assertTrue(dist > 1.79)
|
|
|
|
def testMMFFAngleConstraints(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
mp = ChemicalForceFields.MMFFGetMoleculeProperties(m)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp)
|
|
self.assertTrue(ff)
|
|
ff.MMFFAddAngleConstraint(1, 3, 6, False, 90.0, 90.0, 100.0)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
angle = rdMolTransforms.GetAngleDeg(conf, 1, 3, 6)
|
|
self.assertAlmostEqual(angle, 90, delta=0.1)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp)
|
|
self.assertTrue(ff)
|
|
ff.MMFFAddAngleConstraint(1, 3, 6, True, -10.0, 10.0, 100.0)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
angle = rdMolTransforms.GetAngleDeg(conf, 1, 3, 6)
|
|
self.assertAlmostEqual(angle, 100, delta=0.1)
|
|
|
|
def testMMFFTorsionConstraints(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
conf = m.GetConformer()
|
|
rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, 15.0)
|
|
mp = ChemicalForceFields.MMFFGetMoleculeProperties(m)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp)
|
|
self.assertTrue(ff)
|
|
ff.MMFFAddTorsionConstraint(1, 3, 6, 8, False, 10.0, 20.0, 100.0)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8)
|
|
self.assertAlmostEqual(dihedral, 20, delta=0.1)
|
|
rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, -30.0)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp)
|
|
self.assertTrue(ff)
|
|
ff.MMFFAddTorsionConstraint(1, 3, 6, 8, True, -10.0, 8.0, 100.0)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8)
|
|
self.assertAlmostEqual(dihedral, -40, delta=0.1)
|
|
rdMolTransforms.SetDihedralDeg(conf, 1, 3, 6, 8, -10.0)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp)
|
|
self.assertTrue(ff)
|
|
ff.MMFFAddTorsionConstraint(1, 3, 6, 8, False, -10.0, 8.0, 100.0)
|
|
r = ff.Minimize(1000)
|
|
self.assertTrue(r == 0)
|
|
conf = m.GetConformer()
|
|
dihedral = rdMolTransforms.GetDihedralDeg(conf, 1, 3, 6, 8)
|
|
self.assertAlmostEqual(dihedral, -10, delta=0.1)
|
|
|
|
def testMMFFPositionConstraints(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
mp = ChemicalForceFields.MMFFGetMoleculeProperties(m)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp)
|
|
self.assertTrue(ff)
|
|
conf = m.GetConformer()
|
|
p = conf.GetAtomPosition(1)
|
|
ff.MMFFAddPositionConstraint(1, 0.3, 1.0e5)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
q = conf.GetAtomPosition(1)
|
|
self.assertTrue((p - q).Length() < 0.3)
|
|
|
|
def testMMFFFixedAtoms(self):
|
|
m = Chem.MolFromMolBlock(self.molB, True, False)
|
|
mp = ChemicalForceFields.MMFFGetMoleculeProperties(m)
|
|
ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp)
|
|
self.assertTrue(ff)
|
|
conf = m.GetConformer()
|
|
fp = conf.GetAtomPosition(1)
|
|
ff.AddFixedPoint(1)
|
|
r = ff.Minimize()
|
|
self.assertTrue(r == 0)
|
|
fq = conf.GetAtomPosition(1)
|
|
self.assertTrue((fp - fq).Length() < 0.01)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|