def SetTorsionRad(self, torsion: list, rad: Union[float, int]): """ Set the dihedral angle of the torsion in rad. The torsion can only be defined by a chain of bonded atoms. Args: torsion (list): A list of four atom indexes. degree (float, int): The dihedral angle of the torsion in rad. """ rdMT.SetDihedralRad(self._conf, *torsion, rad)
def genConformer_r(mol, conf, i, matches, degree, sdwriter, args, name, log): '''recursively enumerate all angles for rotatable dihedrals. i is which dihedral we are enumerating by degree to output conformers to out''' rotation_count = 1 if i >= len(matches): #base case, torsions should be set in conf #setting the metal back instead of I if args.metal_complex == True and args.nodihedrals == True: for atom in mol.GetAtoms(): if atom.GetIdx() in args.metal_idx: re_symbol = args.metal_sym[args.metal_idx.index( atom.GetIdx())] for el in elementspt: if el.symbol == re_symbol: atomic_number = el.number atom.SetAtomicNum(atomic_number) sdwriter.write(mol, conf) return 1 else: #log.write(str(i)+'starting new else writing') #incr = math.pi*degree / 180.0 total = 0 deg = 0 while deg < 360.0: #log.write(matches[i]) rad = math.pi * deg / 180.0 #log.write(matches[i],rad) rdMolTransforms.SetDihedralRad(mol.GetConformer(conf), *matches[i], value=rad) #recalculating energies after rotation if args.ff == "MMFF": GetFF = Chem.MMFFGetMoleculeForceField( mol, Chem.MMFFGetMoleculeProperties(mol), confId=conf) elif args.ff == "UFF": GetFF = Chem.UFFGetMoleculeForceField(mol) else: log.write(' Force field {} not supported!'.format(args.ff)) sys.exit() GetFF.Initialize() converged = GetFF.Minimize(maxIts=args.opt_steps_RDKit) energy = GetFF.CalcEnergy() mol.SetProp("Energy", energy) mol.SetProp( '_Name', name + ' - conformer from rotation - ' + str(rotation_count)) rotation_count += 1 total += genConformer_r(mol, conf, i + 1, matches, degree, sdwriter, args, name, log) deg += degree return total
def genConformer_r(mol, conf, i, matches, degree, sdwriter): '''recursively enumerate all angles for rotatable dihedrals. i is which dihedral we are enumerating by degree to output conformers to out''' if i >= len(matches): #base case, torsions should be set in conf sdwriter.write(mol,conf) return 1 else: #incr = math.pi*degree / 180.0 total = 0 deg = 0 while deg < 360.0: rad = math.pi*deg / 180.0 rdMolTransforms.SetDihedralRad(mol.GetConformer(conf),*matches[i],value=rad) total += genConformer_r(mol, conf, i+1, matches, degree, sdwriter) deg += degree return total
def testGetSetDihedral(self): file = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'MolTransforms', 'test_data', '3-cyclohexylpyridine.mol') m = Chem.MolFromMolFile(file, True, False) conf = m.GetConformer() dihedral = rdmt.GetDihedralDeg(conf, 0, 19, 21, 24) self.failUnlessAlmostEqual(dihedral, 176.05, 2) rdmt.SetDihedralDeg(conf, 8, 0, 19, 21, 65.0) dihedral = rdmt.GetDihedralDeg(conf, 8, 0, 19, 21) self.failUnlessAlmostEqual(dihedral, 65.0, 1) rdmt.SetDihedralDeg(conf, 8, 0, 19, 21, -130.0) dihedral = rdmt.GetDihedralDeg(conf, 8, 0, 19, 21) self.failUnlessAlmostEqual(dihedral, -130.0, 1) rdmt.SetDihedralRad(conf, 21, 19, 0, 8, -2. / 3. * math.pi) dihedral = rdmt.GetDihedralRad(conf, 8, 0, 19, 21) self.failUnlessAlmostEqual(dihedral, -2. / 3. * math.pi, 1) dihedral = rdmt.GetDihedralDeg(conf, 8, 0, 19, 21) self.failUnlessAlmostEqual(dihedral, -120.0, 1)
def genConformer_r(mol, conf, i, matches, degree, sdwriter,args,name,log): if i >= len(matches): # base case, torsions should be set in conf #setting the metal back instead of I if args.metal_complex and args.nodihedrals: set_metal_atomic_number(mol,args) sdwriter.write(mol,conf) return 1 else: total = 0 deg = 0 while deg < 360.0: rad = math.pi*deg / 180.0 rdMolTransforms.SetDihedralRad(mol.GetConformer(conf),*matches[i],value=rad) #recalculating energies after rotation GetFF = minimize_rdkit_energy(mol,conf,args,log) mol.SetProp("Energy",GetFF.CalcEnergy()) mol.SetProp('_Name',name) total += genConformer_r(mol, conf, i+1, matches, degree, sdwriter,args,name,log) deg += degree return total
def summ_search(mol, name,args): '''embeds core conformers, then optimizes and filters based on RMSD. Finally the rotatable torsions are systematically rotated''' sdwriter = Chem.SDWriter(name+output) Chem.SanitizeMol(mol) mol = Chem.AddHs(mol) mol.SetProp("_Name",name); if args.nodihedrals == False: rotmatches = getDihedralMatches(mol, args.heavyonly) else: rotmatches = [] if len(rotmatches) > args.max_torsions: print("x Too many torsions (%d). Skipping %s" %(len(rotmatches),(name+output))) else: if args.etkdg: cids = Chem.EmbedMultipleConfs(mol, args.sample, Chem.ETKDG(),randomSeed=args.seed) else: cids = Chem.EmbedMultipleConfs(mol, args.sample,randomSeed=args.seed) if args.verbose: print("o ", len(cids),"conformers initially sampled") #energy minimize all to get more realistic results if args.verbose: print("o Optimizing", len(cids), "initial conformers with", args.ff) if args.verbose: print("o Found", len(rotmatches), "rotatable torsions") cenergy = [] for i, conf in enumerate(cids): #identify the atoms and decide Force Field for atom in mol.GetAtoms(): if atom.GetAtomicNum() > 36: #upto Kr for MMFF, if not use UFF args.ff = "UFF" #print("UFF is used because there are atoms that MMFF doesn't recognise") if args.ff == "MMFF": GetFF = Chem.MMFFGetMoleculeForceField(mol, Chem.MMFFGetMoleculeProperties(mol),confId=conf) elif args.ff == "UFF": GetFF = Chem.UFFGetMoleculeForceField(mol) else: print(' Force field {} not supported!'.format(args.ff)); sys.exit() GetFF.Initialize() converged = GetFF.Minimize() cenergy.append(GetFF.CalcEnergy()) #if args.verbose: # print("- conformer", (i+1), "optimized: ", args.ff, "energy", GetFF.CalcEnergy()) #reduce to unique set if args.verbose: print("o Removing duplicate conformers ( RMSD <", args.rms_threshold, ")") sortedcids = sorted(cids,key = lambda cid: cenergy[cid]) selectedcids = [] for i, conf in enumerate(sortedcids): #set torsions to zero for m in rotmatches: rdMolTransforms.SetDihedralRad(mol.GetConformer(conf),*m,value=0) #check rmsd for seenconf in selectedcids: rms = get_conf_RMS(mol,seenconf,conf, args.heavyonly) if rms < args.rms_threshold: break else: #loop completed normally - no break, included empty selectedcids.append(conf) #now exhaustively drive torsions of selected conformers if args.verbose: print("o ", len(selectedcids),"unique (ignoring torsions) starting conformers remain") n_confs = int(len(selectedcids) * (360 / args.degree) ** len(rotmatches)) if args.verbose: print("o Systematic generation of", n_confs, "confomers") total = 0 for conf in selectedcids: total += genConformer_r(mol, conf, 0, rotmatches, args.degree, sdwriter) if args.verbose: print("o %d total conformations generated"%total) sdwriter.close()
print len(cids),"conformers sampled" #energy minimize all to get more realistic results cenergy = [] for conf in cids: #not passing confID only minimizes the first conformer converged = not Chem.UFFOptimizeMolecule(mol,confId=conf) cenergy.append(Chem.UFFGetMoleculeForceField(mol,confId=conf).CalcEnergy()) #reduce to unique set sortedcids = sorted(cids,key = lambda cid: cenergy[cid]) selectedcids = [] for conf in sortedcids: #set torsions to zero for m in rotmatches: rdMolTransforms.SetDihedralRad(mol.GetConformer(conf),*m,value=0) #check rmsd for seenconf in selectedcids: rms = getRMS(mol,seenconf,conf) if rms < args.rms_threshold: break else: #loop completed normally - no break, included empty selectedcids.append(conf) #now exhaustively drive torsions of selected conformers if args.verbose: print len(selectedcids),"unique (ignoring torsions) starting conformers" total = 0 for conf in selectedcids: total += genConformer_r(mol, conf, 0, rotmatches, args.degree, sdwriter)