def testTorsionFingerprints(self): # we use the xray structure from the paper (JCIM, 52, 1499, 2012): 1DWD refFile = os.path.join(RDConfig.RDCodeDir, 'Chem', 'test_data', '1DWD_ligand.pdb') ref = Chem.MolFromSmiles( 'NC(=[NH2+])c1ccc(C[C@@H](NC(=O)CNS(=O)(=O)c2ccc3ccccc3c2)C(=O)N2CCCCC2)cc1') mol = Chem.MolFromPDBFile(refFile) mol = AllChem.AssignBondOrdersFromTemplate(ref, mol) # the torsion lists tors_list, tors_list_rings = TorsionFingerprints.CalculateTorsionLists(mol) self.assertEqual(len(tors_list), 11) self.assertEqual(len(tors_list_rings), 4) self.assertAlmostEqual(tors_list[-1][1], 180.0, 4) tors_list, tors_list_rings = TorsionFingerprints.CalculateTorsionLists(mol, maxDev='spec') self.assertAlmostEqual(tors_list[-1][1], 90.0, 4) self.assertRaises(ValueError, TorsionFingerprints.CalculateTorsionLists, mol, maxDev='test') tors_list, tors_list_rings = TorsionFingerprints.CalculateTorsionLists(mol, symmRadius=0) self.assertEqual(len(tors_list[0][0]), 2) # the weights weights = TorsionFingerprints.CalculateTorsionWeights(mol) self.assertAlmostEqual(weights[4], 1.0) self.assertEqual(len(weights), len(tors_list + tors_list_rings)) weights = TorsionFingerprints.CalculateTorsionWeights(mol, 15, 14) self.assertAlmostEqual(weights[3], 1.0) self.assertRaises(ValueError, TorsionFingerprints.CalculateTorsionWeights, mol, 15, 3) # the torsion angles tors_list, tors_list_rings = TorsionFingerprints.CalculateTorsionLists(mol) torsions = TorsionFingerprints.CalculateTorsionAngles(mol, tors_list, tors_list_rings) self.assertEqual(len(weights), len(torsions)) self.assertAlmostEqual(torsions[2][0][0], 232.5346, 4) # the torsion fingerprint deviation tfd = TorsionFingerprints.CalculateTFD(torsions, torsions) self.assertAlmostEqual(tfd, 0.0) refFile = os.path.join(RDConfig.RDCodeDir, 'Chem', 'test_data', '1PPC_ligand.pdb') mol2 = Chem.MolFromPDBFile(refFile) mol2 = AllChem.AssignBondOrdersFromTemplate(ref, mol2) torsions2 = TorsionFingerprints.CalculateTorsionAngles(mol2, tors_list, tors_list_rings) weights = TorsionFingerprints.CalculateTorsionWeights(mol) tfd = TorsionFingerprints.CalculateTFD(torsions, torsions2, weights=weights) self.assertAlmostEqual(tfd, 0.0691, 4) tfd = TorsionFingerprints.CalculateTFD(torsions, torsions2) self.assertAlmostEqual(tfd, 0.1115, 4) # the wrapper functions tfd = TorsionFingerprints.GetTFDBetweenMolecules(mol, mol2) self.assertAlmostEqual(tfd, 0.0691, 4) mol.AddConformer(mol2.GetConformer(), assignId=True) mol.AddConformer(mol2.GetConformer(), assignId=True) tfd = TorsionFingerprints.GetTFDBetweenConformers(mol, confIds1=[0], confIds2=[1, 2]) self.assertEqual(len(tfd), 2) self.assertAlmostEqual(tfd[0], 0.0691, 4) tfdmat = TorsionFingerprints.GetTFDMatrix(mol) self.assertEqual(len(tfdmat), 3)
def prune_last_conformer( mol: Chem.Mol, tfd_thresh: float, energies: List[float]) -> Tuple[Chem.Mol, List[float]]: """Prunes the last conformer of the molecule. If no conformers in `mol` have a TFD (Torsional Fingerprint Deviation) with the last conformer of less than `tfd_thresh`, the last conformer is kept. Otherwise, the lowest energy conformer with TFD less than `tfd_thresh` is kept and all other conformers are discarded. Parameters ---------- mol : RDKit Mol The molecule to be pruned. The conformers in the molecule should be ordered by ascending energy. tfd_thresh : float The minimum threshold for TFD between conformers. energies : list of float A list of all the energies of the conformers in `mol`. Returns ------- mol : RDKit Mol The updated molecule after pruning, with conformers sorted by ascending energy. energies : list of float A list of all the energies of the conformers in `mol` after pruning and sorting by ascending energy. """ if tfd_thresh < 0 or mol.GetNumConformers() <= 1: return mol, energies idx = bisect.bisect(energies[:-1], energies[-1]) tfd = TorsionFingerprints.GetTFDBetweenConformers( mol, range(0, mol.GetNumConformers() - 1), [mol.GetNumConformers() - 1], useWeights=False) tfd = np.array(tfd) # if lower energy conformer is within threshold, drop new conf if not np.all(tfd[:idx] >= tfd_thresh): energies = energies[:-1] mol.RemoveConformer(mol.GetNumConformers() - 1) return mol, energies else: keep = list(range(0, idx)) keep.append(mol.GetNumConformers() - 1) keep += [ x for x in range(idx, mol.GetNumConformers() - 1) if tfd[x] >= tfd_thresh ] new = Chem.Mol(mol) new.RemoveAllConformers() for i in keep: conf = mol.GetConformer(i) new.AddConformer(conf, assignId=True) return new, [energies[i] for i in keep]
def get_tfd(mol): return TorsionFingerprints.GetTFDBetweenConformers(mol, [0], [1])