def createMolecule(self, mol, molTitle): ''' Get a OE residue, return a OE molecule ''' # Creating a new Res GraphMol newMol = oechem.OEGraphMol() newMol.SetTitle(molTitle) # Create every atom found in the OEHierResidue for atom in mol.GetAtoms(): newMol.NewAtom(atom) #---------------------------------------------# # Recreate the molecule from atom coordinates # #---------------------------------------------# # Using OpenEye's charge model. Works on molecules with fully specified # hydrogen counts. Charge determined based on atom valence. oechem.OEDetermineConnectivity(newMol) oechem.OEFindRingAtomsAndBonds(newMol) oechem.OEPerceiveBondOrders(newMol) oechem.OEAssignImplicitHydrogens(newMol) oechem.OEAssignFormalCharges(newMol) # Other things to consider # Set atom radius #oechem.OEAssignBondiVdWRadii(newMol) #oechem.OEAssignPartialCharges(newMol, # oechem.OECharges_None, # False, # False) return newMol
def mol_from_json(symbols, connectivity, geometry, permute_xyz=False): """ Generate OEMol from QCSchema molecule specs Parameters ---------- inp_molecule: dict Must have symbols and connectivity and/or geometry Note: If geometry is given, the molecule will have a tag indicating that the goemetry came from QCSchema. This will ensure that the order of the atoms and configuration is not change for generation of mapped SMILES and isomeric SMILES. Returns ------- molecule: OEMol """ molecule = oechem.OEMol() for s in symbols: molecule.NewAtom(_symbols[s]) # Add connectivity for bond in connectivity: a1 = molecule.GetAtom(oechem.OEHasAtomIdx(bond[0])) a2 = molecule.GetAtom(oechem.OEHasAtomIdx(bond[1])) bond_order = bond[-1] if not isinstance(bond_order, int) and not bond_order.is_integer(): raise ValueError( "bond order must be a whole number. A bond order of 1.5 is not allowed" ) molecule.NewBond(a1, a2, int(bond_order)) # Add geometry if molecule.NumAtoms() != geometry.shape[0] / 3: raise ValueError( "Number of atoms in molecule does not match length of position array" ) molecule.SetCoords(oechem.OEFloatArray(geometry)) molecule.SetDimension(3) if not permute_xyz: # Add tag that the geometry is from JSON and shouldn't be changed. geom_tag = oechem.OEGetTag("json_geometry") molecule.SetData(geom_tag, True) oechem.OEDetermineConnectivity(molecule) oechem.OEFindRingAtomsAndBonds(molecule) # No need to perceive Bond Order because the information was added from the connectivity table. Apparently, this # function does many different perceptions under the hood and it can add implicit hydrogens to divalent N that should be negatively charged. #oechem.OEPerceiveBondOrders(molecule) # This seems to add hydrogens that are not in the json #oechem.OEAssignImplicitHydrogens(molecule) oechem.OEAssignFormalCharges(molecule) oechem.OEAssignAromaticFlags(molecule) oechem.OEPerceiveChiral(molecule) oechem.OE3DToAtomStereo(molecule) oechem.OE3DToBondStereo(molecule) return molecule
def mol_from_json(symbols, connectivity, geometry, permute_xyz=False): """ Generate OEMol from QCSchema molecule specs Parameters ---------- inp_molecule: dict Must have symbols and connectivity and/or geometry Note: If geometry is given, the molecule will have a tag indicating that the goemetry came from QCSchema. This will ensure that the order of the atoms and configuration is not change for generation of mapped SMILES and isomeric SMILES. Returns ------- molecule: OEMol """ molecule = oechem.OEMol() for s in symbols: molecule.NewAtom(_symbols[s]) # Add connectivity for bond in connectivity: a1 = molecule.GetAtom(oechem.OEHasAtomIdx(bond[0])) a2 = molecule.GetAtom(oechem.OEHasAtomIdx(bond[1])) molecule.NewBond(a1, a2, bond[-1]) # Add geometry if molecule.NumAtoms() != geometry.shape[0] / 3: raise ValueError( "Number of atoms in molecule does not match length of position array" ) molecule.SetCoords(oechem.OEFloatArray(geometry)) molecule.SetDimension(3) if not permute_xyz: # Add tag that the geometry is from JSON and shouldn't be changed. geom_tag = oechem.OEGetTag("json_geometry") molecule.SetData(geom_tag, True) oechem.OEDetermineConnectivity(molecule) oechem.OEFindRingAtomsAndBonds(molecule) oechem.OEPerceiveBondOrders(molecule) # This seems to add hydrogens that are not in the json #oechem.OEAssignImplicitHydrogens(molecule) oechem.OEAssignFormalCharges(molecule) oechem.OEAssignAromaticFlags(molecule) oechem.OEPerceiveChiral(molecule) oechem.OE3DToAtomStereo(molecule) oechem.OE3DToBondStereo(molecule) return molecule
def _process_mol(mol: oechem.OEMol, explicit_H: Optional[str] = None): if explicit_H == 'all': oechem.OEAddExplicitHydrogens(mol) elif explicit_H == 'polar': oechem.OESuppressHydrogens(mol, explicit_H) elif explicit_H is None: oechem.OESuppressHydrogens(mol) else: raise ValueError oechem.OEAssignAromaticFlags(mol) oechem.OEAssignHybridization(mol) oechem.OEAssignFormalCharges(mol) mol.Sweep()
def get_sf_elements(mol): sfObj = SymmetryFunction() oechem.OEAssignFormalCharges(mol) oechem.OEAssignHybridization(mol) rsf, asf = sfObj.CalculateSymmetryFunction(mol) tsf1 = sfObj.CalculateTorsionSymmetryFunction(mol, 1) tsf2 = sfObj.CalculateTorsionSymmetryFunction(mol, 2) tsf = [] for elem1, elem2 in zip(tsf1, tsf2): tsf.append(elem1 + elem2) sf_elements = rsf sf_elements.extend(asf) sf_elements.extend(tsf) return sf_elements
def generate_molecule_from_smiles(smiles, idx=0): """ Generate oemol with geometry from smiles """ print("Molecule %d is %s" % (idx, smiles)) mol = oechem.OEMol() mol.SetTitle("MOL%d" % idx) oechem.OESmilesToMol(mol, smiles) oechem.OEAddExplicitHydrogens(mol) oechem.OETriposAtomNames(mol) oechem.OETriposBondTypeNames(mol) oechem.OEAssignFormalCharges(mol) omega = oeomega.OEOmega() omega.SetMaxConfs(1) omega.SetStrictStereo(False) mol.SetTitle("MOL_%d" % idx) omega(mol) return mol
def _computeNetCharge(molecule): """ Compute the net formal charge on the molecule. Formal charges are assigned by this function. Parameters ---------- molecule : openeye.oechem.OEMol The molecule for which a net formal charge is to be computed Returns ------- net_charge : float The net formal charge on the molecule """ from openeye import oechem oechem.OEAssignFormalCharges(molecule) charges = [atom.GetFormalCharge() for atom in molecule.GetAtoms()] net_charge = np.array(charges).sum() return net_charge
def generateOEMolFromTopologyResidue(residue, geometry=False, tripos_atom_names=False): """ Generate an OpenEye OEMol molecule from an OpenMM Topology Residue. Parameters ---------- residue : simtk.openmm.app.topology.Residue The topology Residue from which an OEMol is to be created. An Exception will be thrown if this residue has external bonds. geometry : bool, optional, default=False If True, will generate a single configuration with OEOmega. Note that stereochemistry will be *random*. tripos_atom_names : bool, optional, default=False If True, will generate and assign Tripos atom names. Returns ------- molecule : openeye.oechem.OEMol The OEMol molecule corresponding to the topology. Atom order will be preserved and bond orders assigned. The Antechamber `bondtype` program will be used to assign bond orders, and these will be converted back into OEMol bond type assignments. Note that there is no way to preserve stereochemistry since `Residue` does not note stereochemistry in any way. """ # Raise an Exception if this residue has external bonds. if len(list(residue.external_bonds())) > 0: raise Exception( "Cannot generate an OEMol from residue '%s' because it has external bonds." % residue.name) from openeye import oechem # Create OEMol where all atoms have bond order 1. molecule = oechem.OEMol() molecule.SetTitle(residue.name) # name molecule after first residue for atom in residue.atoms(): oeatom = molecule.NewAtom(atom.element.atomic_number) oeatom.SetName(atom.name) oeatom.AddData("topology_index", atom.index) oeatoms = {oeatom.GetName(): oeatom for oeatom in molecule.GetAtoms()} for (atom1, atom2) in residue.bonds(): order = 1 molecule.NewBond(oeatoms[atom1.name], oeatoms[atom2.name], order) # Write out a mol2 file without altering molecule. import tempfile tmpdir = tempfile.mkdtemp() mol2_input_filename = os.path.join(tmpdir, 'molecule-before-bond-perception.mol2') ac_output_filename = os.path.join(tmpdir, 'molecule-after-bond-perception.ac') ofs = oechem.oemolostream(mol2_input_filename) m2h = True substruct = False oechem.OEWriteMol2File(ofs, molecule, m2h, substruct) ofs.close() # Run Antechamber bondtype import subprocess #command = 'bondtype -i %s -o %s -f mol2 -j full' % (mol2_input_filename, ac_output_filename) command = 'antechamber -i %s -fi mol2 -o %s -fo ac -j 2' % ( mol2_input_filename, ac_output_filename) [status, output] = getstatusoutput(command) # Define mapping from GAFF bond orders to OpenEye bond orders. order_map = {1: 1, 2: 2, 3: 3, 7: 1, 8: 2, 9: 5, 10: 5} # Read bonds. infile = open(ac_output_filename) lines = infile.readlines() infile.close() antechamber_bond_types = list() for line in lines: elements = line.split() if elements[0] == 'BOND': antechamber_bond_types.append(int(elements[4])) oechem.OEClearAromaticFlags(molecule) for (bond, antechamber_bond_type) in zip(molecule.GetBonds(), antechamber_bond_types): #bond.SetOrder(order_map[antechamber_bond_type]) bond.SetIntType(order_map[antechamber_bond_type]) oechem.OEFindRingAtomsAndBonds(molecule) oechem.OEKekulize(molecule) oechem.OEAssignFormalCharges(molecule) oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) # Clean up. os.unlink(mol2_input_filename) os.unlink(ac_output_filename) os.rmdir(tmpdir) # Generate Tripos atom names if requested. if tripos_atom_names: oechem.OETriposAtomNames(molecule) # Assign geometry if geometry: from openeye import oeomega omega = oeomega.OEOmega() omega.SetMaxConfs(1) omega.SetIncludeInput(False) omega.SetStrictStereo(False) omega(molecule) return molecule
def main(): opt = parser.parse_args() global which_gaff if opt.gaff: which_gaff = opt.gaff else: which_gaff = 1 # 2--> gaff2 global lig_input_mol2 if opt.lig: lig_input_mol2 = opt.lig else: lig_input_mol2 = 'lig_in.mol2' # ============== # # new protocol: # (1) amber bond typer --> ac file (2) openeye convert aromatic mol2 --> kekule form assignment with oechem.OEKekulize(mol) # ============== # command = '$AMBERHOME/bin/antechamber -i %s -fi mol2 -o lig.ac -fo ac -j 2 -dr n -pf y' % lig_input_mol2 print(command) subprocess.call(command, shell=True) molecule = oechem.OEGraphMol() ifs = oechem.oemolistream(lig_input_mol2) flavor = oechem.OEIFlavor_Generic_Default | oechem.OEIFlavor_MOL2_Default | oechem.OEIFlavor_MOL2_Forcefield ifs.SetFlavor(oechem.OEFormat_MOL2, flavor) oechem.OEReadMol2File(ifs, molecule) print(molecule.GetTitle()) # Define mapping from GAFF bond orders to OpenEye bond orders. order_map = {1: 1, 2: 2, 3: 3, 7: 1, 8: 2, 9: 5, 10: 5} # Read bonds. infile = open('lig.ac') lines = infile.readlines() infile.close() antechamber_bond_types = list() for line in lines: elements = line.split() if elements[0] == 'BOND': antechamber_bond_types.append(int(elements[4])) oechem.OEClearAromaticFlags(molecule) for (bond, antechamber_bond_type) in zip(molecule.GetBonds(), antechamber_bond_types): #bond.SetOrder(order_map[antechamber_bond_type]) bond.SetIntType(order_map[antechamber_bond_type]) oechem.OEFindRingAtomsAndBonds(molecule) oechem.OEKekulize(molecule) oechem.OEAssignFormalCharges(molecule) oechem.OEAssignAromaticFlags(molecule, oechem.OEAroModelOpenEye) """ charges = [ atom.GetFormalCharge() for atom in molecule.GetAtoms() ] net_charge = np.array(charges).sum() print("Net Charge:", net_charge) """ subprocess.call('grep CHARGE lig.ac', shell=True) with open('lig.ac', "r") as f: line = f.readline() # if line.find("CHARGE") > -1 and len(line.split())> 2: # net_charge = int( float( line.split()[1] ) ) if line.find("CHARGE") > -1: net_charge = int(line[line.find("(") + 1:line.find(")")]) print("Net Charge:", net_charge) # Write mol2 file for this molecule. outmol = oechem.OEMol(molecule) ofs = oechem.oemolostream() filename = 'lig_oe.mol2' ofs.open(filename) oechem.OEWriteMolecule(ofs, outmol) ofs.close() if which_gaff == 1: gaff = "gaff" elif which_gaff == 2: gaff = "gaff2" command = "$AMBERHOME/bin/antechamber -i lig_oe.mol2 -fi mol2 -o lig_bcc.mol2 -fo mol2 -c bcc -at %s -nc %i -j 5 -pf y -dr n" \ % (gaff, net_charge) print(command) subprocess.call(command, shell=True) command = "$AMBERHOME/bin/parmchk2 -i lig_bcc.mol2 -f mol2 -s %d -o lig.frcmod" % ( which_gaff) print(command) subprocess.call(command, shell=True)
def mk_conformers(options, molecule, maxconf=99, verbose=True): """ Enumerate the list of conformers and associated properties for each protonation and tautomeric state. Parameters ---------- options molecule : openeye.oechem The molecule read from the PDB whose protomer and tautomer states are to be enumerated. maxconf : int, optional, default=128 Maximum number of protomers/tautomers to generate. Returns ------- conformers : list of Conformer The list of protomers/tautomers generated. """ conformers = list() formalChargeOptions = oequacpac.OEFormalChargeOptions(maxconf) tautomerOptions = oequacpac.OETautomerOptions(maxconf) # enumerate pka states index = 0 for pkaState in oequacpac.OEEnumerateFormalCharges(molecule, formalChargeOptions): if (index > maxconf): break # enumerate tautomers of pka states for tautomer in oequacpac.OEEnumerateTautomers(pkaState, tautomerOptions): if (index > maxconf): break # Assign conformer name. name = options.ligand+'%02d' % index tautomer.SetTitle(name) # DEBUG: Write molecule before charging. ofs = oechem.oemolostream() ofs.open(name + '-before.mol2') outmol = oechem.OEMol(tautomer) oechem.OEWriteMolecule(ofs, outmol) ofs.close() # Compute formal charge. oechem.OEAssignFormalCharges(tautomer) formal_charge = 0.0 for atom in tautomer.GetAtoms(): formal_charge += atom.GetFormalCharge() if verbose: print "formal charge: %d" % formal_charge # Assign canonical AM1BCC charges. assign_canonical_am1bcc_charges(tautomer) # DEBUG: Write molecule after charging. ofs = oechem.oemolostream() outmol = oechem.OEMol(tautomer) ofs.open(name + '-after.mol2') oechem.OEWriteMolecule(ofs, outmol) ofs.close() # Create conformer. conformer = Conformer(name, formal_charge, tautomer) # Append to protomer/tautomer list. conformers.append(conformer) # Keep count of protomers/tautomers. index += 1 # Show output if requested. if verbose: print "%12s %+5d %8d atoms" % (name, conformer.charge, conformer.natoms) if verbose: print "%d protomer/tautomer states were enumerated" % len(conformers) return conformers
def mk_conformers_epik(options, molecule, maxconf=99, verbose=True, pH=7): """ Enumerate the list of conformers and associated properties for each protonation and tautomeric state using epik from the Schrodinger Suite. Parameters ---------- options molecule : openeye.oechem The molecule read from the PDB whose protomer and tautomer states are to be enumerated. maxconf : int, optional, default=128 Maximum number of protomers/tautomers to generate. pH : float, optional, default=7.0 pH to use for conformer enumeration Returns ------- conformers : list of Conformer The list of protomers/tautomers generated. """ from schrodinger import structure # Requires Schrodinger Suite # Write mol2 file. if verbose: print "Writing input file as mol2..." outmol = oechem.OEMol(molecule) ofs = oechem.oemolostream() ofs.open('epik-input.mol2') oechem.OEWriteMolecule(ofs, outmol) ofs.close() # Use low level writer to get atom names correct. ofs = oechem.oemolostream() ofs.open('epik-input.mol2') for (dest_atom, src_atom) in zip(outmol.GetAtoms(), molecule.GetAtoms()): dest_atom.SetName(src_atom.GetName()) oechem.OEWriteMol2File(ofs, outmol, True) ofs.close() # Write mol2 file. if verbose: print "Writing input file as sdf..." outmol = oechem.OEMol(molecule) ofs = oechem.oemolostream() ofs.open('epik-input.sdf') oechem.OEWriteMolecule(ofs, outmol) ofs.close() # Write pdb file. if verbose: print "Writing input file as pdb..." outmol = oechem.OEMol(molecule) ofs = oechem.oemolostream() ofs.open('epik-input.pdb') oechem.OEWriteMolecule(ofs, outmol) ofs.close() # Write input for epik. if verbose: print "Converting input file to Maestro format..." reader = structure.StructureReader("epik-input.mol2") writer = structure.StructureWriter("epik-input.mae") for st in reader: writer.append(st) reader.close() writer.close() # Run epik to enumerate protomers/tautomers and get associated state penalties. if verbose: print "Running Epik..." cmd = '%s/epik -imae epik-input.mae -omae epik-output.mae -pht 10.0 -ms 100 -nt -pKa_atom -ph %f -WAIT' % (os.environ['SCHRODINGER'], pH) output = commands.getoutput(cmd) if verbose: print output # Convert output from epik from .mae to .sdf. if verbose: print "Converting output file to SDF..." reader = structure.StructureReader("epik-output.mae") writer = structure.StructureWriter("epik-output.sdf") for st in reader: writer.append(st) reader.close() writer.close() # Also convert to .mol2. if verbose: print "Converting output file to MOL2..." reader = structure.StructureReader("epik-output.mae") writer = structure.StructureWriter("epik-output.mol2") for st in reader: writer.append(st) reader.close() writer.close() # Find minimum charge. ifs = oechem.oemolistream() ifs.open('epik-output.mol2') molecule = oechem.OEGraphMol() min_formal_charge = 1000 while oechem.OEReadMolecule(ifs, molecule): # Check aromaticity. oechem.OEAssignAromaticFlags(molecule) # Assign formal charge oechem.OEAssignFormalCharges(molecule) formal_charge = 0 for atom in molecule.GetAtoms(): formal_charge += atom.GetFormalCharge() # Keep most negative formal charge min_formal_charge = min(min_formal_charge, formal_charge) ifs.close() if verbose: print "Minimum formal charge = %d" % min_formal_charge # Read conformers from SDF and mol2 (converted from Epik). if verbose: print "Reading conformers from SDF..." ifs_sdf = oechem.oemolistream() ifs_sdf.SetFormat(oechem.OEFormat_SDF) ifs_sdf.open('epik-output.sdf') sdf_molecule = oechem.OEGraphMol() ifs_mol2 = oechem.oemolistream() ifs_mol2.open('epik-output.mol2') mol2_molecule = oechem.OEGraphMol() conformer_index = 1 conformers = list() while oechem.OEReadMolecule(ifs_sdf, sdf_molecule): if verbose: print "Conformer %d" % conformer_index # Read corresponding mol2 molecule. oechem.OEReadMolecule(ifs_mol2, mol2_molecule) oechem.OEAssignAromaticFlags(mol2_molecule) # check aromaticity # Make a copy of the mol2 molecule. molecule = oechem.OEMol(mol2_molecule) # Set name name = options.ligand+'%02d' % conformer_index molecule.SetTitle(name) # Assign formal charge oechem.OEAssignFormalCharges(molecule) formal_charge = 0.0 for atom in molecule.GetAtoms(): formal_charge += atom.GetFormalCharge() if verbose: print "formal charge: %d" % formal_charge # DEBUG: Write mol2 file before assigning charges. if verbose: print "Writing %s to mol2..." % name outmol = oechem.OEMol(molecule) ofs = oechem.oemolostream() ofs.open(name + '.mol2') oechem.OEWriteMolecule(ofs, outmol) ofs.close() # Assign canonical AM1BCC charges. try: if verbose: print "Assigning AM1-BCC charges..." #assign_canonical_am1bcc_charges(molecule) assign_simple_am1bcc_charges(molecule) except Exception as e: print str(e) continue # Get Epik data. epik_Ionization_Penalty = float(oechem.OEGetSDData(sdf_molecule, "r_epik_Ionization_Penalty")) epik_Ionization_Penalty_Charging = float(oechem.OEGetSDData(sdf_molecule, "r_epik_Ionization_Penalty_Charging")) epik_Ionization_Penalty_Neutral = float(oechem.OEGetSDData(sdf_molecule, "r_epik_Ionization_Penalty_Neutral")) epik_State_Penalty = float(oechem.OEGetSDData(sdf_molecule, "r_epik_State_Penalty")) epik_Tot_Q = int(oechem.OEGetSDData(sdf_molecule, "i_epik_Tot_Q")) # Compute number of protons. nprotons = epik_Tot_Q - min_formal_charge + 1 # Compute effective pKa. import numpy as np kT = 298 * 6.022e23 * 1.381e-23 / 4184 # kcal/mol for 298 K pKa = options.pH - epik_State_Penalty / (nprotons * kT * np.log(10)) print "effective pKa = %8.3f" % pKa # DEBUG print "%24s : pKa penalty %8.3f kcal/mol | tautomer penalty %8.3f kcal/mol | total state penalty %8.3f\n" % (name, epik_Ionization_Penalty, epik_State_Penalty - epik_Ionization_Penalty, epik_State_Penalty) # Create a conformer and append it to the list. conformer = Conformer(name, epik_Tot_Q, molecule, state_penalty=epik_State_Penalty) conformers.append(conformer) print epik_Tot_Q # DEBUG # Increment counter. conformer_index += 1 ifs_sdf.close() ifs_mol2.close() if verbose: print "%d protomer/tautomer states were enumerated" % len(conformers) return conformers
def mk_single_conformer_epik(mol_name, molecule, verbose=True, pH=7): """ Enumerate the list of conformers and associated properties for each protonation and tautomeric state using epik from the Schrodinger Suite, and save the conformer with the lowest penalty. Parameters ---------- mol_name : string Molecule's name. molecule : openeye.oechem The molecule whose protomer and tautomer states are to be enumerated. pH : float, optional, default=7.0 pH to use for conformer enumeration Returns ------- molecule : openeye.oechem.OEMol The conformer with the lowest penalty. """ # Write mol2 file. if verbose: print "Writing input file as mol2..." outmol = oechem.OEMol(molecule) ofs = oechem.oemolostream() ofs.open('epik-input.mol2') oechem.OEWriteMolecule(ofs, outmol) ofs.close() # Run Schrodinger's epik try: import run_epik run_epik.main(verbose, pH) except ImportError: import subprocess schrodinger_run = os.path.join(os.environ['SCHRODINGER'], 'run') run_epik_script = os.path.join(os.path.dirname(__file__), 'run_epik.py') cmd = schrodinger_run + ' ' + run_epik_script + ' {!r} {:f}'.format(verbose, pH) return_code = subprocess.call(cmd, shell=True) if return_code != 0: raise RuntimeError('{!r} failed, exit status: {:d}'.format(cmd, return_code)) # Find minimum charge. ifs = oechem.oemolistream() ifs.open('epik-output.mol2') molecule = oechem.OEGraphMol() min_formal_charge = 1000 while oechem.OEReadMolecule(ifs, molecule): # Check aromaticity. oechem.OEAssignAromaticFlags(molecule) # Assign formal charge oechem.OEAssignFormalCharges(molecule) formal_charge = 0 for atom in molecule.GetAtoms(): formal_charge += atom.GetFormalCharge() # Keep most negative formal charge min_formal_charge = min(min_formal_charge, formal_charge) ifs.close() if verbose: print "Minimum formal charge = %d" % min_formal_charge # Read conformer with lowest penalty from SDF (converted from Epik). if verbose: print "Reading conformers from SDF..." ifs_sdf = oechem.oemolistream() ifs_sdf.SetFormat(oechem.OEFormat_SDF) ifs_sdf.open('epik-output.sdf') sdf_molecule = oechem.OEGraphMol() oechem.OEReadMolecule(ifs_sdf, sdf_molecule) # Read the molecule with lowest penalty ifs_sdf.close() # Get Epik data. epik_Ionization_Penalty = float(oechem.OEGetSDData(sdf_molecule, "r_epik_Ionization_Penalty")) epik_Ionization_Penalty_Charging = float(oechem.OEGetSDData(sdf_molecule, "r_epik_Ionization_Penalty_Charging")) epik_Ionization_Penalty_Neutral = float(oechem.OEGetSDData(sdf_molecule, "r_epik_Ionization_Penalty_Neutral")) epik_State_Penalty = float(oechem.OEGetSDData(sdf_molecule, "r_epik_State_Penalty")) epik_Tot_Q = int(oechem.OEGetSDData(sdf_molecule, "i_epik_Tot_Q")) # Read conformer with lowest penalty from MOL2 (converted from Epik). ifs_mol2 = oechem.oemolistream() ifs_mol2.open('epik-output.mol2') mol2_molecule = oechem.OEMol() oechem.OEReadMolecule(ifs_mol2, mol2_molecule) ifs_mol2.close() # Make a copy of the mol2 molecule. molecule = oechem.OEMol(mol2_molecule) oechem.OEAssignAromaticFlags(molecule) molecule.SetTitle(mol_name) # Assign formal charge oechem.OEAssignFormalCharges(molecule) formal_charge = 0.0 for atom in molecule.GetAtoms(): formal_charge += atom.GetFormalCharge() if verbose: print "formal charge: %d" % formal_charge # Assign canonical AM1BCC charges. if verbose: print "Assigning AM1-BCC charges..." assign_canonical_am1bcc_charges(molecule) # Save result in mol2 file if verbose: print "Writing %s to mol2..." % mol_name ofs = oechem.oemolostream() ofs.open(mol_name + '.mol2') oechem.OEWriteMolecule(ofs, molecule) ofs.close() # Compute number of protons. nprotons = epik_Tot_Q - min_formal_charge + 1 # Compute effective pKa. import numpy as np kT = 298 * 6.022e23 * 1.381e-23 / 4184 # kcal/mol for 298 K pKa = pH - epik_State_Penalty / (nprotons * kT * np.log(10)) print "effective pKa = %8.3f" % pKa # DEBUG print "%24s : pKa penalty %8.3f kcal/mol | tautomer penalty %8.3f kcal/mol | total state penalty %8.3f" % (mol_name, epik_Ionization_Penalty, epik_State_Penalty - epik_Ionization_Penalty, epik_State_Penalty) print epik_Tot_Q return molecule
def create_openeye_molecule(pdb, options, verbose=True): """ Create OpenEye molecule from PDB representation. The molecule will have hydrogens added and be normalized, but the overall geometry will not be altered. Parameters ---------- pdb : Pdb The PDB-extracted entries for the ligand. Returns ------- molecule : openeye.oechem.OEMol Molecule representation. options : options struct Options structure. """ # Create a molecule container. molecule = oechem.OEGraphMol() # Open a PDB file reader from the stored PDB string representation of HETATM and CONECT records. print pdb.pdb_extract ifs = oechem.oemolistream() ifs.openstring(pdb.pdb_extract) flavor = oechem.OEIFlavor_Generic_Default | oechem.OEIFlavor_PDB_Default | oechem.OEIFlavor_PDB_ALL ifs.SetFlavor(oechem.OEFormat_PDB, flavor) oechem.OEReadPDBFile(ifs, molecule) # Add explicit hydrogens. oechem.OEDetermineConnectivity(molecule) oechem.OEFindRingAtomsAndBonds(molecule) oechem.OEAssignAromaticFlags(molecule) # check aromaticity oechem.OEPerceiveBondOrders(molecule) # We must assign implicit hydrogens first so that the valence model will be correct. oechem.OEAssignImplicitHydrogens(molecule) oechem.OEAssignFormalCharges(molecule) # Now add explicit hydrogens. polarOnly = False set3D = True oechem.OEAddExplicitHydrogens(molecule, polarOnly, set3D) # TODO: Sequentially number hydrogen atoms. # Perceive stereochemostry. oechem.OEPerceiveChiral(molecule) # Set title. molecule.SetTitle(options.ligand) # Write out PDB form of this molecule. # TODO: Fix atom numbering. #if verbose: print "Writing input molecule as PDB..." #outmol = oechem.OEMol(molecule) #ofs = oechem.oemolostream() #flavor = oechem.OEOFlavor_Generic_Default | oechem.OEOFlavor_PDB_Default #ofs.SetFlavor(oechem.OEFormat_PDB, flavor) #ofs.open(options.ligand + '.pdb') #oechem.OEWriteMolecule(ofs, outmol) #ofs.close() # Write mol2 file for this molecule. if verbose: print "Writing input molecule as mol2..." outmol = oechem.OEMol(molecule) ofs = oechem.oemolostream() filename = options.ligand + '.mol2' ofs.open(filename) oechem.OEWriteMolecule(ofs, outmol) ofs.close() # Use low level writer to get atom names correct. ofs = oechem.oemolostream() ofs.open(filename) for (dest_atom, src_atom) in zip(outmol.GetAtoms(), molecule.GetAtoms()): dest_atom.SetName(src_atom.GetName()) oechem.OEWriteMol2File(ofs, outmol, True) ofs.close() # Read and write in PDB format. if verbose: print "Converting mol2 to PDB..." ifs = oechem.oemolistream() ofs = oechem.oemolostream() if ifs.open(options.ligand + '.mol2'): if ofs.open(options.ligand + '.pdb'): for mol in ifs.GetOEGraphMols(): oechem.OEWriteMolecule(ofs, mol) return molecule
# SaaS offerings (each a "Customer"). # Customer is hereby permitted to use, copy, and modify the Sample Code, # subject to these terms. OpenEye claims no rights to Customer's # modifications. Modification of Sample Code is at Customer's sole and # exclusive risk. Sample Code may require Customer to have a then # current license or subscription to the applicable OpenEye offering. # THE SAMPLE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED. OPENEYE DISCLAIMS ALL WARRANTIES, INCLUDING, BUT # NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. In no event shall OpenEye be # liable for any damages or liability in connection with the Sample Code # or its use. # @ <SNIPPET> from openeye import oechem import sys ifs = oechem.oemolistream(sys.argv[1]) ofs = oechem.oemolostream(sys.argv[2]) mol = oechem.OEGraphMol() oechem.OEReadPDBFile(ifs, mol) # @ <SNIPPET-CONNECT-PERCEIVE> oechem.OEDetermineConnectivity(mol) oechem.OEFindRingAtomsAndBonds(mol) oechem.OEPerceiveBondOrders(mol) oechem.OEAssignImplicitHydrogens(mol) oechem.OEAssignFormalCharges(mol) # @ </SNIPPET-CONNECT-PERCEIVE> oechem.OEWriteMolecule(ofs, mol) # @ </SNIPPET>