def test3MultiConf(self): mol = Chem.MolFromSmiles("CC(C)(C)c(cc12)n[n]2C(=O)/C=C(N1)/COC") cids = rdDistGeom.EmbedMultipleConfs(mol, 10, maxAttempts=30, randomSeed=100, useExpTorsionAnglePrefs=False, useBasicKnowledge=False) energies = [115.460, 105.891, 109.868, 104.415, 92.944, 140.917, 139.468, 95.081, 123.528, 107.885] nenergies = [] for cid in cids: ff = ChemicalForceFields.UFFGetMoleculeForceField(mol, 10.0, cid) ee = ff.CalcEnergy() nenergies.append(ee) #print(['%.2f' % x for x in nenergies]) # print(nenergies) self.assertTrue(lstEq(energies, nenergies, tol=1e-2))
def test3MultiConf(self): mol = Chem.MolFromSmiles("CC(C)(C)c(cc12)n[n]2C(=O)/C=C(N1)/COC") cids = rdDistGeom.EmbedMultipleConfs(mol, 10, maxAttempts=30, randomSeed=100, useExpTorsionAnglePrefs=False, useBasicKnowledge=False) energies = [116.330, 106.246, 109.816, 104.890, 93.060, 140.803, 139.253, 95.820, 123.591, 108.655] nenergies = [] for cid in cids: ff = ChemicalForceFields.UFFGetMoleculeForceField(mol, 10.0, cid) ee = ff.CalcEnergy() nenergies.append(ee) # print(['%.3f' % x for x in nenergies]) # print(nenergies) self.assertTrue(lstEq(energies, nenergies, tol=1e-2))
def test7(self) : molB = """ 4 4 0 0 0 0 0 0 0 0999 V2000 -0.8500 0.4512 -0.6671 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.3307 -0.9436 -0.3641 C 0 0 0 0 0 0 0 0 0 0 0 0 0.6796 -0.4074 0.5894 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5011 0.8998 -0.1231 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 2 3 1 0 3 4 1 0 1 4 1 0 M END""" m = Chem.MolFromMolBlock(molB) mp = ChemicalForceFields.MMFFGetMoleculeProperties(m) ff = ChemicalForceFields.MMFFGetMoleculeForceField(m, mp) self.failUnless(ff) e1 = ff.CalcEnergy() r = ff.Minimize() self.failUnless(r == 0) e2 = ff.CalcEnergy() self.failUnless(e2 < e1);
def test9(self) : m = Chem.MolFromSmiles('c1ccccc1CCNN') m = Chem.AddHs(m) mp = ChemicalForceFields.MMFFGetMoleculeProperties(m) mmffBondStretchParams = mp.GetMMFFBondStretchParams(m, 6, 7) self.failUnless(mmffBondStretchParams) self.failUnless((mmffBondStretchParams[0] == 0) and (int(round(mmffBondStretchParams[1] * 1000) == 4258)) and (int(round(mmffBondStretchParams[2] * 1000) == 1508))); mmffBondStretchParams = mp.GetMMFFBondStretchParams(m, 0, 7) self.failIf(mmffBondStretchParams) mmffAngleBendParams = mp.GetMMFFAngleBendParams(m, 6, 7, 8) self.failUnless(mmffAngleBendParams) self.failUnless((mmffAngleBendParams[0] == 0) and (int(round(mmffAngleBendParams[1] * 1000) == 777)) and (int(round(mmffAngleBendParams[2] * 1000) == 108290))); mmffAngleBendParams = mp.GetMMFFAngleBendParams(m, 0, 7, 8) self.failIf(mmffAngleBendParams) mmffStretchBendParams = mp.GetMMFFStretchBendParams(m, 6, 7, 8) self.failUnless(mmffStretchBendParams) self.failUnless((mmffStretchBendParams[0] == 0) and (int(round(mmffStretchBendParams[1] * 1000) == 136)) and (int(round(mmffStretchBendParams[2] * 1000) == 282))); mmffStretchBendParams = mp.GetMMFFStretchBendParams(m, 0, 7, 8) self.failIf(mmffStretchBendParams) mmffTorsionParams = mp.GetMMFFTorsionParams(m, 6, 7, 8, 9) self.failUnless(mmffTorsionParams) self.failUnless((mmffTorsionParams[0] == 0) and (int(round(mmffTorsionParams[1] * 1000) == 0)) and (int(round(mmffTorsionParams[2] * 1000) == -300)) and (int(round(mmffTorsionParams[3] * 1000) == 500))) mmffTorsionParams = mp.GetMMFFTorsionParams(m, 0, 7, 8, 9) self.failIf(mmffTorsionParams) mmffOopBendParams = mp.GetMMFFOopBendParams(m, 6, 5, 4, 0) self.failUnless(mmffOopBendParams) self.failUnless(int(round(mmffOopBendParams * 1000)) == 40) mmffOopBendParams = mp.GetMMFFOopBendParams(m, 6, 5, 4, 1) self.failIf(mmffOopBendParams) sub1 = m.GetSubstructMatch(Chem.MolFromSmarts('NN[H]')) self.failUnless(len(sub1) == 3) nIdx = sub1[0]; hIdx = sub1[2]; mmffVdWParams = mp.GetMMFFVdWParams(nIdx, hIdx) self.failUnless(mmffVdWParams) self.failUnless((int(round(mmffVdWParams[0] * 1000)) == 3321) and (int(round(mmffVdWParams[1] * 1000)) == 34) and (int(round(mmffVdWParams[2] * 1000)) == 2657) and (int(round(mmffVdWParams[3] * 1000)) == 17))
def get_epsilon_sigma_mmff(m1, m2): n1 = m1.GetNumAtoms() n2 = m2.GetNumAtoms() vdw_epsilon, vdw_sigma = np.zeros((n1, n2)), np.zeros((n1, n2)) m_combine = CombineMols(m1, m2) mp = ChemicalForceFields.MMFFGetMoleculeProperties(m_combine) for i1 in range(n1): for i2 in range(n2): param = mp.GetMMFFVdWParams(i1, i1 + i2) if param is None: continue d, e, _, _ = param vdw_epsilon[i1, i2] = e vdw_sigma[i1, i2] = d # print (i1, i2, e, d) return vdw_epsilon, vdw_sigma
def test10(self): m = Chem.MolFromSmiles('c1ccccc1CCNN') m = Chem.AddHs(m) uffBondStretchParams = ChemicalForceFields.GetUFFBondStretchParams( m, 6, 7) self.assertTrue(uffBondStretchParams) self.assertTrue( (int(round(uffBondStretchParams[0] * 1000) == 699592)) and (int(round(uffBondStretchParams[1] * 1000) == 1514))) uffBondStretchParams = ChemicalForceFields.GetUFFBondStretchParams( m, 0, 7) self.assertFalse(uffBondStretchParams) uffAngleBendParams = ChemicalForceFields.GetUFFAngleBendParams( m, 6, 7, 8) self.assertTrue(uffAngleBendParams) self.assertTrue( (int(round(uffAngleBendParams[0] * 1000) == 303297)) and (int(round(uffAngleBendParams[1] * 1000) == 109470))) uffAngleBendParams = ChemicalForceFields.GetUFFAngleBendParams( m, 0, 7, 8) self.assertFalse(uffAngleBendParams) uffTorsionParams = ChemicalForceFields.GetUFFTorsionParams( m, 6, 7, 8, 9) self.assertTrue(uffTorsionParams) self.assertTrue((int(round(uffTorsionParams * 1000) == 976))) uffTorsionParams = ChemicalForceFields.GetUFFTorsionParams( m, 0, 7, 8, 9) self.assertFalse(uffTorsionParams) uffInversionParams = ChemicalForceFields.GetUFFInversionParams( m, 6, 5, 4, 0) self.assertTrue(uffInversionParams) self.assertTrue(int(round(uffInversionParams * 1000)) == 2000) uffInversionParams = ChemicalForceFields.GetUFFInversionParams( m, 6, 5, 4, 1) self.assertFalse(uffInversionParams) uffVdWParams = ChemicalForceFields.GetUFFVdWParams(m, 0, 9) self.assertTrue(uffVdWParams) self.assertTrue((int(round(uffVdWParams[0] * 1000)) == 3754) and (int(round(uffVdWParams[1] * 1000)) == 85))
def test3MultiConf(self): mol = Chem.MolFromSmiles("CC(C)(C)c(cc12)n[n]2C(=O)/C=C(N1)/COC") cids = rdDistGeom.EmbedMultipleConfs(mol, 10, maxAttempts=30, randomSeed=100) energies = [ 112.98, 103.57, 110.78, 100.40, 95.37, 101.64, 114.72, 112.65, 124.53, 107.50 ] nenergies = [] for cid in cids: ff = ChemicalForceFields.UFFGetMoleculeForceField(mol, 10.0, cid) ee = ff.CalcEnergy() nenergies.append(ee) #print(['%.2f'%x for x in nenergies]) #print(nenergies) self.assertTrue(lstEq(energies, nenergies, tol=1e-2))
def test3MultiConf(self): mol = Chem.MolFromSmiles("CC(C)(C)c(cc12)n[n]2C(=O)/C=C(N1)/COC") cids = rdDistGeom.EmbedMultipleConfs(mol, 10, maxAttempts=30, randomSeed=100) energies = [ 90.05, 77.35, 91.45, 81.82, 81.60, 75.65, 86.50, 80.35, 80.55, 73.73 ] nenergies = [] for cid in cids: ff = ChemicalForceFields.UFFGetMoleculeForceField(mol, 10.0, cid) ee = ff.CalcEnergy() nenergies.append(ee) #print ['%.2f'%x for x in nenergies] #print nenergies self.failUnless(lstEq(energies, nenergies, tol=1e-2))
def test2(self): fName = os.path.join(self.dirName, 'benzene.mol') m = Chem.MolFromMolFile(fName) ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.assertTrue(ff) e1 = ff.CalcEnergy() r = ff.Minimize() self.assertTrue(r == 0) e2 = ff.CalcEnergy() self.assertTrue(e2 < e1) # test keyword args: r = ff.Minimize(forceTol=1e-8) self.assertTrue(r == 0) # test keyword args: r = ff.Minimize(energyTol=1e-3) self.assertTrue(r == 0)
def test4AlignConfs(self): mol = Chem.MolFromSmiles('C1CC1CNc(n2)nc(C)cc2Nc(cc34)ccc3[nH]nc4') cids = rdDistGeom.EmbedMultipleConfs(mol, 10, 30, 100) #writer = Chem.SDWriter('mol_899.sdf') for cid in cids: ff = ChemicalForceFields.UFFGetMoleculeForceField(mol, confId=cid) ff.Initialize() more = 1 while more: more = ff.Minimize() # FIX: this should not be necessary but somehow more comes out to be 0 # even with the structure still being crappy ff.Minimize() aids = [12, 13, 14, 15, 16, 17, 18] rdMolAlign.AlignMolConformers(mol, aids) # now test that the atom location of these atom are consistent confs = mol.GetConformers() for aid in aids: mpos = 0 for i, conf in enumerate(confs): if (i == 0): mpos = list(conf.GetAtomPosition(aid)) continue else: pos = list(conf.GetAtomPosition(aid)) self.assertTrue(lstFeq(mpos, pos, .5)) # now test that we can get a list of RMS values rmsvals = [] rdMolAlign.AlignMolConformers(mol, aids, RMSlist=rmsvals) self.assertTrue((len(rmsvals) == mol.GetNumConformers() - 1)) # make sure something sensible happens if we provide a stupid # argument: rmsvals = 4 self.assertRaises(AttributeError, rdMolAlign.AlignMolConformers, mol, atomIds=aids, RMSlist=rmsvals)
def from_mol_to_array(mol): """ Parameters ---------- mol : rdkit.Mol must have 3D conformer Returns gs_charge : list atom_type : list pos : list of list (N*3) ------- """ try: if mol: # initialization gs_charge, atom_type, pos = [], [], [] mmff_prop = ChemicalForceFields.MMFFGetMoleculeProperties(mol) AllChem.ComputeGasteigerCharges(mol) # get charge, atom type, 3D coordinates for i in range(mol.GetNumAtoms()): # get charge gs_charge_i = float( mol.GetAtomWithIdx(i).GetProp('_GasteigerCharge')) # get atom type atom_type_i = mmff_prop.GetMMFFAtomType(i) - 1 # get coordinate pos_i = mol.GetConformer().GetAtomPosition(i) pos_x_i, pos_y_i, pos_z_i = pos_i.x, pos_i.y, pos_i.z gs_charge.append(gs_charge_i) atom_type.append(atom_type_i) pos.append([pos_x_i, pos_y_i, pos_z_i]) return gs_charge, atom_type, pos else: return None except: return None
def test12(self): self.dirName = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'ForceFieldHelpers', 'UFF', 'test_data') fName = os.path.join(self.dirName, 'Issue239.mol') m = Chem.MolFromMolFile(fName) self.assertIsNotNone(m) ff = ChemicalForceFields.UFFGetMoleculeForceField(m) ff.Initialize() positions = ff.Positions() savedPos = list(positions) e1 = ff.CalcEnergy() ff.Minimize(10000, 1.0e-6, 1.0e-3) e2 = ff.CalcEnergy() self.assertTrue(e2 < e1) e3 = ff.CalcEnergy(savedPos) self.assertAlmostEqual(e3, e1, 2) savedPos = tuple(positions) e3 = ff.CalcEnergy(savedPos) self.assertAlmostEqual(e3, e1, 2) savedPos = tuple(numpy.array(savedPos)) e3 = ff.CalcEnergy(savedPos) self.assertAlmostEqual(e3, e1, 2)
def test14(self): self.dirName = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'ForceFieldHelpers', 'UFF', 'test_data') fName = os.path.join(self.dirName, 'Issue239.mol') m = Chem.MolFromMolFile(fName) self.assertIsNotNone(m) ff = ChemicalForceFields.UFFGetMoleculeForceField(m) ff.Initialize() positions = ff.Positions() savedPos = list(positions) grad1 = ff.CalcGrad() for v in grad1: self.assertNotAlmostEqual(v, 0.0, 3) ff.Minimize(10000, 1.0e-6, 1.0e-3) grad2 = ff.CalcGrad() for v in grad2: self.assertAlmostEqual(v, 0.0, 3) ff.Initialize() grad2 = ff.CalcGrad(savedPos) self.assertEqual(len(grad1), len(grad2)) for i in range(len(grad1)): self.assertAlmostEqual(grad1[i], grad2[i], 3)
def test3(self): molB = """ 4 4 0 0 0 0 0 0 0 0999 V2000 -0.8500 0.4512 -0.6671 C 0 0 0 0 0 0 0 0 0 0 0 0 -0.3307 -0.9436 -0.3641 C 0 0 0 0 0 0 0 0 0 0 0 0 0.6796 -0.4074 0.5894 C 0 0 0 0 0 0 0 0 0 0 0 0 0.5011 0.8998 -0.1231 C 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 2 3 1 0 3 4 1 0 1 4 1 0 M END""" m = Chem.MolFromMolBlock(molB) ff = ChemicalForceFields.UFFGetMoleculeForceField(m) self.assertTrue(ff) e1 = ff.CalcEnergy() r = ff.Minimize() self.assertTrue(r == 0) e2 = ff.CalcEnergy() self.assertTrue(e2 < e1)
def update_atom_position(mol1, mol2): mol_copy = Chem.Mol(mol2) # This is a work-around to get a seedSmarts for the FMCS algorithm # and prevent the occassional hanging of FMCS # Might be unnecessary with future versions of rdkit core_frags = BRICS.BRICSDecompose(Chem.RemoveHs(mol1)) frag_smarts = [] for frag in enumerate(core_frags): smi_str = (re.sub('[[1-9][0-9]{0,2}\*]', '[*]', frag[1])) frag_smarts.append( Chem.MolToSmarts(Chem.MolFromSmiles(smi_str)).replace( ':', '~').replace('-', '~').replace('=', '~').replace('#0', '*')) seed = None for query in frag_smarts: if mol_copy.HasSubstructMatch(Chem.MolFromSmarts(query)): seed = query break # Now get MCSS res = rdFMCS.FindMCS([mol1, mol_copy], seedSmarts=seed) mcs_q = Chem.MolFromSmarts(res.smartsString) # Get atom IDs template = mol1.GetSubstructMatches(mcs_q)[0] hit_atom = mol_copy.GetSubstructMatches(mcs_q)[0] # Update XYZ coords of MCSS running_distance = 0 for i in range(0, len(template)): origin = mol1.GetConformer().GetAtomPosition(template[i]) pos = mol_copy.GetConformer().GetAtomPosition(hit_atom[i]) p1 = np.array([origin.x, origin.y, origin.z]) p2 = np.array([pos.x, pos.y, pos.z]) sq_dist = np.sum((p1 - p2)**2, axis=0) dist = np.sqrt(sq_dist) running_distance += dist mol_copy.GetConformer().SetAtomPosition(hit_atom[i], (origin.x, origin.y, origin.z)) if running_distance > 0.1: # relax atoms outside MCSS res_atom = [] for atom in mol_copy.GetAtoms(): if atom.GetIdx() not in hit_atom: res_atom.append(atom.GetIdx()) # do minimization mp = ChemicalForceFields.MMFFGetMoleculeProperties(mol_copy) ff = ChemicalForceFields.MMFFGetMoleculeForceField(mol_copy, mp) for val in hit_atom: ff.AddFixedPoint(val) for val in res_atom: ff.MMFFAddPositionConstraint(val, 1, 5) ff.Minimize() return mol_copy
def scan_torsion(resolution, unique_conformers=[]): """ """ # Load the molecule sdf_filename = "sdf/pentane.sdf" suppl = Chem.SDMolSupplier(sdf_filename, removeHs=False, sanitize=True) mol = next(suppl) # Get molecule information # n_atoms = mol.GetNumAtoms() atoms = mol.GetAtoms() # atoms = [atom.GetAtomicNum() for atom in atoms] atoms = [atom.GetSymbol() for atom in atoms] # Origin conformer = mol.GetConformer() origin = conformer.GetPositions() origin -= rmsd.centroid(origin) # Dihedral angle a = 0 b = 1 c = 5 d = 8 # Origin angle origin_angle = Chem.rdMolTransforms.GetDihedralDeg(conformer, a, b, c, d) # Setup forcefield mp = ChemicalForceFields.MMFFGetMoleculeProperties(mol) ff = ChemicalForceFields.MMFFGetMoleculeForceField(mol, mp) # Define all angles to scan angles = get_angles(resolution) debug_file = "test.xyz" debug_file = open(debug_file, 'a+') if len(unique_conformers) == 0: xyz = rmsd.calculate_rmsd.set_coordinates(atoms, origin) debug_file.write(xyz) debug_file.write("\n") unique_conformers = [origin] for angle in angles: # Reset position for i, pos in enumerate(origin): conformer.SetAtomPosition(i, pos) # Set clockwork angle Chem.rdMolTransforms.SetDihedralDeg(conformer, a, b, c, d, origin_angle + angle) # Setup constrained ff ffc = ChemicalForceFields.MMFFGetMoleculeForceField(mol, mp) ffc.MMFFAddTorsionConstraint(a, b, c, d, False, origin_angle + angle, origin_angle + angle, 1.0e10) ffc.Minimize(maxIts=1000, energyTol=1e-2, forceTol=1e-3) # angle1 = Chem.rdMolTransforms.GetDihedralDeg(conformer, a, b, c, d) ff.Minimize(maxIts=1000, energyTol=1e-2, forceTol=1e-4) # angle2 = Chem.rdMolTransforms.GetDihedralDeg(conformer, a, b, c, d) pos = conformer.GetPositions() pos -= rmsd.centroid(pos) print("debug", len(unique_conformers)) unique = compare_positions(pos, unique_conformers) if not unique: continue pos = align(pos, origin) unique_conformers.append(pos) xyz = rmsd.calculate_rmsd.set_coordinates(atoms, pos) debug_file.write(xyz) debug_file.write("\n") print(angle, unique) debug_file.close() return unique_conformers
def calculate_mopac(molobj, conformer, torsions, origin_angles, delta_angles, delta=10**-7, coord_decimals=6, atoms=None, ffprop=None, reference_smiles=None): sdfstr = cheminfo.molobj_to_sdfstr(molobj) molobj_prime, status = cheminfo.sdfstr_to_molobj(sdfstr) conformer_prime = molobj_prime.GetConformer() # Setup constrained forcefield # ffprop_prime, ffc = get_forcefield(molobj_prime) ffc = ChemicalForceFields.MMFFGetMoleculeForceField(molobj_prime, ffprop) # Set angles and constrains for all torsions for i, angle in enumerate(delta_angles): set_angle = origin_angles[i] + angle # Set clockwork angle try: Chem.rdMolTransforms.SetDihedralDeg(conformer_prime, *torsions[i], set_angle) except: pass # Set forcefield constrain ffc.MMFFAddTorsionConstraint(*torsions[i], False, set_angle-delta, set_angle+delta, 1.0e10) # minimize constrains status = run_forcefield(ffc, 500) # Set result coordinates = conformer_prime.GetPositions() coordinates = np.round(coordinates, coord_decimals) # rdkit hack, read description smiles = "" try: energy, ocoordinates = quantum.optmize_conformation(atoms, coordinates) status = 0 coordinates = ocoordinates if reference_smiles is not None: new_smiles = quantum.get_smiles(atoms, coordinates) smiles = new_smiles if new_smiles != reference_smiles: status = 5 except: energy = 0.0 status = 4 # if status == 0: # atoms_str = [cheminfo.convert_atom(atom) for atom in atoms] # txt = rmsd.set_coordinates(atoms_str, coordinates, title="") # with open("_tmp_local_dump.xyz", 'a') as f: # f.write(txt) # f.write("\n") # # print(status, smiles) return energy, coordinates, status
def get_forcefield(molobj): ffprop = ChemicalForceFields.MMFFGetMoleculeProperties(molobj) forcefield = ChemicalForceFields.MMFFGetMoleculeForceField(molobj, ffprop) # 0.01 overhead return ffprop, forcefield
def calculate_forcefield(molobj, conformer, torsions, origin_angles, delta_angles, ffprop=None, ff=None, delta=10**-7, coord_decimals=6, grad_threshold=100): """ Disclaimer: lots of hacks, sorry. Let me know if you have an alternative. Note: There is a artificat where if delta < 10**-16 the FF will find a *extremely* local minima with very high energy (un-physical)the FF will find a *extremely* local minima with very high energy (un-physical). Setting delta to 10**-6 (numerical noise) should fix this. Note: rdkit forcefield restrained optimization will optimized to a *very* local and very unphysical minima which the global optimizer cannot get out from. Truncating the digits of the coordinates to six is a crude but effective way to slight move the the molecule out of this in a reproducable way. """ if ffprop is None or ff is None: ffprop, ff = get_forcefield(molobj) sdfstr = cheminfo.molobj_to_sdfstr(molobj) molobj_prime, status = cheminfo.sdfstr_to_molobj(sdfstr) conformer_prime = molobj_prime.GetConformer() # Setup constrained forcefield # ffprop_prime, ffc = get_forcefield(molobj_prime) ffc = ChemicalForceFields.MMFFGetMoleculeForceField(molobj_prime, ffprop) # Set angles and constrains for all torsions for i, angle in enumerate(delta_angles): set_angle = origin_angles[i] + angle # Set clockwork angle try: Chem.rdMolTransforms.SetDihedralDeg(conformer_prime, *torsions[i], set_angle) except: pass # Set forcefield constrain ffc.MMFFAddTorsionConstraint(*torsions[i], False, set_angle-delta, set_angle+delta, 1.0e10) # minimize constrains status = run_forcefield(ffc, 500) # Set result coordinates = conformer_prime.GetPositions() coordinates = np.round(coordinates, coord_decimals) # rdkit hack, read description cheminfo.conformer_set_coordinates(conformer, coordinates) # minimize global status = run_forcefield_prime(ff, 700, force=1e-4) # Get current energy energy = ff.CalcEnergy() if status == 0: grad = ff.CalcGrad() grad = np.array(grad) grad_norm = linalg.norm(grad) if grad_norm > grad_threshold: status = 4 debug = False if energy > 1000 and debug: print(torsions, origin_angles, delta_angles) print(energy, status) print("id") print(id(molobj_prime)) print(id(molobj)) molobj_test, status = cheminfo.sdfstr_to_molobj(sdfstr) coordinates = conformer.GetPositions() cheminfo.molobj_set_coordinates(molobj_test, coordinates) ffprop_t, ff_t = get_forcefield(molobj) run_forcefield(ff_t, 500) print(coordinates) for idxs in torsions: angle = Chem.rdMolTransforms.GetDihedralDeg(conformer, *idxs) print("ANGLE 1", angle) f = open("_test_dumpsdf.sdf", 'w') sdf = cheminfo.save_molobj(molobj) f.write(sdf) # prop, ff = get_forcefield(molobj) # status = run_forcefield(ff, 500) conformer = molobj_test.GetConformer() for idxs in torsions: angle = Chem.rdMolTransforms.GetDihedralDeg(conformer, *idxs) print("ANGLE 2",angle) print(energy, status) sdf = cheminfo.save_molobj(molobj_test) f.write(sdf) f.close() quit() # Get current positions pos = conformer.GetPositions() return energy, pos, status
def test4(self): m = Chem.MolFromSmiles('[Cu](C)(C)(C)(C)C') self.assertFalse(ChemicalForceFields.UFFHasAllMoleculeParams(m)) m = Chem.MolFromSmiles('C(C)(C)(C)C') self.assertTrue(ChemicalForceFields.UFFHasAllMoleculeParams(m))
def testAddConformersFromTrajectory(self): molBlock = \ '\n' \ ' RDKit 3D\n' \ '\n' \ ' 71 74 0 0 0 0 0 0 0 0999 V2000\n' \ ' 8.2543 3.1901 -0.3005 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 7.4558 1.9712 0.0938 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 7.3934 1.0441 -0.9483 O 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 6.6660 -0.0533 -0.4641 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 5.1928 0.2346 -0.4609 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 4.3713 -0.9410 -0.5770 N 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 3.1852 -1.0034 -1.2291 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 2.2914 0.1276 -1.6316 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 0.9308 -0.4468 -1.9908 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 0.1417 -0.7821 -0.7545 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -0.1848 0.3695 0.0456 N 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -1.5661 0.7686 -0.0745 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -2.4768 -0.0640 0.8206 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -3.8874 0.1143 0.3941 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -4.6333 -0.9984 0.0264 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -6.0127 -0.9516 -0.0400 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -6.7062 0.1599 0.3963 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -8.0408 0.4828 -0.1977 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -7.7914 1.1180 -1.5591 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -8.7622 1.4403 0.7265 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -8.8409 -0.7397 -0.4395 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -8.9121 -1.6637 0.4258 O 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -9.7414 -0.7636 -1.5059 O 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -5.9736 1.2357 0.8565 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -4.5843 1.2252 0.8530 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 0.6263 1.4884 -0.3942 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 2.0541 1.0258 -0.4230 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 2.9225 -2.3317 -1.2963 N 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 3.6061 -2.9745 -0.3180 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 3.3554 -4.1536 0.3735 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 3.7653 -4.2712 1.6948 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 4.8254 -3.4613 2.0796 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 5.1978 -2.3436 1.3419 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 4.5694 -2.0799 0.1305 C 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 9.3138 3.1372 0.0031 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 7.8117 4.0754 0.1798 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 8.2358 3.3535 -1.4074 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 6.4027 2.2146 0.3634 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 7.9270 1.5444 1.0040 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 7.0677 -0.2415 0.5615 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 6.9530 -0.9105 -1.1025 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 4.9578 0.7259 0.5137 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 4.9985 0.9430 -1.3033 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 2.7171 0.7264 -2.4494 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 0.3994 0.2339 -2.6810 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 1.1342 -1.4171 -2.5076 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -0.7632 -1.3370 -1.0391 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 0.7845 -1.4394 -0.1311 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 0.0125 0.1989 1.0673 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -1.6672 1.8215 0.2925 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -1.8705 0.7271 -1.1337 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -2.3045 0.3159 1.8590 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -2.1980 -1.1367 0.7635 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -4.1513 -1.9468 -0.2114 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -6.6138 -1.7460 -0.4718 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -7.0727 0.4399 -2.0858 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -7.3144 2.1076 -1.4482 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -8.7609 1.1720 -2.1135 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -8.3137 2.4504 0.5729 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -8.6170 1.0817 1.7580 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -9.8244 1.4444 0.4200 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -6.4629 2.0541 1.3719 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' -4.0445 2.0563 1.3058 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 0.3329 1.8224 -1.3991 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 0.4920 2.3164 0.3160 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 2.2025 0.3766 0.4766 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 2.7945 1.8369 -0.3969 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 2.4404 -4.6964 0.1303 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 3.3157 -5.0055 2.3587 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 5.4272 -3.7654 2.9380 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 5.5668 -1.5069 1.9380 H 0 0 0 0 0 0 0 0 0 0 0 0\n' \ ' 1 2 1 0\n' \ ' 2 3 1 0\n' \ ' 3 4 1 0\n' \ ' 4 5 1 0\n' \ ' 5 6 1 0\n' \ ' 6 7 1 0\n' \ ' 7 8 1 0\n' \ ' 8 9 1 0\n' \ ' 9 10 1 0\n' \ ' 10 11 1 0\n' \ ' 11 12 1 0\n' \ ' 12 13 1 0\n' \ ' 13 14 1 0\n' \ ' 14 15 2 0\n' \ ' 15 16 1 0\n' \ ' 16 17 2 0\n' \ ' 17 18 1 0\n' \ ' 18 19 1 0\n' \ ' 18 20 1 0\n' \ ' 18 21 1 0\n' \ ' 21 22 2 0\n' \ ' 21 23 1 0\n' \ ' 17 24 1 0\n' \ ' 24 25 2 0\n' \ ' 11 26 1 0\n' \ ' 26 27 1 0\n' \ ' 7 28 2 0\n' \ ' 28 29 1 0\n' \ ' 29 30 2 0\n' \ ' 30 31 1 0\n' \ ' 31 32 2 0\n' \ ' 32 33 1 0\n' \ ' 33 34 2 0\n' \ ' 34 6 1 0\n' \ ' 27 8 1 0\n' \ ' 34 29 1 0\n' \ ' 25 14 1 0\n' \ ' 1 35 1 0\n' \ ' 1 36 1 0\n' \ ' 1 37 1 0\n' \ ' 2 38 1 0\n' \ ' 2 39 1 0\n' \ ' 4 40 1 0\n' \ ' 4 41 1 0\n' \ ' 5 42 1 0\n' \ ' 5 43 1 0\n' \ ' 8 44 1 0\n' \ ' 9 45 1 0\n' \ ' 9 46 1 0\n' \ ' 10 47 1 0\n' \ ' 10 48 1 0\n' \ ' 11 49 1 0\n' \ ' 12 50 1 0\n' \ ' 12 51 1 0\n' \ ' 13 52 1 0\n' \ ' 13 53 1 0\n' \ ' 15 54 1 0\n' \ ' 16 55 1 0\n' \ ' 19 56 1 0\n' \ ' 19 57 1 0\n' \ ' 19 58 1 0\n' \ ' 20 59 1 0\n' \ ' 20 60 1 0\n' \ ' 20 61 1 0\n' \ ' 24 62 1 0\n' \ ' 25 63 1 0\n' \ ' 26 64 1 0\n' \ ' 26 65 1 0\n' \ ' 27 66 1 0\n' \ ' 27 67 1 0\n' \ ' 30 68 1 0\n' \ ' 31 69 1 0\n' \ ' 32 70 1 0\n' \ ' 33 71 1 0\n' \ 'M CHG 2 11 1 23 -1\n' \ 'M END\n' mol = Chem.MolFromMolBlock(molBlock, removeHs=False) everySteps = 10 maxIts = 1000 gradTol = 0.01 rdbase = os.environ['RDBASE'] fName = os.path.join(rdbase, 'Code', 'GraphMol', 'Wrap', 'test_data', 'bilastine_trajectory.sdf') w = Chem.SDWriter(fName) field = ChemicalForceFields.MMFFGetMoleculeForceField( mol, ChemicalForceFields.MMFFGetMoleculeProperties(mol)) (res, sv) = field.MinimizeTrajectory(everySteps, maxIts, gradTol) self.assertEqual(res, 0) traj = Trajectory(3, mol.GetNumAtoms(), sv) mol.RemoveConformer(0) traj.AddConformersToMol(mol) for nConf in range(mol.GetNumConformers()): mol.SetProp('ENERGY', '{0:.4f}'.format(traj.GetSnapshot(nConf).GetEnergy())) w.write(mol, nConf) w.close() traj.Clear() n1 = mol.GetNumConformers() traj.AddConformersToMol(mol) n2 = mol.GetNumConformers() self.assertEqual(n1, n2) # GetSnapshot should raise exception after Clear() e = False try: traj.GetSnapshot(0) except: e = True self.assertTrue(e)
def test4(self): m = Chem.MolFromSmiles('[Cu](C)(C)(C)(C)C') self.failIf(ChemicalForceFields.UFFHasAllMoleculeParams(m)) m = Chem.MolFromSmiles('C(C)(C)(C)C') self.failUnless(ChemicalForceFields.UFFHasAllMoleculeParams(m))
def get_conformation(mol, res, torsions): """ param: rdkit mol clockwork resolutions torsions indexes return unique conformations """ # Load mol info n_torsions = len(torsions) # init energy energies = [] states = [] # no constraints ffprop, forcefield = get_forcefield(mol) # Get conformer and origin conformer = mol.GetConformer() origin = conformer.GetPositions() # TODO origin -= rmsd.centroid(origin) # Origin angle origin_angles = [] # type of idxs torsions = [[int(y) for y in x] for x in torsions] for idxs in torsions: angle = Chem.rdMolTransforms.GetDihedralDeg(conformer, *idxs) origin_angles.append(angle) # Axis holder axis_pos = [] # Get resolution angles angle_iterator = get_angles(res, n_torsions) for angles in angle_iterator: # Reset positions for i, pos in enumerate(origin): conformer.SetAtomPosition(i, pos) # Setup constrained forcefield ffc = ChemicalForceFields.MMFFGetMoleculeForceField(mol, ffprop) # Set angles and constrains for all torsions for i, angle in enumerate(angles): set_angle = origin_angles[i] + angle # Set clockwork angle try: Chem.rdMolTransforms.SetDihedralDeg(conformer, *torsions[i], set_angle) except: pass # Set forcefield constrain ffc.MMFFAddTorsionConstraint(*torsions[i], False, set_angle, set_angle, 1.0e10) # minimize constrains status = run_forcefield(ffc, 500) # minimize global status = run_forcefield2(forcefield, 700, force=1e-4) # Get current energy energy = forcefield.CalcEnergy() # Get current positions pos = conformer.GetPositions() axis_pos += [pos] energies += [energy] states += [status] return energies, axis_pos, states
def OptimizeMol(mol, bm, atomMatches=None, excludedVolumes=None, forceConstant=1200.0, maxPasses=5, verbose=False): """ carries out a UFF optimization for a molecule optionally subject to the constraints in a bounds matrix - atomMatches, if provided, is a sequence of sequences - forceConstant is the force constant of the spring used to enforce the constraints returns a 2-tuple: 1) the energy of the initial conformation 2) the energy post-embedding NOTE that these energies include the energies of the constraints >>> m = Chem.MolFromSmiles('OCCN') >>> feats = [ChemicalFeatures.FreeChemicalFeature('HBondAcceptor', 'HAcceptor1', Geometry.Point3D(0.0, 0.0, 0.0)), ... ChemicalFeatures.FreeChemicalFeature('HBondDonor', 'HDonor1', Geometry.Point3D(2.65, 0.0, 0.0)), ... ] >>> pcophore=Pharmacophore.Pharmacophore(feats) >>> pcophore.setLowerBound(0,1, 2.5) >>> pcophore.setUpperBound(0,1, 2.8) >>> atomMatch = ((0,),(3,)) >>> bm,embeds,nFail = EmbedPharmacophore(m,atomMatch,pcophore,randomSeed=23,silent=1) >>> len(embeds) 10 >>> testM = embeds[0] Do the optimization: >>> e1,e2 = OptimizeMol(testM,bm,atomMatches=atomMatch) Optimizing should have lowered the energy: >>> e2 < e1 True Check the constrained distance: >>> conf = testM.GetConformer(0) >>> p0 = conf.GetAtomPosition(0) >>> p3 = conf.GetAtomPosition(3) >>> d03 = p0.Distance(p3) >>> d03 >= pcophore.getLowerBound(0,1)-.01 True >>> d03 <= pcophore.getUpperBound(0,1)+.01 True If we optimize without the distance constraints (provided via the atomMatches argument) we're not guaranteed to get the same results, particularly in a case like the current one where the pharmcophore brings the atoms uncomfortably close together: >>> testM = embeds[1] >>> e1,e2 = OptimizeMol(testM,bm) >>> e2 < e1 True >>> conf = testM.GetConformer(0) >>> p0 = conf.GetAtomPosition(0) >>> p3 = conf.GetAtomPosition(3) >>> d03 = p0.Distance(p3) >>> d03 >= pcophore.getLowerBound(0,1)-.01 True >>> d03 <= pcophore.getUpperBound(0,1)+.01 False """ try: ff = ChemicalForceFields.UFFGetMoleculeForceField(mol) except Exception: logger.info('Problems building molecular forcefield', exc_info=True) return -1.0, -1.0 weights = [] if (atomMatches): for k in range(len(atomMatches)): for i in atomMatches[k]: for l in range(k + 1, len(atomMatches)): for j in atomMatches[l]: weights.append((i, j)) for i, j in weights: if j < i: i, j = j, i minV = bm[j, i] maxV = bm[i, j] ff.AddDistanceConstraint(i, j, minV, maxV, forceConstant) if excludedVolumes: nAts = mol.GetNumAtoms() conf = mol.GetConformer() idx = nAts for exVol in excludedVolumes: assert exVol.pos is not None logger.debug('ff.AddExtraPoint(%.4f,%.4f,%.4f)' % (exVol.pos[0], exVol.pos[1], exVol.pos[2])) ff.AddExtraPoint(exVol.pos[0], exVol.pos[1], exVol.pos[2], True) indices = [] for localIndices, foo, bar in exVol.featInfo: indices += list(localIndices) for i in range(nAts): v = numpy.array(conf.GetAtomPosition(i)) - numpy.array( exVol.pos) d = numpy.sqrt(numpy.dot(v, v)) if i not in indices: if d < 5.0: logger.debug( 'ff.AddDistanceConstraint(%d,%d,%.3f,%d,%.0f)' % (i, idx, exVol.exclusionDist, 1000, forceConstant)) ff.AddDistanceConstraint(i, idx, exVol.exclusionDist, 1000, forceConstant) else: logger.debug( 'ff.AddDistanceConstraint(%d,%d,%.3f,%.3f,%.0f)' % (i, idx, bm[exVol.index, i], bm[i, exVol.index], forceConstant)) ff.AddDistanceConstraint(i, idx, bm[exVol.index, i], bm[i, exVol.index], forceConstant) idx += 1 ff.Initialize() e1 = ff.CalcEnergy() if isNaN(e1): raise ValueError('bogus energy') if verbose: print(Chem.MolToMolBlock(mol)) for i, vol in enumerate(excludedVolumes): pos = ff.GetExtraPointPos(i) print( ' % 7.4f % 7.4f % 7.4f As 0 0 0 0 0 0 0 0 0 0 0 0' % tuple(pos), file=sys.stderr) needsMore = ff.Minimize() nPasses = 0 while needsMore and nPasses < maxPasses: needsMore = ff.Minimize() nPasses += 1 e2 = ff.CalcEnergy() if isNaN(e2): raise ValueError('bogus energy') if verbose: print('--------') print(Chem.MolToMolBlock(mol)) for i, vol in enumerate(excludedVolumes): pos = ff.GetExtraPointPos(i) print( ' % 7.4f % 7.4f % 7.4f Sb 0 0 0 0 0 0 0 0 0 0 0 0' % tuple(pos), file=sys.stderr) ff = None return e1, e2
#!/usr/bin/env python # -*- coding: utf-8 -*- # (c) 2012-2019 [email protected] # This file is part of MolecularFramework. # You can use,modify, and distribute it under # the terms of the GNU General Public Licenze, version 3. # See the file LICENSE for details from rdkit import Chem from rdkit.Chem import AllChem from rdkit.Chem import ChemicalForceFields #m = Chem.MolFromSmiles('N') m = Chem.MolFromSmiles("O") #m = Chem.MolFromSmiles("[CH4]") m2 = Chem.AddHs(m) #m2 = m AllChem.EmbedMolecule(m2) AllChem.MMFFOptimizeMolecule(m2) mp = ChemicalForceFields.MMFFGetMoleculeProperties(m2) for i in range(m2.GetNumAtoms()): print(m2.GetAtoms()[i].GetAtomicNum()) print(mp.GetMMFFPartialCharge(i)) print(mp.GetMMFFVdWParams(i, i)) print("-" * 8)
def test6Chirality(self): # turn on chirality and we should get chiral volume that is pretty consistent and # positive tgtVol = 13.0 smiles = "Cl[C@](C)(F)Br" mol = Chem.MolFromSmiles(smiles) cids = rdDistGeom.EmbedMultipleConfs(mol, 30, maxAttempts=30, randomSeed=100) self.assertTrue(len(cids) == 30) for cid in cids: conf = mol.GetConformer(cid) vol = computeChiralVol(conf.GetAtomPosition(0), conf.GetAtomPosition(2), conf.GetAtomPosition(3), conf.GetAtomPosition(4)) self.assertTrue(abs(vol - tgtVol) < 1) # turn of chirality and now we should see both chiral forms smiles = "ClC(C)(F)Br" mol = Chem.MolFromSmiles(smiles) cids = rdDistGeom.EmbedMultipleConfs(mol, 30, maxAttempts=30, randomSeed=120) self.assertTrue(len(cids) == 30) nPos = 0 nNeg = 0 for cid in cids: conf = mol.GetConformer(cid) vol = computeChiralVol(conf.GetAtomPosition(0), conf.GetAtomPosition(2), conf.GetAtomPosition(3), conf.GetAtomPosition(4)) self.assertTrue(abs(vol - tgtVol) < 1 or abs(vol + tgtVol) < 1) if vol < 0: nNeg += 1 else: nPos += 1 self.assertTrue(nPos > 0) self.assertTrue(nNeg > 0) tgtVol = 5.0 for i in range(10): smiles = "Cl[C@H](F)Br" mol = Chem.MolFromSmiles(smiles) ci = rdDistGeom.EmbedMolecule(mol, 30, (i + 1) * 10) conf = mol.GetConformer(ci) vol = computeChiralVol(conf.GetAtomPosition(0), conf.GetAtomPosition(1), conf.GetAtomPosition(2), conf.GetAtomPosition(3)) self.assertTrue(abs(vol - tgtVol) < 1, "%s %s" % (vol, tgtVol)) tgtVol = 3.5 expected = [ -3.62, -3.67, -3.72, 3.91, 3.95, 3.98, 3.90, 3.94, 3.98, 3.91 ] nPos = 0 nNeg = 0 for i in range(30): smiles = "ClC(F)Br" mol = Chem.MolFromSmiles(smiles) ci = rdDistGeom.EmbedMolecule(mol, 30, (i + 1) * 10) conf = mol.GetConformer(ci) vol = computeChiralVol(conf.GetAtomPosition(0), conf.GetAtomPosition(1), conf.GetAtomPosition(2), conf.GetAtomPosition(3)) self.assertTrue(abs(vol - tgtVol) < 1 or abs(vol + tgtVol) < 1) if vol < 0: nNeg += 1 else: nPos += 1 self.assertTrue(nPos > 0) self.assertTrue(nNeg > 0) smiles = "Cl[C@H](F)Br" m = Chem.MolFromSmiles(smiles) mol = Chem.AddHs(m) cids = rdDistGeom.EmbedMultipleConfs(mol, 10, maxAttempts=30, randomSeed=100) self.assertTrue(len(cids) == 10) tgtVol = 10.5 for cid in cids: conf = mol.GetConformer(cid) vol = computeChiralVol(conf.GetAtomPosition(0), conf.GetAtomPosition(2), conf.GetAtomPosition(3), conf.GetAtomPosition(4)) self.assertTrue(abs(vol - tgtVol) < 2.) # let's try a little more complicated system expectedV1 = -2.0 expectedV2 = -2.9 for i in range(5): smi = "C1=CC=C(C=C1)[C@H](OC1=C[NH]N=C1)C(=O)[NH]C[C@H](Cl)C1=CC=NC=C1" mol = Chem.MolFromSmiles(smi) ci = rdDistGeom.EmbedMolecule(mol, randomSeed=(i + 1) * 15) self.assertTrue(ci >= 0) ff = ChemicalForceFields.UFFGetMoleculeForceField(mol, 10.0, ci) ff.Minimize() conf = mol.GetConformer(ci) vol1 = computeChiralVol(conf.GetAtomPosition(6), conf.GetAtomPosition(3), conf.GetAtomPosition(7), conf.GetAtomPosition(13)) self.assertTrue( abs(vol1 - expectedV1) < 1 or abs(vol1 + expectedV1) < 1) if vol1 < 0: nNeg += 1 else: nPos += 1 vol2 = computeChiralVol(conf.GetAtomPosition(17), conf.GetAtomPosition(16), conf.GetAtomPosition(18), conf.GetAtomPosition(19)) self.assertTrue( abs(vol2 - expectedV2) < 1 or abs(vol2 + expectedV2) < 1) # remove the chiral specification and we should see other chiral # forms of the compound expectedV1 = 2.0 #[-2.30, -2.31, -2.30, 2.30, -1.77] expectedV2 = 2.8 #[2.90, 2.89, 2.69, -2.90, -2.93] self.assertTrue(nPos > 0) self.assertTrue(nNeg > 0) for i in range(5): smi = "C1=CC=C(C=C1)C(OC1=C[NH]N=C1)C(=O)[NH]CC(Cl)C1=CC=NC=C1" mol = Chem.MolFromSmiles(smi) ci = rdDistGeom.EmbedMolecule(mol, 30, (i + 1) * 10) ff = ChemicalForceFields.UFFGetMoleculeForceField(mol, 10.0, ci) ff.Minimize() conf = mol.GetConformer(ci) vol1 = computeChiralVol(conf.GetAtomPosition(6), conf.GetAtomPosition(3), conf.GetAtomPosition(7), conf.GetAtomPosition(13)) vol2 = computeChiralVol(conf.GetAtomPosition(17), conf.GetAtomPosition(16), conf.GetAtomPosition(18), conf.GetAtomPosition(19)) self.assertTrue(abs(abs(vol1) - expectedV1) < 1.0) self.assertTrue(abs(abs(vol2) - expectedV2) < 1.0)
def scan_angles(mol, n_steps, torsions, globalopt=False): """ scan torsion and get energy landscape """ # Load mol info n_atoms = mol.GetNumAtoms() n_torsions = len(torsions) atoms = mol.GetAtoms() atoms = [atom.GetSymbol() for atom in atoms] # Setup forcefield for molecule # no constraints ffprop_mmff = ChemicalForceFields.MMFFGetMoleculeProperties(mol) forcefield = ChemicalForceFields.MMFFGetMoleculeForceField( mol, ffprop_mmff) # Get conformer and origin conformer = mol.GetConformer() origin = conformer.GetPositions() origin -= rmsd.centroid(origin) # Origin angle origin_angles = [] for idxs in torsions: angle = Chem.rdMolTransforms.GetDihedralDeg(conformer, *idxs) origin_angles.append(angle) angles = np.linspace(0.0, 360.0, n_steps) axis_angles = [] axis_energies = [] axis_pos = [] f = open("test.xyz", 'w') # Get resolution angles for angles in itertools.product(angles, repeat=n_torsions): # Reset positions for i, pos in enumerate(origin): conformer.SetAtomPosition(i, pos) # Setup constrained forcefield ffc = ChemicalForceFields.MMFFGetMoleculeForceField(mol, ffprop_mmff) # ffu = ChemicalForceFields.UFFGetMoleculeForceField(mol) # Set angles and constrains for all torsions for i, angle in enumerate(angles): set_angle = origin_angles[i] + angle # Set clockwork angle try: Chem.rdMolTransforms.SetDihedralDeg(conformer, *torsions[i], set_angle) except: pass # Set forcefield constrain eps = 1e-5 eps = 0.05 ffc.MMFFAddTorsionConstraint(*torsions[i], False, set_angle - eps, set_angle + eps, 1.0e6) # ffu.UFFAddTorsionConstraint(*torsions[i], False, # set_angle, set_angle, 1.0e10) # minimize constrains conv = ffc.Minimize(maxIts=1000, energyTol=1e-2, forceTol=1e-2) if conv == 1: # unconverged print("unconverged", globalopt) else: print("converged", globalopt) if globalopt: forcefield.Minimize(maxIts=1000, energyTol=1e-3, forceTol=1e-3) energy = forcefield.CalcEnergy() else: energy = forcefield.CalcEnergy() # Get current positions pos = conformer.GetPositions() pos -= rmsd.centroid(pos) pos = align(pos, origin) xyz = rmsd.set_coordinates(atoms, pos) f.write(xyz) f.write("\n") angles = [] for idxs in torsions: angle = Chem.rdMolTransforms.GetDihedralDeg(conformer, *idxs) angles.append(angle) axis_angles.append(angles) axis_energies.append(energy) axis_pos.append(pos) f.close() return axis_angles, axis_energies