def prepare_receptor(complex_pdb_filename, prefix): # Read the receptor and identify design units from openeye import oespruce, oechem complex = read_pdb_file(complex_pdb_filename) print('Identifying design units...') design_units = list(oespruce.OEMakeDesignUnits(complex)) for i, design_unit in enumerate(design_units): filename = f'DU_{i}.oedu' print(f'Writing design unit {i} to {filename}') oechem.OEWriteDesignUnit(filename, design_unit) if len(design_units) > 1: print('More than one design unit found---using first one') design_unit = design_units[0] # Prepare the receptor print('Preparing receptor...') from openeye import oedocking protein = oechem.OEGraphMol() design_unit.GetProtein(protein) ligand = oechem.OEGraphMol() design_unit.GetLigand(ligand) receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, ligand) oedocking.OEWriteReceptorFile(receptor, f'{prefix}-receptor.oeb.gz') with oechem.oemolostream(f'{prefix}-protein.pdb') as ofs: oechem.OEWriteMolecule(ofs, protein) with oechem.oemolostream(f'{prefix}-ligand.mol2') as ofs: oechem.OEWriteMolecule(ofs, ligand) with oechem.oemolostream(f'{prefix}-ligand.pdb') as ofs: oechem.OEWriteMolecule(ofs, ligand) with oechem.oemolostream(f'{prefix}-ligand.sdf') as ofs: oechem.OEWriteMolecule(ofs, ligand)
def main(argv=[__name__]): path = "receptor_pdbs/*.pdb" #input: pdbs from clustering files = glob.glob(path) for i in files: centroid_number = i[-5:-4] imstr = oechem.oemolistream(i) proteinStructure = oechem.OEGraphMol() oechem.OEReadMolecule(imstr, proteinStructure) coordinates_dictionary = oechem.OEMolBase.GetCoords(proteinStructure) x_coord = [] y_coord = [] z_coord = [] for key in coordinates_dictionary: x = coordinates_dictionary[key][0] y = coordinates_dictionary[key][1] z = coordinates_dictionary[key][2] x_coord.append(x) y_coord.append(y) z_coord.append(z) x_max = max(x_coord) x_min = min(x_coord) y_max = max(y_coord) y_min = min(y_coord) z_max = max(z_coord) z_min = min(z_coord) box = oedocking.OEBox( x_max, y_max, z_max, x_min, y_min, z_min) #Box set using max and min coordinates of entire protein receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, proteinStructure, box) oedocking.OEWriteReceptorFile(receptor, "receptor_oebs/receptor" + str(centroid_number) + ".oeb") #output: receptor oebs return 0
def main(argv=[__name__]): if len(argv) != 3: oechem.OEThrow.Usage("SetOuterContourVolume.py <receptor> <volume>") receptor = oechem.OEGraphMol() if not oedocking.OEReadReceptorFile(receptor, argv[1]): oechem.OEThrow.Fatal("Unable to open receptor file") outerContourVolume = float(argv[2]) # @ <SNIPPET-SET-OUTER-CONTOUR-VOLUME-1> negativeImagePotential = oedocking.OEReceptorGetNegativeImageGrid(receptor) gridElement = [] for i in range(negativeImagePotential.GetSize()): gridElement.append(negativeImagePotential[i]) gridElement.sort() gridElement.reverse() countToVolume = pow(negativeImagePotential.GetSpacing(), 3) ilevel = int((outerContourVolume / countToVolume) + 0.5) outerContourLevel = gridElement[-1] if ilevel < len(gridElement): outerContourLevel = gridElement[ilevel] oedocking.OEReceptorSetOuterContourLevel(receptor, outerContourLevel) # @ </SNIPPET-SET-OUTER-CONTOUR-VOLUME-1> if not oedocking.OEWriteReceptorFile(receptor, argv[1]): oechem.OEThrow.Fatal("Unable to write updated receptor")
def create_box_receptor(protein, xmax, ymax, zmax, xmin, ymin, zmin, receptor_save_path=None): """ Create a box receptor for docking. Parameters ---------- protein: oechem.OEGraphMol An oechem.OEGraphMol object holding a prepared protein structure. xmax: float or int Maximal number in x direction. ymax: float or int Maximal number in y direction. zmax: float or int Maximal number in z direction. xmin: float or int Minimal number in x direction. ymin: float or int Minimal number in x direction. zmin: float or int Minimal number in z direction. receptor_save_path: str File path for saving created receptor. If receptor_save_path is not provided, receptor will not be saved. Returns ------- receptor: oechem.OEGraphMol An oechem.OEGraphMol object holding a receptor with defined binding site via box dimensions. """ # Standard libraries import pathlib # External libraries from openeye import oechem, oedocking # create receptor box = oedocking.OEBox(xmax, ymax, zmax, xmin, ymin, zmin) receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, box) # save receptor if receptor_save_path is not None: oedocking.OEWriteReceptorFile( receptor, str(pathlib.Path(receptor_save_path).absolute())) return receptor
def create_receptor(output_name, pdb_file, bp_min, bp_max): check_oeb = output_name proteinStructure = oechem.OEGraphMol() ifs = oechem.oemolistream(pdb_file) ifs.SetFormat(oechem.OEFormat_PDB) oechem.OEReadMolecule(ifs, proteinStructure) box = oedocking.OEBox(*bp_max, *bp_min) receptor = oechem.OEGraphMol() s = oedocking.OEMakeReceptor(receptor, proteinStructure, box) oedocking.OEWriteReceptorFile(receptor, check_oeb)
def create_hint_receptor(protein, hintx, hinty, hintz, receptor_save_path=None): """ Create a hint receptor for docking. Parameters ---------- protein: oechem.OEGraphMol An oechem.OEGraphMol object holding a prepared protein structure. hintx: float or int A number defining the hint x coordinate. hinty: float or int A number defining the hint y coordinate. hintz: float or int A number defining the hint z coordinate. receptor_save_path: str File path for saving created receptor. If receptor_save_path is not provided, receptor will not be saved. Returns ------- receptor: oechem.OEGraphMol An oechem.OEGraphMol object holding a receptor with defined binding site via hint coordinates. """ # Standard libraries import pathlib # External libraries from openeye import oechem, oedocking # create receptor receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, hintx, hinty, hintz) # save receptor if receptor_save_path is not None: oedocking.OEWriteReceptorFile( receptor, str(pathlib.Path(receptor_save_path).absolute())) return receptor
def main(argv=[__name__]): if len(sys.argv) != 5: oechem.OEThrow.Usage( "MakeReceptorWithHintXYZ.py <protein> <hint x> <hint y> <hint z>") # @ <SNIPPET-MAKE-RECEPTOR-WITH-HINT-XYZ-1> protein = oechem.OEGraphMol() imstr = oechem.oemolistream(sys.argv[1]) oechem.OEReadMolecule(imstr, protein) hintX = float(sys.argv[2]) hintY = float(sys.argv[3]) hintZ = float(sys.argv[4]) receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, hintX, hintY, hintZ) # @ </SNIPPET-MAKE-RECEPTOR-WITH-HINT-XYZ-1> oedocking.OEWriteReceptorFile(receptor, "receptor.oeb.gz")
def main(argv): if len(argv) != 3: oechem.OEThrow.Usage( "MakeReceptorWithLigand.py <protein> <bound ligand>") proteinMolStream = oechem.oemolistream(argv[1]) ligandMolStream = oechem.oemolistream(argv[2]) # @ <SNIPPET-MAKE-RECEPTOR-WITH-LIGAND-1> protein = oechem.OEGraphMol() oechem.OEReadMolecule(proteinMolStream, protein) ligand = oechem.OEGraphMol() oechem.OEReadMolecule(ligandMolStream, ligand) receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, ligand) # @ </SNIPPET-MAKE-RECEPTOR-WITH-LIGAND-1> oedocking.OEWriteReceptorFile(receptor, "receptor.oeb.gz")
def main(argv=[__name__]): if len(argv) != 2: oechem.OEThrow.Usage("ToggleInterContour.py <receptor>") receptor = oechem.OEGraphMol() if not oedocking.OEReadReceptorFile(receptor, argv[1]): oechem.OEThrow.Fatal("Cannot read receptor") # @ <SNIPPET-TOGGLE-INNER-CONTOUR-1> innerContourLevel = oedocking.OEReceptorGetInnerContourLevel(receptor) oedocking.OEReceptorSetInnerContourLevel(receptor, -innerContourLevel) # @ </SNIPPET-TOGGLE-INNER-CONTOUR-1> if innerContourLevel > 0.0: oechem.OEThrow.Info("Toggling inner contour off") else: oechem.OEThrow.Info("Toggling inner contour on") if not oedocking.OEWriteReceptorFile(receptor, argv[1]): oechem.OEThrow.Fatal("Unable to write receptor")
def make_receptor( pdb): from openeye import oedocking, oechem import os.path file_name = str(os.path.basename(pdb)) check_oeb = conf['cache'] + file_name.split(".")[0] + ".oeb" if os.path.isfile(check_oeb): g = oechem.OEGraphMol() oedocking.OEReadReceptorFile(g, check_oeb) return g else: proteinStructure = oechem.OEGraphMol() ifs = oechem.oemolistream(pdb) ifs.SetFormat(oechem.OEFormat_PDB) oechem.OEReadMolecule(ifs, proteinStructure) box = oedocking.OEBox(*conf['bp_max'], *conf['bp_min']) receptor = oechem.OEGraphMol() s = oedocking.OEMakeReceptor(receptor, proteinStructure, box) oedocking.OEWriteReceptorFile(receptor, check_oeb) assert (s != False) return receptor
def create_hybrid_receptor(protein, ligand, receptor_save_path=None): """ Create a receptor for hybrid docking. Parameters ---------- protein: oechem.OEGraphMol An oechem.OEGraphMol object holding a prepared protein structure. ligand: oechem.OEGraphMol An oechem.OEGraphMol object holding a prepared ligand structure. receptor_save_path: str File path for saving created receptor. If receptor_save_path is not provided, receptor will not be saved. Returns ------- receptor: oechem.OEGraphMol An oechem.OEGraphMol object holding a receptor with protein and ligand. """ # Standard libraries import pathlib # External libraries from openeye import oechem, oedocking # create receptor receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, ligand) # save receptor if receptor_save_path is not None: oedocking.OEWriteReceptorFile( receptor, str(pathlib.Path(receptor_save_path).absolute())) return receptor
def main(argv=[__name__]): if len(sys.argv) != 8: oechem.OEThrow.Usage("MakeReceptorFromBox.py \ <protein> <xmax> <ymax> <zmax> <xmin> <ymin> <zmin>" ) xmax = float(sys.argv[2]) ymax = float(sys.argv[3]) zmax = float(sys.argv[4]) xmin = float(sys.argv[5]) ymin = float(sys.argv[6]) zmin = float(sys.argv[7]) # @ <SNIPPET-MAKE-RECEPTOR-WITH-BOX-1> imstr = oechem.oemolistream(sys.argv[1]) proteinStructure = oechem.OEGraphMol() oechem.OEReadMolecule(imstr, proteinStructure) box = oedocking.OEBox(xmax, ymax, zmax, xmin, ymin, zmin) receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, proteinStructure, box) # @ </SNIPPET-MAKE-RECEPTOR-WITH-BOX-1> oedocking.OEWriteReceptorFile(receptor, "receptor.oeb.gz")
def write_receptor(receptor: oechem.OEGraphMol, paths: List[Path]) -> None: for path in paths: # if not path.exists(): oedocking.OEWriteReceptorFile(oechem.OEGraphMol(receptor), str(path))
def hybrid_docking(receptor_path, molecules_path, docked_molecules_path, n_poses=10): """Automated hybrid docking of small molecules to a receptor. Parameters ---------- receptor_path : str Path to PDB file containing receptor and reference ligand, or pre-prepared receptor for docking molecules_path : str Path to file containing one or more molecules (in OpenEye readable format) to be docked. (For example, list of SMILES) docked_molecules_path : str Path to output file to be created to contain docked molecules Uses OpenEye recognized file extension, such as .mol2 or .sdf n_poses : int, optional, default=1 Number of docked poses to generate receptor_filename : str, optional, default=None If not None, the pre-prepared receptor is loaded TODO: How can this API be improved? """ from .docking import create_receptor, load_receptor, pose_molecule from openeye import oedocking, oechem #import openmoltools as moltools # TODO: Bring these methods into this module # Try to load pre-prepared receptor from specified file receptor = oechem.OEGraphMol() print('Attempting to load receptor from {}...'.format(receptor_path)) if not oedocking.OEReadReceptorFile(receptor, receptor_path): # Load complex of receptor and reference ligand complex_istream = oechem.oemolistream(receptor_path) complex = oechem.OEGraphMol() oechem.OEReadMolecule(complex_istream, complex) # Attempt to split into components and build receptor based on reference ligand print('Attempting to split complex into components...') ligand = oechem.OEGraphMol() protein = oechem.OEGraphMol() water = oechem.OEGraphMol() other = oechem.OEGraphMol() if oechem.OESplitMolComplex(ligand, protein, water, other, complex): # Create receptor using bound ligand reference print('Creating receptor using reference ligand...') oedocking.OEMakeReceptor(receptor, protein, ligand) # TODO: We can store prepared receptor file if desired oedocking.OEWriteReceptorFile( receptor, '/home/guoj1/projects/INSPIRE/kinomodel/kinomodel/data/docking/prepared_receptor.oeb' ) else: raise Exception( 'Could not split specified PDB file {} into receptor and reference ligand' .format(receptor_path)) # Open file for writing docked molecules docked_molecules_ostream = oechem.oemolostream(docked_molecules_path) # Configure omega # From canonical recipe: https://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html from openeye import oeomega omega = oeomega.OEOmega() omega.SetIncludeInput(False) omega.SetCanonOrder(False) omega.SetSampleHydrogens(True) eWindow = 15.0 omega.SetEnergyWindow(eWindow) omega.SetMaxConfs(800) omega.SetRMSThreshold(1.0) # Dock all molecules requested dock_method = oedocking.OEDockMethod_Hybrid2 dock_resolution = oedocking.OESearchResolution_Standard dock = oedocking.OEDock(dock_method, dock_resolution) dock.Initialize(receptor) molecules_istream = oechem.oemolistream(molecules_path) molecule = oechem.OEGraphMol() for molecule in molecules_istream.GetOEMols(): print("docking", molecule.GetTitle()) #docked_molecules = pose_molecule(receptor, molecule, n_poses=n_poses) #molecule = moltools.openeye.get_charges(molecule, keep_confs=10) # Generate conformers if not omega(molecule): continue # Apply charges from openeye import oequacpac oequacpac.OEAssignCharges(molecule, oequacpac.OEAM1BCCELF10Charges()) # Dock docked_molecule = oechem.OEGraphMol() dock.DockMultiConformerMolecule(docked_molecule, molecule) sdtag = oedocking.OEDockMethodGetName(dock_method) oedocking.OESetSDScore(docked_molecule, dock, sdtag) dock.AnnotatePose(docked_molecule) oechem.OEWriteMolecule(docked_molecules_ostream, docked_molecule)
def PrepareReceptor(pdb,padding=4,outpath=""): """ Prepares a receptor from a pdb with a crystalized ligand Padding controls the docking region. If outpath is given, PrepareReceptor will write an openeye binary (oeb) of the receptor structure. This will be faster than rebuilding the receptor every time. """ print("STOP CALLING THIS FUNCTION") exit() com = oechem.OEGraphMol() ifs = oechem.oemolistream() if ifs.open(pdb): oechem.OEReadPDBFile(ifs, com) ifs.close() """ Sorry, this requires some explanation. Openeye wasn't recognizing the previously docked ligand, so I tried to find other ways. The next blocks of code take our system and split it based on its connected components, for which its REQUIRED that our protein only has a single chain. It assumes that the last component is the ligand. It then creates the ligand (lig) and protein (prot) as separate molecules. Next, it finds the minimum and maximum 3D coordinates of the current ligand and produces a box around it with the specified padding. Finally it uses this box to create a 'receptor' object into which ligands can be docked. Only the receptor is returned. Openeye's docking shouldn't be this involved, but I couldn't get it to run the typical 'hybrid' docking without error. """ oechem.OEDetermineConnectivity(com) nparts, connect = oechem.OEDetermineComponents(com) if(nparts != 2): print("ERR in dock_conf::prepareReceptor. PDB doesn't have 2 connected components") exit() ## TODO: What is a good way to catch errors? # Get apo pred = oechem.OEPartPredAtom(connect) pred.SelectPart(nparts) lig = oechem.OEGraphMol() oechem.OESubsetMol(lig, com, pred) print(lig) # Get protein pred = oechem.OEPartPredAtom(connect) pred.SelectPart(1) prot = oechem.OEGraphMol() oechem.OESubsetMol(prot, com, pred) # Get box dimensions by iterating over ligand x_min = y_min = z_min = float('inf') x_max = y_max = z_max = -float('inf') crd = lig.GetCoords() print("CRD", crd) for atm in crd: x,y,z = crd[atm] if x < x_min: x_min = x if y < y_min: y_min = y if z < z_min: z_min = z if x > x_max: x_max = x if y > y_max: y_max = y if z > z_max: z_max = z x_min -= padding y_min -= padding z_min -= padding x_max += padding y_max += padding z_max += padding print(x_min,y_min,z_max, y_max) # Now prepare the receptor receptor = oechem.OEGraphMol() box = oedocking.OEBox() box.Setup(x_max, y_max, z_max, x_min, y_min, z_min) oedocking.OEMakeReceptor(receptor, prot, box) if not outpath == "": oedocking.OEWriteReceptorFile(receptor,f'{outpath}/receptor.oeb') return receptor
def prepare_receptor(complex_pdb_filename, output_basepath, dimer=False): """ Parameters ---------- complex_pdb_filename : str The complex PDB file to read in output_basepath : str Base path for output dimer : bool, optional, default=False If True, generate the dimer as the biological unit """ import os basepath, filename = os.path.split(complex_pdb_filename) prefix, extension = os.path.splitext(filename) prefix = os.path.join(output_basepath, prefix) # Check if receptor already exists receptor_filename = f'{prefix}-receptor.oeb.gz' thiolate_receptor_filename = f'{prefix}-receptor-thiolate.oeb.gz' if os.path.exists(receptor_filename) and os.path.exists( thiolate_receptor_filename): return # Read in PDB file pdbfile_lines = [ line for line in open(complex_pdb_filename, 'r') if 'UNK' not in line ] # If monomer is specified, drop crystal symmetry lines if not dimer: pdbfile_lines = [ line for line in pdbfile_lines if 'REMARK 350' not in line ] # Reconstruct PDBFile contents pdbfile_contents = ''.join(pdbfile_lines) # Read the receptor and identify design units from openeye import oespruce, oechem from tempfile import NamedTemporaryFile with NamedTemporaryFile(delete=False, mode='wt', suffix='.pdb') as pdbfile: pdbfile.write(pdbfile_contents) pdbfile.close() complex = read_pdb_file(pdbfile.name) # TODO: Clean up #print('Identifying design units...') design_units = list(oespruce.OEMakeDesignUnits(complex)) if len(design_units) == 1: design_unit = design_units[0] elif len(design_units) > 1: #print('More than one design unit found---using first one') design_unit = design_units[0] elif len(design_units) == 0: raise Exception(f' * No design units found for {complex_pdb_filename}') # Prepare the receptor #print('Preparing receptor...') from openeye import oedocking protein = oechem.OEGraphMol() design_unit.GetProtein(protein) ligand = oechem.OEGraphMol() design_unit.GetLigand(ligand) receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, ligand) oedocking.OEWriteReceptorFile(receptor, receptor_filename) with oechem.oemolostream(f'{prefix}-protein.pdb') as ofs: oechem.OEWriteMolecule(ofs, protein) with oechem.oemolostream(f'{prefix}-ligand.mol2') as ofs: oechem.OEWriteMolecule(ofs, ligand) with oechem.oemolostream(f'{prefix}-ligand.pdb') as ofs: oechem.OEWriteMolecule(ofs, ligand) with oechem.oemolostream(f'{prefix}-ligand.sdf') as ofs: oechem.OEWriteMolecule(ofs, ligand) # Filter out UNK from PDB files (which have covalent adducts) pdbfile_lines = [ line for line in open(f'{prefix}-protein.pdb', 'r') if 'UNK' not in line ] with open(f'{prefix}-protein.pdb', 'wt') as outfile: outfile.write(''.join(pdbfile_lines)) # Adjust protonation state of CYS145 to generate thiolate form #print('Deprotonating CYS145...') pred = oechem.OEAtomMatchResidue(["CYS:145: :A"]) for atom in protein.GetAtoms(pred): if oechem.OEGetPDBAtomIndex(atom) == oechem.OEPDBAtomName_SG: oechem.OESuppressHydrogens(atom) atom.SetFormalCharge(-1) atom.SetImplicitHCount(0) # Adjust protonation states #print('Re-optimizing hydrogen positions...') place_hydrogens_opts = oechem.OEPlaceHydrogensOptions() place_hydrogens_opts.SetBypassPredicate(pred) protonate_opts = oespruce.OEProtonateDesignUnitOptions( place_hydrogens_opts) success = oespruce.OEProtonateDesignUnit(design_unit, protonate_opts) design_unit.GetProtein(protein) # Old hacky way to adjust protonation states #opts = oechem.OEPlaceHydrogensOptions() #opts.SetBypassPredicate(pred) #describe = oechem.OEPlaceHydrogensDetails() #success = oechem.OEPlaceHydrogens(protein, describe, opts) #if success: # oechem.OEUpdateDesignUnit(design_unit, protein, oechem.OEDesignUnitComponents_Protein) # Write thiolate form of receptor receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, ligand) oedocking.OEWriteReceptorFile(receptor, thiolate_receptor_filename) with oechem.oemolostream(f'{prefix}-protein-thiolate.pdb') as ofs: oechem.OEWriteMolecule(ofs, protein) # Filter out UNK from PDB files (which have covalent adducts) pdbfile_lines = [ line for line in open(f'{prefix}-protein-thiolate.pdb', 'r') if 'UNK' not in line ] with open(f'{prefix}-protein-thiolate.pdb', 'wt') as outfile: outfile.write(''.join(pdbfile_lines))
def main(argv=[__name__]): if len(argv) != 3: oechem.OEThrow.Usage("%s <input receptor> <output receptor>" % argv[0]) # @ <SNIPPET-RECEPTOR-IO-1> receptor = oechem.OEGraphMol() inputReceptorFilename = argv[1] oedocking.OEReadReceptorFile(receptor, inputReceptorFilename) # @ </SNIPPET-RECEPTOR-IO-1> # @ <SNIPPET-RECEPTOR-IO-2> outputReceptorFilename = argv[2] oedocking.OEWriteReceptorFile(receptor, outputReceptorFilename) # @ </SNIPPET-RECEPTOR-IO-2> # @<SNIPPET-RECEPTOR-IO-3> bytes = oedocking.OEWriteReceptorToBytes(".oeb", receptor) receptorIO = oechem.OEGraphMol() status = oedocking.OEReadReceptorFromBytes(receptorIO, ".oeb", bytes) # @</SNIPPET-RECEPTOR-IO-3> print("SNIPPET-RECEPTOR-IO-3: .oeb status={} nbytes={}".format(status, len(bytes))) # @<SNIPPET-RECEPTOR-IO-4> bytes = oedocking.OEWriteReceptorToBytes(".oeb.gz", receptor) receptorIO = oechem.OEGraphMol() status = oedocking.OEReadReceptorFromBytes(receptorIO, ".oeb.gz", bytes) # @</SNIPPET-RECEPTOR-IO-4> print("SNIPPET-RECEPTOR-IO-4: .oeb.gz status={} nbytes={}".format(status, len(bytes))) # @<SNIPPET-RECEPTOR-IO-5> bytes = oedocking.OEWriteReceptorToBytes(".json", receptor) receptorIO = oechem.OEGraphMol() status = oedocking.OEReadReceptorFromBytes(receptorIO, ".json", bytes) # @</SNIPPET-RECEPTOR-IO-5> print("SNIPPET-RECEPTOR-IO-5: .json status={} nbytes={}".format(status, len(bytes))) # @<SNIPPET-RECEPTOR-IO-6> bytes = oedocking.OEWriteReceptorToBytes(".json.gz", receptor) receptorIO = oechem.OEGraphMol() status = oedocking.OEReadReceptorFromBytes(receptorIO, ".json.gz", bytes) # @</SNIPPET-RECEPTOR-IO-6> print("SNIPPET-RECEPTOR-IO-6: .json.gz status={} nbytes={}".format(status, len(bytes))) # @<SNIPPET-RECEPTOR-IO-7> gzip = False bytes = oedocking.OEWriteReceptorToBytes(oechem.OEFormat_OEB, oechem.OEGetDefaultOFlavor(oechem.OEFormat_OEB), gzip, receptor) receptorIO = oechem.OEGraphMol() status = oedocking.OEReadReceptorFromBytes(receptorIO, oechem.OEFormat_OEB, oechem.OEGetDefaultIFlavor(oechem.OEFormat_OEB), gzip, bytes) # @</SNIPPET-RECEPTOR-IO-7> print("SNIPPET-RECEPTOR-IO-7: .oeb status={} nbytes={}".format(status, len(bytes))) # @<SNIPPET-RECEPTOR-IO-8> gzip = True bytes = oedocking.OEWriteReceptorToBytes(oechem.OEFormat_OEB, oechem.OEGetDefaultOFlavor(oechem.OEFormat_OEB), gzip, receptor) receptorIO = oechem.OEGraphMol() status = oedocking.OEReadReceptorFromBytes(receptorIO, oechem.OEFormat_OEB, oechem.OEGetDefaultIFlavor(oechem.OEFormat_OEB), gzip, bytes) # @</SNIPPET-RECEPTOR-IO-8> print("SNIPPET-RECEPTOR-IO-8: .oeb.gz status={} nbytes={}".format(status, len(bytes))) # @<SNIPPET-RECEPTOR-IO-9> gzip = False bytes = oedocking.OEWriteReceptorToBytes(oechem.OEFormat_JSON, oechem.OEGetDefaultOFlavor(oechem.OEFormat_JSON), gzip, receptor) receptorIO = oechem.OEGraphMol() status = oedocking.OEReadReceptorFromBytes(receptorIO, oechem.OEFormat_JSON, oechem.OEGetDefaultIFlavor(oechem.OEFormat_JSON), gzip, bytes) # @</SNIPPET-RECEPTOR-IO-9> print("SNIPPET-RECEPTOR-IO-9: .json status={} nbytes={}".format(status, len(bytes))) # @<SNIPPET-RECEPTOR-IO-10> gzip = True bytes = oedocking.OEWriteReceptorToBytes(oechem.OEFormat_JSON, oechem.OEGetDefaultOFlavor(oechem.OEFormat_JSON), gzip, receptor) receptorIO = oechem.OEGraphMol() status = oedocking.OEReadReceptorFromBytes(receptorIO, oechem.OEFormat_JSON, oechem.OEGetDefaultIFlavor(oechem.OEFormat_JSON), gzip, bytes) # @</SNIPPET-RECEPTOR-IO-10> print("SNIPPET-RECEPTOR-IO-10: .json.gz status={} nbytes={}".format(status, len(bytes)))
def prepare_receptor(complex_pdb_filename, output_basepath, dimer=False, retain_water=False): """ Parameters ---------- complex_pdb_filename : str The complex PDB file to read in output_basepath : str Base path for output dimer : bool, optional, default=False If True, generate the dimer as the biological unit retain_water : bool, optional, default=False If True, will retain waters """ # Check whether this is a diamond SARS-CoV-2 Mpro structure or not import re is_diamond_structure = (re.search('-x\d+_', complex_pdb_filename) is not None) import os basepath, filename = os.path.split(complex_pdb_filename) prefix, extension = os.path.splitext(filename) prefix = os.path.join(output_basepath, prefix) # Check if receptor already exists receptor_filename = f'{prefix}-receptor.oeb.gz' thiolate_receptor_filename = f'{prefix}-receptor-thiolate.oeb.gz' if os.path.exists(receptor_filename) and os.path.exists( thiolate_receptor_filename): return # Read in PDB file, skipping UNK atoms (left over from processing covalent ligands) pdbfile_lines = [ line for line in open(complex_pdb_filename, 'r') if 'UNK' not in line ] # Check if biological symmetry header is present has_biological_symmetry_header = False for line in pdbfile_lines: if 'REMARK 350' in line: has_biological_symmetry_header = True break # Prepend REMARK 350 (biological symmetry) header lines for Mpro (from 5RGG) if not present if is_diamond_structure and (not has_biological_symmetry_header): pdbfile_lines = [ line + '\n' for line in BIOLOGICAL_SYMMETRY_HEADER.split('\n') ] + pdbfile_lines # If monomer is specified, drop crystal symmetry lines if not dimer: pdbfile_lines = [ line for line in pdbfile_lines if 'REMARK 350' not in line ] # Filter out waters if not retain_water: pdbfile_lines = [line for line in pdbfile_lines if 'HOH' not in line] # Filter out LINK records to covalent inhibitors so we can model non-covalent complex pdbfile_lines = [line for line in pdbfile_lines if 'LINK' not in line] # Reconstruct PDBFile contents pdbfile_contents = ''.join(pdbfile_lines) # Append SEQRES to all structures if they do not have it seqres = """\ SEQRES 1 A 306 SER GLY PHE ARG LYS MET ALA PHE PRO SER GLY LYS VAL SEQRES 2 A 306 GLU GLY CYS MET VAL GLN VAL THR CYS GLY THR THR THR SEQRES 3 A 306 LEU ASN GLY LEU TRP LEU ASP ASP VAL VAL TYR CYS PRO SEQRES 4 A 306 ARG HIS VAL ILE CYS THR SER GLU ASP MET LEU ASN PRO SEQRES 5 A 306 ASN TYR GLU ASP LEU LEU ILE ARG LYS SER ASN HIS ASN SEQRES 6 A 306 PHE LEU VAL GLN ALA GLY ASN VAL GLN LEU ARG VAL ILE SEQRES 7 A 306 GLY HIS SER MET GLN ASN CYS VAL LEU LYS LEU LYS VAL SEQRES 8 A 306 ASP THR ALA ASN PRO LYS THR PRO LYS TYR LYS PHE VAL SEQRES 9 A 306 ARG ILE GLN PRO GLY GLN THR PHE SER VAL LEU ALA CYS SEQRES 10 A 306 TYR ASN GLY SER PRO SER GLY VAL TYR GLN CYS ALA MET SEQRES 11 A 306 ARG PRO ASN PHE THR ILE LYS GLY SER PHE LEU ASN GLY SEQRES 12 A 306 SER CYS GLY SER VAL GLY PHE ASN ILE ASP TYR ASP CYS SEQRES 13 A 306 VAL SER PHE CYS TYR MET HIS HIS MET GLU LEU PRO THR SEQRES 14 A 306 GLY VAL HIS ALA GLY THR ASP LEU GLU GLY ASN PHE TYR SEQRES 15 A 306 GLY PRO PHE VAL ASP ARG GLN THR ALA GLN ALA ALA GLY SEQRES 16 A 306 THR ASP THR THR ILE THR VAL ASN VAL LEU ALA TRP LEU SEQRES 17 A 306 TYR ALA ALA VAL ILE ASN GLY ASP ARG TRP PHE LEU ASN SEQRES 18 A 306 ARG PHE THR THR THR LEU ASN ASP PHE ASN LEU VAL ALA SEQRES 19 A 306 MET LYS TYR ASN TYR GLU PRO LEU THR GLN ASP HIS VAL SEQRES 20 A 306 ASP ILE LEU GLY PRO LEU SER ALA GLN THR GLY ILE ALA SEQRES 21 A 306 VAL LEU ASP MET CYS ALA SER LEU LYS GLU LEU LEU GLN SEQRES 22 A 306 ASN GLY MET ASN GLY ARG THR ILE LEU GLY SER ALA LEU SEQRES 23 A 306 LEU GLU ASP GLU PHE THR PRO PHE ASP VAL VAL ARG GLN SEQRES 24 A 306 CYS SER GLY VAL THR PHE GLN """ has_seqres = 'SEQRES' in pdbfile_contents if not has_seqres: #print('Adding SEQRES') pdbfile_contents = seqres + pdbfile_contents # Read the receptor and identify design units from openeye import oespruce, oechem from tempfile import NamedTemporaryFile with NamedTemporaryFile(delete=False, mode='wt', suffix='.pdb') as pdbfile: pdbfile.write(pdbfile_contents) pdbfile.close() complex = read_pdb_file(pdbfile.name) # TODO: Clean up # Strip protons from structure to allow SpruceTK to add these back # See: 6wnp, 6wtj, 6wtk, 6xb2, 6xqs, 6xqt, 6xqu, 6m2n #print('Suppressing hydrogens') #print(f' Initial: {sum([1 for atom in complex.GetAtoms()])} atoms') for atom in complex.GetAtoms(): if atom.GetAtomicNum() > 1: oechem.OESuppressHydrogens(atom) #print(f' Final: {sum([1 for atom in complex.GetAtoms()])} atoms') # Delete and rebuild C-terminal residue because Spruce causes issues with this # See: 6m2n 6lze #print('Deleting C-terminal residue O') pred = oechem.OEIsCTerminalAtom() for atom in complex.GetAtoms(): if pred(atom): for nbor in atom.GetAtoms(): if oechem.OEGetPDBAtomIndex(nbor) == oechem.OEPDBAtomName_O: complex.DeleteAtom(nbor) #pred = oechem.OEAtomMatchResidue(["GLN:306:.*:.*:.*"]) #for atom in complex.GetAtoms(pred): # if oechem.OEGetPDBAtomIndex(atom) == oechem.OEPDBAtomName_O: # print('Deleting O') # complex.DeleteAtom(atom) #het = oespruce.OEHeterogenMetadata() #het.SetTitle("LIG") # real ligand 3 letter code #het.SetID("CovMoonShot1234") # in case you have corporate IDs #het.SetType(oespruce.OEHeterogenType_Ligand) # mdata.AddHeterogenMetadata(het) #print('Identifying design units...') # Produce zero design units if we fail to protonate # Log warnings errfs = oechem.oeosstream( ) # create a stream that writes internally to a stream oechem.OEThrow.SetOutputStream(errfs) oechem.OEThrow.Clear() oechem.OEThrow.SetLevel( oechem.OEErrorLevel_Verbose) # capture verbose error output opts = oespruce.OEMakeDesignUnitOptions() #print(f'ligand atoms: min {opts.GetSplitOptions().GetMinLigAtoms()}, max {opts.GetSplitOptions().GetMaxLigAtoms()}') opts.GetSplitOptions().SetMinLigAtoms( 7) # minimum fragment size (in heavy atoms) mdata = oespruce.OEStructureMetadata() opts.GetPrepOptions().SetStrictProtonationMode(True) # Both N- and C-termini should be zwitterionic # Mpro cleaves its own N- and C-termini # See https://www.pnas.org/content/113/46/12997 opts.GetPrepOptions().GetBuildOptions().SetCapNTermini(False) opts.GetPrepOptions().GetBuildOptions().SetCapCTermini(False) # Don't allow truncation of termini, since force fields don't have parameters for this opts.GetPrepOptions().GetBuildOptions().GetCapBuilderOptions( ).SetAllowTruncate(False) # Build loops and sidechains opts.GetPrepOptions().GetBuildOptions().SetBuildLoops(True) opts.GetPrepOptions().GetBuildOptions().SetBuildSidechains(True) # Don't flip Gln189 #pred = oechem.OEAtomMatchResidue(["GLN:189: :A"]) pred = oechem.OEAtomMatchResidue(["GLN:189:.*:.*:.*"]) protonate_opts = opts.GetPrepOptions().GetProtonateOptions() place_hydrogens_opts = protonate_opts.GetPlaceHydrogensOptions() #place_hydrogens_opts.SetBypassPredicate(pred) place_hydrogens_opts.SetNoFlipPredicate(pred) #protonate_opts = oespruce.OEProtonateDesignUnitOptions(place_hydrogens_opts) #opts.GetPrepOptions().SetProtonateOptions(protonate_options); # Make design units design_units = list(oespruce.OEMakeDesignUnits(complex, mdata, opts)) # Restore error stream oechem.OEThrow.SetOutputStream(oechem.oeerr) # Capture the warnings to a string warnings = errfs.str().decode("utf-8") if len(design_units) >= 1: design_unit = design_units[0] print('') print('') print(f'{complex_pdb_filename} : SUCCESS') print(warnings) elif len(design_units) == 0: print('') print('') print(f'{complex_pdb_filename} : FAILURE') print(warnings) msg = f'No design units found for {complex_pdb_filename}\n' msg += warnings msg += '\n' raise Exception(msg) # Prepare the receptor #print('Preparing receptor...') from openeye import oedocking protein = oechem.OEGraphMol() design_unit.GetProtein(protein) ligand = oechem.OEGraphMol() design_unit.GetLigand(ligand) # Create receptor and other files receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, ligand) oedocking.OEWriteReceptorFile(receptor, receptor_filename) with oechem.oemolostream(f'{prefix}-protein.pdb') as ofs: oechem.OEWriteMolecule(ofs, protein) with oechem.oemolostream(f'{prefix}-ligand.mol2') as ofs: oechem.OEWriteMolecule(ofs, ligand) with oechem.oemolostream(f'{prefix}-ligand.pdb') as ofs: oechem.OEWriteMolecule(ofs, ligand) with oechem.oemolostream(f'{prefix}-ligand.sdf') as ofs: oechem.OEWriteMolecule(ofs, ligand) # Filter out UNK from PDB files (which have covalent adducts) pdbfile_lines = [ line for line in open(f'{prefix}-protein.pdb', 'r') if 'UNK' not in line ] with open(f'{prefix}-protein.pdb', 'wt') as outfile: outfile.write(''.join(pdbfile_lines)) # Adjust protonation state of CYS145 to generate thiolate form #print('Deprotonating CYS145...') # DEBUG #pred = oechem.OEAtomMatchResidue(["CYS:145: :A"]) pred = oechem.OEAtomMatchResidue(["CYS:145:.*:.*:.*"]) place_hydrogens_opts.SetBypassPredicate(pred) for atom in protein.GetAtoms(pred): if oechem.OEGetPDBAtomIndex(atom) == oechem.OEPDBAtomName_SG: #print('Modifying CYS 145 SG') oechem.OESuppressHydrogens(atom) atom.SetFormalCharge(-1) atom.SetImplicitHCount(0) #print('Protonating HIS41...') # DEBUG #pred = oechem.OEAtomMatchResidue(["HIS:41: :A"]) pred = oechem.OEAtomMatchResidue(["HIS:41:.*:.*:.*"]) place_hydrogens_opts.SetBypassPredicate(pred) for atom in protein.GetAtoms(pred): if oechem.OEGetPDBAtomIndex(atom) == oechem.OEPDBAtomName_ND1: #print('Protonating HIS 41 ND1') oechem.OESuppressHydrogens(atom) # strip hydrogens from residue atom.SetFormalCharge(+1) atom.SetImplicitHCount(1) # Update the design unit with the modified formal charge for CYS 145 SG oechem.OEUpdateDesignUnit(design_unit, protein, oechem.OEDesignUnitComponents_Protein) # Don't flip Gln189 #pred = oechem.OEAtomMatchResidue(["GLN:189: :A"]) #protonate_opts = opts.GetPrepOptions().GetProtonateOptions(); #place_hydrogens_opts = protonate_opts.GetPlaceHydrogensOptions() #place_hydrogens_opts.SetNoFlipPredicate(pred) # Adjust protonation states #print('Re-optimizing hydrogen positions...') # DEBUG #place_hydrogens_opts = oechem.OEPlaceHydrogensOptions() #place_hydrogens_opts.SetBypassPredicate(pred) #protonate_opts = oespruce.OEProtonateDesignUnitOptions(place_hydrogens_opts) success = oespruce.OEProtonateDesignUnit(design_unit, protonate_opts) design_unit.GetProtein(protein) # Write thiolate form of receptor receptor = oechem.OEGraphMol() oedocking.OEMakeReceptor(receptor, protein, ligand) oedocking.OEWriteReceptorFile(receptor, thiolate_receptor_filename) with oechem.oemolostream(f'{prefix}-protein-thiolate.pdb') as ofs: oechem.OEWriteMolecule(ofs, protein) # Filter out UNK from PDB files (which have covalent adducts) pdbfile_lines = [ line for line in open(f'{prefix}-protein-thiolate.pdb', 'r') if 'UNK' not in line ] with open(f'{prefix}-protein-thiolate.pdb', 'wt') as outfile: outfile.write(''.join(pdbfile_lines))