def rdkit_mmff94_xyz(smiles, **kwargs): """ Returns the string of the XYZ file obtained performing the MMFF94 molecular mechanics optimization of the given SMILES using RDKit. Writing temporary files in $MM_WORKING_DIR if defined or otherwise in /tmp :param smiles: input_SMILES :param max_iterations: max number of iterations (default 500) :return : XYZ string of optimized geometry, success (whether the MM optimization was successful and the smiles has stayed identical after optimization) """ working_dir = os.environ[ "MM_WORKING_DIR"] if "MM_WORKING_DIR" in os.environ else "/tmp" # Converting the molecule to RDKit object mol = MolFromSmiles(smiles) smi_canon = MolToSmiles(MolFromSmiles(smiles)) # Setting paths filename_smiles = str(os.getpid()) + "_" + smi_to_filename(smi_canon) xyz_path = join(working_dir, filename_smiles + '.xyz') post_MM_smi_path = join(working_dir, filename_smiles + '.smi') # Computing geometry try: # Adding implicit hydrogens mol = AddHs(mol) # MM optimization EmbedMolecule(mol) value = MMFFOptimizeMolecule(mol, maxIters=kwargs["max_iterations"]) # Success if returned value is null success_RDKIT_output = value == 0 # Computing XYZ from optimized molecule xyz_str = MolToXYZBlock(mol) # Writing optimized XYZ to file with open(xyz_path, "w") as f: f.writelines(xyz_str) # Success if the optimization has converged and the post MM smiles is identical the pre MM smiles success = success_RDKIT_output and check_identical_geometries( xyz_path, smi_canon, post_MM_smi_path) except Exception as e: success = False xyz_str = None finally: # Removing files remove_files([post_MM_smi_path, xyz_path]) return xyz_str, success
def _optimize(self, mol): return MMFFOptimizeMolecule(mol)
smiles = 'CN1COCN(C1=N[N+](=O)[O-])CC2=CN=C(S2)Cl' # ファイル名を決める t = datetime.datetime.fromtimestamp(time.time()) psi4.set_output_file("{}_{}{}{}_{}{}.log".format(smiles, t.year, t.month, t.day, t.hour, t.minute)) # SMILES から三次元構造を発生させて、粗3D構造最適化 mol = Chem.MolFromSmiles(smiles) mol = Chem.AddHs(mol) params = ETKDGv3() params.randomSeed = 1 EmbedMolecule(mol, params) # MMFF(Merck Molecular Force Field) で構造最適化する MMFFOptimizeMolecule(mol) #UFF(Universal Force Field)普遍力場で構造最適化したい場合は #UFFOptimizeMolecule(mol) conf = mol.GetConformer() # Psi4 に入力可能な形式に変換する。 # 電荷とスピン多重度を設定(下は、電荷0、スピン多重度1) mol_input = "0 1" #各々の原子の座標をXYZフォーマットで記述 for atom in mol.GetAtoms(): mol_input += "\n " + atom.GetSymbol() + " " + str(conf.GetAtomPosition(atom.GetIdx()).x)\ + " " + str(conf.GetAtomPosition(atom.GetIdx()).y)\ + " " + str(conf.GetAtomPosition(atom.GetIdx()).z)
batch = batch.to(args.device) pos_s = simple_generate_batch(model_cnf, batch, num_samples=1, embedder=embedder)[0] # (1, BN, 3) batch.pos = pos_s[0] batch.to('cpu') batch_list = batch.to_data_list() all_data_list += batch_list grouped_data = split_dataset_by_smiles(all_data_list) for smiles in grouped_data: for data in grouped_data[smiles]: rdmol = data['rdmol'] rdmol = set_rdmol_positions_(rdmol, data.pos.cpu()) gen_rdmols.append(rdmol) # Optimize using MMFF opt_rdmols = [] if args.mmff: for mol in tqdm(gen_rdmols, desc='MMFF Optimize'): opt_mol = deepcopy(mol) MMFFOptimizeMolecule(opt_mol) opt_rdmols.append(opt_mol) gen_rdmols = opt_rdmols # Save logger.info('Saving to: %s' % args.out) with open(args.out, 'wb') as f: pickle.dump(gen_rdmols, f)