def enumerate_conformations(name, smiles): """Generate geometry and run epik.""" # Generate molecule geometry with OpenEye print "Generating molecule {}".format(name) oe_molecule = openeye.smiles_to_oemol(smiles) try: oe_molecule = openeye.get_charges(oe_molecule, keep_confs=1) except RuntimeError as e: traceback.print_exc() print "Skipping molecule " + name return # Create output subfolder output_basepath = os.path.join(output_dir, name) if not os.path.isdir(output_basepath): os.mkdir(output_basepath) output_basepath = os.path.join(output_basepath, name) # Save mol2 file with residue name = first three uppercase letters print "Running epik on molecule {}".format(name) mol2_file_path = output_basepath + '-input.mol2' residue_name = re.sub('[^A-Za-z]+', '', name.upper())[:3] openeye.molecule_to_mol2(oe_molecule, mol2_file_path, residue_name=residue_name) # Run epik on mol2 file mae_file_path = output_basepath + '-epik.mae' schrodinger.run_epik(mol2_file_path, mae_file_path, tautomerize=True, max_structures=32, ph_tolerance=10.0) # Convert maestro file to sdf and mol2 schrodinger.run_structconvert(mae_file_path, output_basepath + '-epik.sdf') schrodinger.run_structconvert(mae_file_path, output_basepath + '-epik.mol2')
def _writeMolecule(molecule, output_filename): """ Write the molecule to a file. Parameters ---------- molecule : openeye.oechem.OEMol The molecule to write (will be modified by writer). output_filename : str The filename of file to be written; type is autodetected by extension. """ from openmoltools.openeye import molecule_to_mol2 molecule_to_mol2(molecule, tripos_mol2_filename=output_filename, conformer=0, residue_name=molecule.GetTitle())
def _writeMolecule(molecule, output_filename, standardize=True): """ Write the molecule to a file. Parameters ---------- molecule : openeye.oechem.OEMol The molecule to write (will be modified by writer). output_filename : str The filename of file to be written; type is autodetected by extension. standardize : bool, optional, default=True Standardize molecular properties such as atom names in the output file. """ from openmoltools.openeye import molecule_to_mol2 molecule_to_mol2(molecule, tripos_mol2_filename=output_filename, conformer=0, residue_name=molecule.GetTitle(), standardize=standardize)
def oemol_to_antechamber(m, gaff_mol2_filename, frcmod_filename, residue_name="MOL", strictStereo=False): """ Build a molecule from a mol2 file and run antechamber, generating GAFF mol2 and frcmod files from a smiles string. Charges will be generated using the OpenEye QuacPac AM1-BCC implementation. Created by hacking openmoltools/openeye.py Parameters ---------- m : oechem molecule object Molecule to construct and charge gaff_mol2_filename : str Filename of mol2 file output of antechamber, with charges created from openeye frcmod_filename : str Filename of frcmod file output of antechamber. Most likely this file will be almost empty, at least for typical molecules. residue_name : str, optional, default="MOL" OpenEye writes mol2 files with <0> as the residue / ligand name. This chokes many mol2 parsers, so we replace it with a string of your choosing. This might be useful for downstream applications if the residue names are required to be unique. strictStereo : bool, optional, default=False If False, permits smiles strings with unspecified stereochemistry. See https://docs.eyesopen.com/omega/usage.html """ #oechem = import_("openeye.oechem") #if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for oechem!")) # Get the absolute path so we can find these filenames from inside a temporary directory. gaff_mol2_filename = os.path.abspath(gaff_mol2_filename) frcmod_filename = os.path.abspath(frcmod_filename) m = openeye.get_charges(m, strictStereo=strictStereo, keep_confs=1) with enter_temp_directory(): # Avoid dumping 50 antechamber files in local directory. _unused = openeye.molecule_to_mol2(m, "./tmp.mol2", residue_name=residue_name) net_charge = oechem.OENetCharge(m) tmp_gaff_mol2_filename, tmp_frcmod_filename = amber.run_antechamber("tmp", "./tmp.mol2", charge_method=None, net_charge=net_charge) # USE OE AM1BCC charges! shutil.copy(tmp_gaff_mol2_filename, gaff_mol2_filename) shutil.copy(tmp_frcmod_filename, frcmod_filename)
omega(molecule) return molecule ################################################################################ # MAIN ################################################################################ if __name__ == '__main__': # Create list of molecules that share a common core. molecule_names = ['benzene', 'toluene', 'methoxytoluene'] molecules = [ create_molecule(name) for name in molecule_names ] # DEBUG: Write molecules to mol2 files for ease of debugging/visualization. for (index, molecule) in enumerate(molecules): openeye.molecule_to_mol2(molecule, tripos_mol2_filename='molecule-%05d.mol2' % index) # Create an OpenMM system to represent the environment. molecule = create_molecule('benzene') # TODO: Change to supramolecular host, like 18-crown-6? [system, topology, positions] = generate_openmm_system(molecule) # Translate the molecule out of the way so it doesn't overlap with anything. positions[:,2] += 15.0 * unit.angstroms # translate 15A along z-axis # Create merged topology for ligands and add them to the environment. [system, topology, positions] = create_merged_topology(system, topology, positions, molecules) # DEBUG: Write new atom identities. natoms = system.getNumParticles() for (index, atom) in enumerate(topology.atoms()): print '%8d %8s %8s %8s %8s %8s %8.3f %8.3f %8.3f' % (index, atom.name, atom.residue.chain.index, atom.element.name, atom.residue.index, atom.residue.name, positions[index,0]/unit.angstroms, positions[index,1]/unit.angstroms, positions[index,2]/unit.angstroms) app.PDBFile.writeFile(topology, positions, file=open('initial.pdb','w'))
failed_molecules_dict = {} # Generate charges for an OpenEye OEMol molecule. It will return molecule with OpenEye's recommended AM1BCC # charge selection scheme. for key, value in eMolID_oemol_dict.items(): print("Generating conformer for ", key, "...") try: oe_molecule = omtoe.get_charges(value, keep_confs=1) except RuntimeError: print("Conformation generation failed for {}.".format(key)) # Save failed molecule to failed_molecules_dict failed_molecules_dict[key] = value mol2_filename = mol2_directory_path + "/" + str(key) + ".mol2" omtoe.molecule_to_mol2(oe_molecule, tripos_mol2_filename=mol2_filename) print("Mol2 file {} generated.".format(mol2_filename)) print("") print("Conformer generation for {} molecules failed.".format( len(failed_molecules_dict))) # Remove failed molecules from oMolID_oemol_dict dictionary for key, value in failed_molecules_dict.items(): eMolID_oemol_dict.pop(key, None) print("{} molecules removed from the list.".format(len(failed_molecules_dict))) # Save dictionary of successful conformers as spickle file pickle.dump(eMolID_oemol_dict, open("eMolID_oemol_dict.pickle", "wb")) # Save dictionary of failed molecules as confromer generation as a pickle file
name = mol.GetTitle() print('\nGenerating input for {}'.format(name)) try: os.mkdir(os.path.join(output_path, name)) except FileExistsError: print("Overwriting existing directory") conformers = openeye.generate_conformers(mol) tagged_smiles = oechem.OEMolToSmiles(mol) json_data["tagged_smiles"] = tagged_smiles molecule, atom_map = utils.get_atom_map(tagged_smiles, conformers, is_mapped=True) if not atom_map: print("Can't get atom map. Skipping {}".format(name)) continue print("{} has {} conformers".format(name, conformers.GetMaxConfIdx())) # Generate mol2 file openeye.molecule_to_mol2(conformers, tripos_mol2_filename='{}.mol2'.format(name), conformer=None) # Generate xyz file #xyz = utils.to_mapped_xyz(conformers, atom_map=atom_map, xyz_format=True, filename=name) xyz = utils.to_mapped_xyz(conformers, atom_map=atom_map) for i, coords in enumerate(xyz.split('*')): json_data['molecule'] = coords json_filename = "{}_{}.input.json".format(name, str(i)) json_path = os.path.join(name, json_filename) with open(json_path, 'w') as outfile: json.dump(json_data, outfile, indent=4, sort_keys=True) input_filename = os.path.join(os.getcwd(), json_filename) # replace command on psub script with open('bond_order_bsub.lsf', 'r') as file: filedata = file.read() JOB_NAME = '{}_{}'.format(name, str(i))
else: #raise Exception("Force type %s unknown." % force_name) pass return [system, topology, positions] if __name__ == '__main__': # Create two test molecules. #molecule1 = create_molecule('toluene') molecule1 = create_molecule('aspirin') molecule2 = create_molecule('methoxytoluene') #molecule2 = create_molecule('benzene') # Write molecules to mol2 files for ease of debugging. openeye.molecule_to_mol2(molecule1, tripos_mol2_filename='molecule1.mol2') openeye.molecule_to_mol2(molecule2, tripos_mol2_filename='molecule2.mol2') # Create an OpenMM system for molecule1 in some sort of "environment". # This system will be modified to introduce the ability to mutate molecule1 to molecule2. [system1, topology1, positions1] = generate_openmm_system(molecule1) # Modify the system to allow mutation to molecule2. natoms = molecule1.NumAtoms() [system, topology, positions] = create_relative_alchemical_transformation(system1, topology1, positions1, range(natoms), molecule1, molecule2) # Write. natoms = system.getNumParticles() for index in range(natoms): print '%8d %8.3f %8.3f %8.3f' % (index, positions[index,0]/unit.angstroms, positions[index,1]/unit.angstroms, positions[index,2]/unit.angstroms) app.PDBFile.writeFile(topology, positions, file=open('initial.pdb','w'))
def savePDBandFFXML(self, pdb_filename=None, ffxml_filename=None): """ Creates a .pdb file representative of the dual topology and a corresponding .xml file. Arguments: pdb_filename (optional) the name of the pdb file to save to ffxml_filename (optional) the name of the xml file to save to Will not overwrite an existing ffxml file with the same file name. Requires mdtraj and antechamber Creates class variables: self.pdb_filename (string) name of file to save pdb self.ffxml_filename (string) name of file to save initial xml (will not contain custom force entries) """ try: import mdtraj as md except: return if pdb_filename is None: pdb_filename = self.title + ".pdb" self.pdb_filename = pdb_filename file_prefix = pdb_filename[:-4] self.mol2_file = file_prefix + ".mol2" if ffxml_filename is None: ffxml_filename = file_prefix + ".xml" self.ffxml_filename = ffxml_filename self.createDualTopology() substructure_pdb = "SUB_" + file_prefix + ".pdb" substructure_mol2 = "SUB_" + file_prefix + ".mol2" with gaff2xml.utils.enter_temp_directory(): _unused = openeye.molecule_to_mol2(self.dual_topology, self.mol2_file) _unused = openeye.molecule_to_mol2(self.common_substructure, substructure_mol2) traj = md.load(self.mol2_file) print("Run Antechamber") # the substructure will work fine and can be run through gaff2xml gaff_mol2_SUB = gaff2xml.utils.run_antechamber( "SUB_" + file_prefix, substructure_mol2, charge_method=None)[0] # the dual topology will have issues and has to be run differently gaff_mol2_filename, frcmod_filename = self._run_antechamber( file_prefix, gaff_mol2_SUB, charge_method=None) print("Create ffxml file") ffxml = gaff2xml.utils.create_ffxml_file( [gaff_mol2_filename], [frcmod_filename], override_mol2_residue_name=file_prefix) if not os.path.exists(ffxml_filename): outfile = open(ffxml_filename, 'w') outfile.write(ffxml.read()) outfile.close() ffxml.seek(0) self.ffxml = ffxml traj.save_pdb(pdb_filename)
def savePDBandFFXML(self, pdb_filename=None, ffxml_filename=None): """ Creates a .pdb file representative of the dual topology and a corresponding .xml file. Arguments: pdb_filename (optional) the name of the pdb file to save to ffxml_filename (optional) the name of the xml file to save to Will not overwrite an existing ffxml file with the same file name. Requires mdtraj and antechamber Creates class variables: self.pdb_filename (string) name of file to save pdb self.ffxml_filename (string) name of file to save initial xml (will not contain custom force entries) """ try: import mdtraj as md except: return if pdb_filename is None: pdb_filename = self.title+".pdb" self.pdb_filename = pdb_filename file_prefix = pdb_filename[:-4] self.mol2_file = file_prefix+".mol2" if ffxml_filename is None: ffxml_filename = file_prefix+".xml" self.ffxml_filename = ffxml_filename self.createDualTopology() substructure_pdb = "SUB_" + file_prefix + ".pdb" substructure_mol2 = "SUB_" + file_prefix + ".mol2" with gaff2xml.utils.enter_temp_directory(): _unused = openeye.molecule_to_mol2(self.dual_topology,self.mol2_file) _unused = openeye.molecule_to_mol2(self.common_substructure,substructure_mol2) traj = md.load(self.mol2_file) print("Run Antechamber") # the substructure will work fine and can be run through gaff2xml gaff_mol2_SUB = gaff2xml.utils.run_antechamber("SUB_"+file_prefix, substructure_mol2, charge_method=None)[0] # the dual topology will have issues and has to be run differently gaff_mol2_filename, frcmod_filename = self._run_antechamber(file_prefix, gaff_mol2_SUB, charge_method=None) print("Create ffxml file") ffxml = gaff2xml.utils.create_ffxml_file([gaff_mol2_filename], [frcmod_filename], override_mol2_residue_name=file_prefix) if not os.path.exists(ffxml_filename): outfile = open(ffxml_filename, 'w') outfile.write(ffxml.read()) outfile.close() ffxml.seek(0) self.ffxml = ffxml traj.save_pdb(pdb_filename)