Exemplo n.º 1
0
def iupac_to_oemol(iupac_name):
    """Create a OEMolBuilder from a iupac name.

    Parameters
    ----------
    iupac_name : str
        IUPAC name of desired molecule.

    Returns
    -------
    molecule : OEMol
        A normalized molecule with desired iupac name.

    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for OEChem!"))
    oeiupac = import_("openeye.oeiupac")
    if not oeiupac.OEIUPACIsLicensed(): raise(ImportError("Need License for OEOmega!"))

    # Create an OEMol molecule from IUPAC name.
    molecule = oechem.OEMol()  # create a molecule

    # Populate the MoleCule from the IUPAC name
    if not oeiupac.OEParseIUPACName(molecule, iupac_name):
        raise ValueError("The supplied IUPAC name '%s' could not be parsed." % iupac_name)

    molecule = normalize_molecule(molecule)

    return molecule
Exemplo n.º 2
0
def iupac_to_oemol(iupac_name):
    """Create a OEMolBuilder from a iupac name.
    
    Parameters
    ----------
    iupac_name : str
        IUPAC name of desired molecule.

    Returns
    -------
    molecule : OEMol
        A normalized molecule with desired iupac name

    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for OEChem!"))
    oeiupac = import_("openeye.oeiupac")
    if not oeiupac.OEIUPACIsLicensed(): raise(ImportError("Need License for OEOmega!"))

    # Create an OEMol molecule from IUPAC name.
    molecule = oechem.OEMol()  # create a molecule

    # Populate the MoleCule from the IUPAC name
    if not oeiupac.OEParseIUPACName(molecule, iupac_name):
        raise ValueError("The supplied IUPAC name '%s' could not be parsed." % iupac_name)

    molecule = normalize_molecule(molecule)

    return molecule
Exemplo n.º 3
0
def generate_conformers(molecule, max_confs=800, strictStereo=True, ewindow=15.0, rms_threshold=1.0, strictTypes=True):
    """Generate conformations for the supplied molecule

    Parameters
    ----------
    molecule : OEMol
        Molecule for which to generate conformers
    max_confs : int, optional, default=800
        Max number of conformers to generate.  If None, use default OE Value.
    strictStereo : bool, optional, default=True
        If False, permits smiles strings with unspecified stereochemistry.
    strictTypes : bool, optional, default=True
        If True, requires that Omega have exact MMFF types for atoms in molecule; otherwise, allows the closest atom type of the same element to be used.

    Returns
    -------
    molcopy : OEMol
        A multi-conformer molecule with up to max_confs conformers.

    Notes
    -----
    Roughly follows
    http://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html

    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise (ImportError("Need License for OEChem!"))
    oeomega = import_("openeye.oeomega")
    if not oeomega.OEOmegaIsLicensed():
        raise (ImportError("Need License for OEOmega!"))

    molcopy = oechem.OEMol(molecule)
    omega = oeomega.OEOmega()

    # These parameters were chosen to match http://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html
    omega.SetMaxConfs(max_confs)
    omega.SetIncludeInput(True)
    omega.SetCanonOrder(False)

    omega.SetSampleHydrogens(True)  # Word to the wise: skipping this step can lead to significantly different charges!
    omega.SetEnergyWindow(ewindow)
    omega.SetRMSThreshold(
        rms_threshold
    )  # Word to the wise: skipping this step can lead to significantly different charges!

    omega.SetStrictStereo(strictStereo)
    omega.SetStrictAtomTypes(strictTypes)

    omega.SetIncludeInput(False)  # don't include input
    if max_confs is not None:
        omega.SetMaxConfs(max_confs)

    status = omega(molcopy)  # generate conformation
    if not status:
        raise (RuntimeError("omega returned error code %d" % status))

    return molcopy
Exemplo n.º 4
0
def smiles_to_antechamber(smiles_string,
                          gaff_mol2_filename,
                          frcmod_filename,
                          residue_name="MOL",
                          strictStereo=False,
                          protonation=False):
    """Build a molecule from a smiles string and run antechamber,
    generating GAFF mol2 and frcmod files from a smiles string.  Charges
    will be generated using the OpenEye QuacPac AM1-BCC implementation.

    Parameters
    ----------
    smiles_string : str
        Smiles string of 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
    protonation : bool, optional, default=False
        If True, uses OESetNeutralpHModel to set a pH model for the molecule
        to attempt to obtain protonation states appropriate for neutral pH.
        Depending on the application this may or may not be what you want, e.g. for
        hydration free energy calculations you may want the typical depicted (neutral) form.
    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise (ImportError("Need License for oechem!"))
    oequacpac = import_("openeye.oequacpac")

    # 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 = smiles_to_oemol(smiles_string)
    if protonation:
        oequacpac.OESetNeutralpHModel(m)
    m = get_charges(m, strictStereo=strictStereo, keep_confs=1)

    with enter_temp_directory(
    ):  # Avoid dumping 50 antechamber files in local directory.
        _unused = molecule_to_mol2(m, "./tmp.mol2", residue_name=residue_name)
        net_charge = oechem.OENetCharge(m)
        tmp_gaff_mol2_filename, tmp_frcmod_filename = 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)
Exemplo n.º 5
0
def get_charges(molecule, max_confs=800, strictStereo=True, keep_confs=None):
    """Generate charges for an OpenEye OEMol molecule.

    Parameters
    ----------
    molecule : OEMol
        Molecule for which to generate conformers. 
        Omega will be used to generate max_confs conformations.
    max_confs : int, optional, default=800
        Max number of conformers to generate
    strictStereo : bool, optional, default=True
        If False, permits smiles strings with unspecified stereochemistry.
        See https://docs.eyesopen.com/omega/usage.html
    keep_confs : int, optional, default=None
        If not None, only keep this many conformations in the final
        charged OEMol.  Multiple conformations are still used to *determine*
        the charges.  For example, keep_confs=1 will return an OEMol with
        just a single conformation, while keep_confs=None returns all the
        conformations generated by Omega.        
    
    Returns
    -------
    charged_copy : OEMol
        A molecule with OpenEye's recommended AM1BCC charge selection scheme.

    Notes
    -----
    Roughly follows 
    http://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html
    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise (ImportError("Need License for OEChem!"))
    oequacpac = import_("openeye.oequacpac")
    if not oequacpac.OEQuacPacIsLicensed():
        raise (ImportError("Need License for oequacpac!"))

    molecule = normalize_molecule(molecule)

    charged_copy = generate_conformers(
        molecule, max_confs=max_confs, strictStereo=strictStereo
    )  # Generate up to max_confs conformers

    status = oequacpac.OEAssignPartialCharges(
        charged_copy, oequacpac.OECharges_AM1BCCSym
    )  # AM1BCCSym recommended by Chris Bayly to KAB+JDC, Oct. 20 2014.

    if not status:
        raise (RuntimeError("OEAssignPartialCharges returned error code %d" % status))

    for k, conf in enumerate(charged_copy.GetConfs()):
        if keep_confs is not None and k > keep_confs - 1:
            charged_copy.DeleteConf(conf)

    return charged_copy
Exemplo n.º 6
0
def generate_conformers(molecule, max_confs=800, strictStereo=True, ewindow=15.0, rms_threshold=1.0, strictTypes = True):
    """Generate conformations for the supplied molecule

    Parameters
    ----------
    molecule : OEMol
        Molecule for which to generate conformers
    max_confs : int, optional, default=800
        Max number of conformers to generate.  If None, use default OE Value.
    strictStereo : bool, optional, default=True
        If False, permits smiles strings with unspecified stereochemistry.
    strictTypes : bool, optional, default=True
        If True, requires that Omega have exact MMFF types for atoms in molecule; otherwise, allows the closest atom type of the same element to be used.

    Returns
    -------
    molcopy : OEMol
        A multi-conformer molecule with up to max_confs conformers.

    Notes
    -----
    Roughly follows
    http://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html

    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for OEChem!"))
    oeomega = import_("openeye.oeomega")
    if not oeomega.OEOmegaIsLicensed(): raise(ImportError("Need License for OEOmega!"))

    molcopy = oechem.OEMol(molecule)
    omega = oeomega.OEOmega()

    # These parameters were chosen to match http://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html
    omega.SetMaxConfs(max_confs)
    omega.SetIncludeInput(True)
    omega.SetCanonOrder(False)

    omega.SetSampleHydrogens(True)  # Word to the wise: skipping this step can lead to significantly different charges!
    omega.SetEnergyWindow(ewindow)
    omega.SetRMSThreshold(rms_threshold)  # Word to the wise: skipping this step can lead to significantly different charges!

    omega.SetStrictStereo(strictStereo)
    omega.SetStrictAtomTypes(strictTypes)

    omega.SetIncludeInput(False)  # don't include input
    if max_confs is not None:
        omega.SetMaxConfs(max_confs)

    status = omega(molcopy)  # generate conformation
    if not status:
        raise(RuntimeError("omega returned error code %d" % status))


    return molcopy
Exemplo n.º 7
0
def smiles_to_antechamber(smiles_string, gaff_mol2_filename, frcmod_filename, residue_name="MOL", strictStereo=False, protonation=False):
    """Build a molecule from a smiles string and run antechamber,
    generating GAFF mol2 and frcmod files from a smiles string.  Charges
    will be generated using the OpenEye QuacPac AM1-BCC implementation.

    Parameters
    ----------
    smiles_string : str
        Smiles string of 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
    protonation : bool, optional, default=False
        If True, uses OESetNeutralpHModel to set a pH model for the molecule
        to attempt to obtain protonation states appropriate for neutral pH.
        Depending on the application this may or may not be what you want, e.g. for
        hydration free energy calculations you may want the typical depicted (neutral) form.
    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for oechem!"))
    oequacpac = import_("openeye.oequacpac")

    # 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 = smiles_to_oemol(smiles_string)
    if protonation:
        oequacpac.OESetNeutralpHModel(m)
    m = get_charges(m, strictStereo=strictStereo, keep_confs=1)

    with enter_temp_directory():  # Avoid dumping 50 antechamber files in local directory.
        _unused = molecule_to_mol2(m, "./tmp.mol2", residue_name=residue_name)
        net_charge = oechem.OENetCharge(m)
        tmp_gaff_mol2_filename, tmp_frcmod_filename = 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)
Exemplo n.º 8
0
def smiles_to_oemol(smiles):
    """Create a OEMolBuilder from a smiles string.

    Parameters
    ----------
    smiles : str
        SMILES representation of desired molecule.

    Returns
    -------
    molecule : OEMol
        A normalized molecule with desired smiles string.

    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise (ImportError("Need License for OEChem!"))

    molecule = oechem.OEMol()
    if not oechem.OEParseSmiles(molecule, smiles):
        raise ValueError("The supplied SMILES '%s' could not be parsed." % smiles)

    molecule = normalize_molecule(molecule)

    return molecule
Exemplo n.º 9
0
def smiles_to_oemol(smiles):
    """Create a OEMolBuilder from a smiles string.

    Parameters
    ----------
    smiles : str
        SMILES representation of desired molecule.

    Returns
    -------
    molecule : OEMol
        A normalized molecule with desired smiles string.

    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise (ImportError("Need License for OEChem!"))

    molecule = oechem.OEMol()
    if not oechem.OEParseSmiles(molecule, smiles):
        raise ValueError("The supplied SMILES '%s' could not be parsed." %
                         smiles)

    molecule = normalize_molecule(molecule)

    return molecule
Exemplo n.º 10
0
def get_names_to_charges(molecule):
    """Return a dictionary of atom names and partial charges, as well as a string representation.

    Parameters
    ----------
    molecule : OEMol
        Molecule for which to grab charges

    Returns
    -------
    data : dictionary
        A dictinoary whose (key, val) pairs are the atom names and partial
        charges, respectively.
    molrepr : str
        A string representation of data
    """

    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for oechem!"))
    molcopy = oechem.OEMol(molecule)
    molrepr = ""
    data = {}
    for atom in molcopy.GetAtoms():
        name = atom.GetName()
        charge = atom.GetPartialCharge()
        data[name] = charge
        molrepr += "%s %f \n" % (name, charge)
    return data, molrepr
Exemplo n.º 11
0
def get_names_to_charges(molecule):
    """Return a dictionary of atom names and partial charges, as well as a string representation.

    Parameters
    ----------
    molecule : OEMol
        Molecule for which to grab charges

    Returns
    -------
    data : dictionary
        A dictinoary whose (key, val) pairs are the atom names and partial
        charges, respectively.
    molrepr : str
        A string representation of data
    """
    
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for oechem!"))
    molcopy = oechem.OEMol(molecule)
    molrepr = ""
    data = {}
    for atom in molcopy.GetAtoms():
        name = atom.GetName()
        charge = atom.GetPartialCharge()
        data[name] = charge
        molrepr += "%s %f \n" % (name, charge)
    return data, molrepr
Exemplo n.º 12
0
def molecule_to_mol2(molecule,
                     tripos_mol2_filename=None,
                     conformer=0,
                     residue_name="MOL"):
    """Convert OE molecule to tripos mol2 file.

    Parameters
    ----------
    molecule : openeye.oechem.OEGraphMol
        The molecule to be converted.
    tripos_mol2_filename : str, optional, default=None
        Output filename.  If None, will create a filename similar to
        name.tripos.mol2, where name is the name of the OE molecule.
    conformer : int, optional, default=0
        Save this frame
    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.

    Returns
    -------
    tripos_mol2_filename : str
        Filename of output tripos mol2 file

    """

    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise (ImportError("Need License for oechem!"))

    # Get molecule name.
    molecule_name = molecule.GetTitle()
    logger.debug(molecule_name)

    # Write molecule as Tripos mol2.
    if tripos_mol2_filename is None:
        tripos_mol2_filename = molecule_name + '.tripos.mol2'

    ofs = oechem.oemolostream(tripos_mol2_filename)
    ofs.SetFormat(oechem.OEFormat_MOL2H)
    for k, mol in enumerate(molecule.GetConfs()):
        if k == conformer:
            oechem.OEWriteMolecule(ofs, mol)

    ofs.close()

    # Replace <0> substructure names with valid text.
    infile = open(tripos_mol2_filename, 'r')
    lines = infile.readlines()
    infile.close()
    newlines = [line.replace('<0>', residue_name) for line in lines]
    outfile = open(tripos_mol2_filename, 'w')
    outfile.writelines(newlines)
    outfile.close()

    return molecule_name, tripos_mol2_filename
Exemplo n.º 13
0
def molecule_to_mol2(molecule, tripos_mol2_filename=None, conformer=0, residue_name="MOL"):
    """Convert OE molecule to tripos mol2 file.

    Parameters
    ----------
    molecule : openeye.oechem.OEGraphMol
        The molecule to be converted.
    tripos_mol2_filename : str, optional, default=None
        Output filename.  If None, will create a filename similar to
        name.tripos.mol2, where name is the name of the OE molecule.
    conformer : int, optional, default=0
        Save this frame
    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.

    Returns
    -------
    tripos_mol2_filename : str
        Filename of output tripos mol2 file

    """

    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise (ImportError("Need License for oechem!"))

    # Get molecule name.
    molecule_name = molecule.GetTitle()
    logger.debug(molecule_name)

    # Write molecule as Tripos mol2.
    if tripos_mol2_filename is None:
        tripos_mol2_filename = molecule_name + ".tripos.mol2"

    ofs = oechem.oemolostream(tripos_mol2_filename)
    ofs.SetFormat(oechem.OEFormat_MOL2H)
    for k, mol in enumerate(molecule.GetConfs()):
        if k == conformer:
            oechem.OEWriteMolecule(ofs, mol)

    ofs.close()

    # Replace <0> substructure names with valid text.
    infile = open(tripos_mol2_filename, "r")
    lines = infile.readlines()
    infile.close()
    newlines = [line.replace("<0>", residue_name) for line in lines]
    outfile = open(tripos_mol2_filename, "w")
    outfile.writelines(newlines)
    outfile.close()

    return molecule_name, tripos_mol2_filename
Exemplo n.º 14
0
def normalize_molecule(molecule):
    """
    Normalize a copy of the molecule by checking aromaticity, adding explicit hydrogens, and
    (if possible) renaming by IUPAC name.

    Parameters
    ----------
    molecule : OEMol
        the molecule to be normalized.

    Returns
    -------
    molcopy : OEMol
        A (copied) version of the normalized molecule

    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise(ImportError("Need License for OEChem!"))
    oeiupac = import_("openeye.oeiupac")
    has_iupac = oeiupac.OEIUPACIsLicensed()

    molcopy = oechem.OEMol(molecule)

    # Assign aromaticity.
    oechem.OEAssignAromaticFlags(molcopy, oechem.OEAroModelOpenEye)

    # Add hydrogens.
    oechem.OEAddExplicitHydrogens(molcopy)

    # Set title to IUPAC name.
    if has_iupac:
        name = oeiupac.OECreateIUPACName(molcopy)
        molcopy.SetTitle(name)

    # Check for any missing atom names, if found reassign all of them.
    if any([atom.GetName() == '' for atom in molcopy.GetAtoms()]):
        oechem.OETriposAtomNames(molcopy)

    return molcopy
Exemplo n.º 15
0
def writeSDF(mol2_filename, sdf_filename, mol_name):
    """For generating .sdf file format from .mol2 file, using OEIFlavor (OpenEye). Creates three tags (partial_charges, partial_bond_orders, and atom_types) in the .sdf file using values from the reference (.mol2 file).
    
    Parameters
    ----------
    mol2_filename: str
        Mol2 filename used to write the .sdf file. The .mol2 file is preserved.
    sdf_filename: str
        SDF filename (path) used to save the sdf file generated.
    mol_name: str
        Name of molecule used to write the title for the .sdf file generated.
    
    Notes
    -----------
    In partial_bonds_orders tag, .mol2 bond orders are translated to .sdf bond orders using OEIFlavor, aromatic bonds ('ar') are transformed to 1 or 2.

    Limitations
    -----------
    Creates only three tags in .sdf file. The tags are partial_charges, partial_bond_orders, and atom_types (GAFF). Their values are set according to the correspondent .mol2 file properties.
    """
    oechem = import_("openeye.oechem")
    
    ifs = oechem.oemolistream(mol2_filename)
    MOL2flavor = oechem.OEIFlavor_Generic_Default | oechem.OEIFlavor_MOL2_Default | oechem.OEIFlavor_MOL2_Forcefield
    ifs.SetFlavor(oechem.OEFormat_MOL2, MOL2flavor)

    ofs = oechem.oemolostream(sdf_filename)
    tag_names = ['partial_charges', 'partial_bond_orders', 'atom_types']
    
    # Set the title and assign partial charges for the .mol2 file
    for mol in ifs.GetOEGraphMols():
        mol.SetTitle(mol_name)
        molToCharge = oechem.OEMol(mol)
        
        # Get partial charges and atom types from .mol2 file and store them to put into the .sdf file as tags
        charges = []
        atom_types = []
        for atom, atomCharged in zip(mol.GetAtoms(), molToCharge.GetAtoms()):
            atom.SetPartialCharge( atomCharged.GetPartialCharge() )
            charges += [atom.GetPartialCharge()]
            atom_types += [atom.GetType()]

        #print("partial charges " + str(charges))
        #print("atom types: " + str(atom_types))
        # Create the tags for the sdf file
        mol = createTag(tag_names, mol, charges, atom_types)
        oechem.OEWriteMolecule(ofs, mol)
    ifs.close()
    ofs.close()
Exemplo n.º 16
0
def createTag(tag_names, mol, charges, atom_types):
    """Create the tags for sdf file."""
    oechem = import_("openeye.oechem")
    mol_id = oechem.OEGetSDData(mol, 'Mol_Index')
    for tag in tag_names:
        if tag == 'partial_charges':
            value = manipulatePartialChargesTag(charges)
        elif tag == 'partial_bond_orders':
            value = manipulateBondOrdersTag(mol)
        elif tag == 'atom_types':
            value = manipulateAtomTypes(atom_types)
        else:
            #Tag Name Error
            raise Exception('Wrong tag name')
            break
        oechem.OESetSDData(mol, oechem.OESDDataPair(tag, value))
    return mol
Exemplo n.º 17
0
import simtk.openmm as mm
import numpy as np
import re
from mdtraj.testing import eq
from unittest import skipIf
from openmoltools import utils, packmol
import os
import openmoltools.openeye
import pandas as pd
import mdtraj as md
from numpy.testing import assert_raises

smiles_fails_with_strictStereo = "CN1CCN(CC1)CCCOc2cc3c(cc2OC)C(=[NH+]c4cc(c(cc4Cl)Cl)OC)C(=C=[N-])C=[NH+]3"

try:
    oechem = utils.import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise (ImportError("Need License for OEChem!"))
    oequacpac = utils.import_("openeye.oequacpac")
    if not oequacpac.OEQuacPacIsLicensed():
        raise (ImportError("Need License for oequacpac!"))
    oeiupac = utils.import_("openeye.oeiupac")
    if not oeiupac.OEIUPACIsLicensed():
        raise (ImportError("Need License for OEOmega!"))
    oeomega = utils.import_("openeye.oeomega")
    if not oeomega.OEOmegaIsLicensed():
        raise (ImportError("Need License for OEOmega!"))
    HAVE_OE = True
    openeye_exception_message = str()
except Exception as e:
    HAVE_OE = False
Exemplo n.º 18
0
from nose.plugins.attrib import attr
from unittest import skipIf
from openmoltools import utils
import os

try:
    oechem = utils.import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for OEChem!"))
    oequacpac = utils.import_("openeye.oequacpac")
    if not oequacpac.OEQuacPacIsLicensed(): raise(ImportError("Need License for oequacpac!"))
    oeiupac = utils.import_("openeye.oeiupac")
    if not oeiupac.OEIUPACIsLicensed(): raise(ImportError("Need License for OEOmega!"))        
    oeomega = utils.import_("openeye.oeomega")
    if not oeomega.OEOmegaIsLicensed(): raise(ImportError("Need License for OEOmega!"))    
    HAVE_OE = True
except:
    HAVE_OE = False


@skipIf(not HAVE_OE, "Cannot run test_drugs() module without OpenEye tools.")
@attr('slow')
def test_drugs():
    import openeye.oechem
    database_filename = utils.get_data_filename("chemicals/drugs/Zdd.mol2.gz")
    ifs = openeye.oechem.oemolistream(database_filename)
    for molecule in ifs.GetOEMols():
        with utils.enter_temp_directory():
            molecule_name, tripos_mol2_filename = utils.molecule_to_mol2(molecule)
            yield utils.tag_description(lambda : utils.test_molecule(molecule_name, tripos_mol2_filename), "Testing drugs %s" % molecule_name)

@skipIf(not HAVE_OE, "Cannot test test_drug() without OpenEye tools.")
Exemplo n.º 19
0
def get_charges(molecule, max_confs=800, strictStereo=True, keep_confs=None):
    """Generate charges for an OpenEye OEMol molecule.

    Parameters
    ----------
    molecule : OEMol
        Molecule for which to generate conformers. 
        Omega will be used to generate max_confs conformations.
    max_confs : int, optional, default=800
        Max number of conformers to generate
    strictStereo : bool, optional, default=True
        If False, permits smiles strings with unspecified stereochemistry.
        See https://docs.eyesopen.com/omega/usage.html
    keep_confs : int, optional, default=None
        If None, apply the charges to the provided conformation and return
        this conformation. Otherwise, return some or all of the generated
        conformations. If -1, all generated conformations are returned. 
        Otherwise, keep_confs = N will return an OEMol with up to N
        generated conformations.  Multiple conformations are still used to
        *determine* the charges.
    
    Returns
    -------
    charged_copy : OEMol
        A molecule with OpenEye's recommended AM1BCC charge selection scheme.

    Notes
    -----
    Roughly follows 
    http://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html
    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed():
        raise (ImportError("Need License for OEChem!"))
    oequacpac = import_("openeye.oequacpac")
    if not oequacpac.OEQuacPacIsLicensed():
        raise (ImportError("Need License for oequacpac!"))

    molecule = normalize_molecule(molecule)

    charged_copy = generate_conformers(
        molecule, max_confs=max_confs,
        strictStereo=strictStereo)  # Generate up to max_confs conformers

    status = oequacpac.OEAssignPartialCharges(
        charged_copy, oequacpac.OECharges_AM1BCCSym
    )  # AM1BCCSym recommended by Chris Bayly to KAB+JDC, Oct. 20 2014.

    if not status:
        raise (RuntimeError("OEAssignPartialCharges returned error code %d" %
                            status))

    #Determine conformations to return
    if keep_confs == None:
        #If returning original conformation
        original = molecule.GetCoords()
        #Delete conformers over 1
        for k, conf in enumerate(charged_copy.GetConfs()):
            if k > 0:
                charged_copy.DeleteConf(conf)
        #Copy coordinates to single conformer
        charged_copy.SetCoords(original)
    elif keep_confs > 0:
        #Otherwise if a number is provided, return this many confs if available
        for k, conf in enumerate(charged_copy.GetConfs()):
            if k > keep_confs - 1:
                charged_copy.DeleteConf(conf)
    elif keep_confs == -1:
        #If we want all conformations, continue
        pass
    else:
        #Not a valid option to keep_confs
        raise (ValueError('Not a valid option to keep_confs in get_charges.'))

    return charged_copy
Exemplo n.º 20
0
def get_charges(molecule, max_confs=800, strictStereo=True,
                normalize=True, keep_confs=None, legacy=True):
    """Generate charges for an OpenEye OEMol molecule.

    Parameters
    ----------
    molecule : OEMol
        Molecule for which to generate conformers.
        Omega will be used to generate max_confs conformations.
    max_confs : int, optional, default=800
        Max number of conformers to generate
    strictStereo : bool, optional, default=True
        If False, permits smiles strings with unspecified stereochemistry.
        See https://docs.eyesopen.com/omega/usage.html
    normalize : bool, optional, default=True
        If True, normalize the molecule by checking aromaticity, adding
        explicit hydrogens, and renaming by IUPAC name.
    keep_confs : int, optional, default=None
        If None, apply the charges to the provided conformation and return
        this conformation, unless no conformation is present.
        Otherwise, return some or all of the generated
        conformations. If -1, all generated conformations are returned.
        Otherwise, keep_confs = N will return an OEMol with up to N
        generated conformations.  Multiple conformations are still used to
        *determine* the charges.
    legacy : bool, default=True
        If False, uses the new OpenEye charging engine.
        See https://docs.eyesopen.com/toolkits/python/quacpactk/OEProtonFunctions/OEAssignCharges.html#

    Returns
    -------
    charged_copy : OEMol
        A molecule with OpenEye's recommended AM1BCC charge selection scheme.

    Notes
    -----
    Roughly follows
    http://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html
    """

    # If there is no geometry, return at least one conformation.
    if molecule.GetConfs() == 0:
        keep_confs = 1

    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for OEChem!"))
    oequacpac = import_("openeye.oequacpac")
    if not oequacpac.OEQuacPacIsLicensed(): raise(ImportError("Need License for oequacpac!"))

    if normalize:
        molecule = normalize_molecule(molecule)
    else:
        molecule = oechem.OEMol(molecule)

    charged_copy = generate_conformers(molecule, max_confs=max_confs, strictStereo=strictStereo)  # Generate up to max_confs conformers

    if not legacy:
        # 2017.2.1 OEToolkits new charging function
        status = oequacpac.OEAssignCharges(charged_copy, oequacpac.OEAM1BCCCharges())
        if not status: raise(RuntimeError("OEAssignCharges failed."))
    else:
        # AM1BCCSym recommended by Chris Bayly to KAB+JDC, Oct. 20 2014.
        status = oequacpac.OEAssignPartialCharges(charged_copy, oequacpac.OECharges_AM1BCCSym)
        if not status: raise(RuntimeError("OEAssignPartialCharges returned error code %d" % status))



    #Determine conformations to return
    if keep_confs == None:
        #If returning original conformation
        original = molecule.GetCoords()
        #Delete conformers over 1
        for k, conf in enumerate( charged_copy.GetConfs() ):
            if k > 0:
                charged_copy.DeleteConf(conf)
        #Copy coordinates to single conformer
        charged_copy.SetCoords( original )
    elif keep_confs > 0:
        logger.debug("keep_confs was set to %s. Molecule positions will be reset." % keep_confs)

        #Otherwise if a number is provided, return this many confs if available
        for k, conf in enumerate( charged_copy.GetConfs() ):
            if k > keep_confs - 1:
                charged_copy.DeleteConf(conf)
    elif keep_confs == -1:
        #If we want all conformations, continue
        pass
    else:
        #Not a valid option to keep_confs
        raise(ValueError('Not a valid option to keep_confs in get_charges.'))

    return charged_copy
Exemplo n.º 21
0
            def mole_fractions_to_n_monomers(self, density= 1 * grams/milliliter, cutoff=12*angstrom):
                """
                This function is used to generate the number of molecules for
                each compound in the solution from the mole fractions of each molecule.

                Parameters
                ----------
                density : openmm units
                   the solution density
                cutoff : openmm units
                   the cutoff distance of the largest compound in the solution

                Returns
                -------
                self.n_monomers : integer list
                   the list of molecule number for each compound in the solution

                size : float
                   the edge of the box volume

                """
                oechem = import_("openeye.oechem")

                # Calculate the maximum atomic distance in a molecule
                def max_dist_mol(mol):
                    max_dist = 0.0
                    coords = mol.GetCoords() # Are the coords always in A in mol2 file?
                    for i in range(0, mol.NumAtoms()):
                        crdi = np.array([coords[i][0], coords[i][1], coords[i][2]])
                        for j in range(i+1, mol.NumAtoms()):
                            crdj = np.array([coords[j][0], coords[j][1], coords[j][2]])
                            dist = np.linalg.norm(crdi-crdj)
                            if dist > max_dist:
                                max_dist = dist

                    return max_dist * angstrom

                # The sum of all the mole fractions
                sum_fractions = sum([i for i in self.mole_fractions if i != None])

                if sum_fractions > 1.0:
                    raise ValueError('Error: The total molar fraction is greater than 1.0')

                if sum_fractions == 1.0 and self.filling_compound:
                     raise ValueError('Error: The total molar fraction is 1.0 and it is not possible to add any filling compound to the solution, but a filling compound was specified')

                if sum_fractions < 1.0 and not self.filling_compound:
                    raise ValueError('Error: The total molar fraction is less than 1.0 and no filling compound (i.e. compound with unspecified mole fraction) is provided')

                if self.filling_compound:
                    self.filling_compound.mole_fraction = 1.0 - sum_fractions
                    self.mole_fractions = [i if i != None else (1.0 - sum_fractions) for i in self.mole_fractions]


                max_dist_mols = 0.0 * angstrom
                delta_volume = 0.0 * angstrom**3
                sum_wgt_frac = 0.0 * grams/mole


                for i in range(0, len(self.sdf_filenames)):
                    istream = oechem.oemolistream(self.sdf_filenames[i])#gaff_mol2_files give wrong wgt because not sybyl format!
                    mol = oechem.OEMol()

                    if not oechem.OEReadMolecule(istream, mol):
                        raise IOError('Error: It was not possible to create the OpenEye molecule object by reading the file: %s' % self.gaff_mol2_filenames[i])
                    # Molecular weight
                    wgt = oechem.OECalculateMolecularWeight(mol) * grams/mole

                    if self.component_list[i].mole_fraction == 0.0:
                        delta_volume = oechem.OECalculateMolecularWeight(mol) * angstrom**3

                    sum_wgt_frac = sum_wgt_frac + wgt * self.component_list[i].mole_fraction

                    max_dist= max_dist_mol(mol)

                    if max_dist  > max_dist_mols:
                         max_dist_mols = max_dist


                cube_length = ((max_dist_mols + 2*cutoff)**3 + delta_volume)**(1.0/3.0)

                n_monomers = []


                # n_i = Volume * Density * mole_fraction_i/sum_j(wgt_j * mole_fraction_j)
                self.n_monomers = [int(round(AVOGADRO_CONSTANT_NA * comp.mole_fraction * density * cube_length**3 / sum_wgt_frac)) \
                                   if comp.mole_fraction !=0 else 1 for comp in self.component_list]


                return self.n_monomers, cube_length
Exemplo n.º 22
0
def get_charges(molecule, max_confs=800, strictStereo=True, keep_confs=None):
    """Generate charges for an OpenEye OEMol molecule.

    Parameters
    ----------
    molecule : OEMol
        Molecule for which to generate conformers. 
        Omega will be used to generate max_confs conformations.
    max_confs : int, optional, default=800
        Max number of conformers to generate
    strictStereo : bool, optional, default=True
        If False, permits smiles strings with unspecified stereochemistry.
        See https://docs.eyesopen.com/omega/usage.html
    keep_confs : int, optional, default=None
        If None, apply the charges to the provided conformation and return
        this conformation. Otherwise, return some or all of the generated
        conformations. If -1, all generated conformations are returned. 
        Otherwise, keep_confs = N will return an OEMol with up to N
        generated conformations.  Multiple conformations are still used to
        *determine* the charges.
    
    Returns
    -------
    charged_copy : OEMol
        A molecule with OpenEye's recommended AM1BCC charge selection scheme.

    Notes
    -----
    Roughly follows 
    http://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html
    """
    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for OEChem!"))
    oequacpac = import_("openeye.oequacpac")
    if not oequacpac.OEQuacPacIsLicensed(): raise(ImportError("Need License for oequacpac!"))
    
    molecule = normalize_molecule(molecule)

    charged_copy = generate_conformers(molecule, max_confs=max_confs, strictStereo=strictStereo)  # Generate up to max_confs conformers
    
    status = oequacpac.OEAssignPartialCharges(charged_copy, oequacpac.OECharges_AM1BCCSym)  # AM1BCCSym recommended by Chris Bayly to KAB+JDC, Oct. 20 2014.
    
    if not status:
        raise(RuntimeError("OEAssignPartialCharges returned error code %d" % status))

    #Determine conformations to return
    if keep_confs == None:
        #If returning original conformation
        original = molecule.GetCoords()
        #Delete conformers over 1
        for k, conf in enumerate( charged_copy.GetConfs() ):
            if k > 0:
                charged_copy.DeleteConf(conf)
        #Copy coordinates to single conformer
        charged_copy.SetCoords( original )
    elif keep_confs > 0:
        #Otherwise if a number is provided, return this many confs if available
        for k, conf in enumerate( charged_copy.GetConfs() ):
            if k > keep_confs - 1:
                charged_copy.DeleteConf(conf)
    elif keep_confs == -1:
        #If we want all conformations, continue
        pass
    else:
        #Not a valid option to keep_confs
        raise(ValueError('Not a valid option to keep_confs in get_charges.')) 
   
    return charged_copy
Exemplo n.º 23
0
    def __init__(self, name=None, label=None, smiles=None, number=None, mole_fraction=None):
        """
        Initialization class function

        Parameters
        ----------
        name : str
           the molecule name
        label : str
           the molecule label used to generates files
        smiles : str
           the molecule SMILES string
        number : int
           the number of molecule
        mole_fraction : float
           molecular mole fraction

        REQUIRED: A name and/or label. If no SMILES is provided, the name will be used to generate SMILES and if no name is provided, the label will be used to attempt to generate SMILES.
        """


        oechem = import_("openeye.oechem")
        oeiupac = import_("openeye.oeiupac")

        # Checking name and label

        ref_str = ''

        if not name and not label:
            raise ValueError("Error: No component parameters name or label"+
" have been provided for the component")

        if label:
            if not isinstance(label, str):
                raise ValueError("Error: The component label %s is not a string" % label)
            ref_str = label

        if name:
            if not isinstance(name, str):
                raise ValueError("Error: The component name %s is not a string" % name)
            ref_str = name

        if label and not name:
            print('\nWARNING: component name not provided; label will be used as component name\n')

        # Checking smiles, molecule number and mole fraction

        if smiles:
            if not isinstance(smiles, str):
                raise ValueError("Error: The SMILES % for the component %s is not a string" % (smiles, ref_str))
            #Check this is a valid SMILES string
            mol = oechem.OEMol()
            status = oechem.OEParseSmiles(mol, smiles)
            if not status:
                raise ValueError("Error: The SMILES %s for the component %s"
                 " cannot be processed by OEChem." % (smiles, ref_str) )

        if number is not None:
            if not isinstance(number, int):
                raise ValueError("Error: The molecule quantity %s for the component %s is not an integer" % (number, ref_str))
            if number < 1:
                raise ValueError("Error: The molecule quantity %s for the component %s must be a positive integer" % (number, ref_str))

        if mole_fraction:
            if not isinstance(mole_fraction, float):
                raise ValueError("Error: The mole fraction %s for the component %s is not a float number" % (mole_fraction, ref_str))
            if mole_fraction < 0.0:
                raise ValueError("Error: The mole fraction %s for the component %s must be positive" % (mole_fraction, ref_str))
            if mole_fraction > 1.0:
                raise ValueError("Error: The mole fraction %s for the component %s is greater than one" % (mole_fraction, ref_str))

        if number and mole_fraction:
            raise ValueError("Error: molecule number and mole fraction for the compound %s cannot be both specified" % ref_str)

        if not smiles:
            mol = oechem.OEMol()
            if name:
                try:
                    oeiupac.OEParseIUPACName(mol, name)
                    smiles = oechem.OECreateIsoSmiString(mol)
                    #If smiles is empty, didn't parse correctly
                    if smiles == '':
                        raise ValueError("Error: The supplied name '%s' could not be parsed" % name)
                except:
                    raise ValueError("Error: The supplied name '%s' could not be parsed" % name)
            elif label:
                try:
                    oeiupac.OEParseIUPACName(mol, label)
                    smiles = oechem.OECreateIsoSmiString(mol)
                    if smiles == '':
                        raise ValueError("Error: The supplied name '%s' could not be parsed" % name)
                except:
                    raise ValueError("Error: The supplied label '%s' could not be parsed" % label)

        self.name = name
        self.label = label
        self.smiles = smiles
        self.number = number
        self.mole_fraction = mole_fraction


        return
Exemplo n.º 24
0
def molecule_to_mol2(molecule, tripos_mol2_filename=None, conformer=0, residue_name="MOL", standardize=True):
    """Convert OE molecule to tripos mol2 file.

    Parameters
    ----------
    molecule : openeye.oechem.OEGraphMol
        The molecule to be converted.
    tripos_mol2_filename : str, optional, default=None
        Output filename.  If None, will create a filename similar to
        name.tripos.mol2, where name is the name of the OE molecule.
    conformer : int, optional, default=0
        Save this frame
        If None, save all conformers
    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.
    standardize: bool, optional, default=True
        Use a high-level writer, which will standardize the molecular properties.
        Set this to false if you wish to retain things such as atom names.
        In this case, a low-level writer will be used.

    Returns
    -------
    tripos_mol2_filename : str
        Filename of output tripos mol2 file

    """

    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for oechem!"))

    # Get molecule name.
    molecule_name = molecule.GetTitle()
    logger.debug(molecule_name)

    # Write molecule as Tripos mol2.
    if tripos_mol2_filename is None:
        tripos_mol2_filename = molecule_name + '.tripos.mol2'

    ofs = oechem.oemolostream(tripos_mol2_filename)
    ofs.SetFormat(oechem.OEFormat_MOL2H)
    for k, mol in enumerate(molecule.GetConfs()):
        if k == conformer or conformer is None:
            # Standardize will override molecular properties(atom names etc.)
            if standardize:
                oechem.OEWriteMolecule(ofs, mol)
            else:
                oechem.OEWriteMol2File(ofs, mol)

    ofs.close()

    # Replace <0> substructure names with valid text.
    infile = open(tripos_mol2_filename, 'r')
    lines = infile.readlines()
    infile.close()
    newlines = [line.replace('<0>', residue_name) for line in lines]
    outfile = open(tripos_mol2_filename, 'w')
    outfile.writelines(newlines)
    outfile.close()

    return molecule_name, tripos_mol2_filename
Exemplo n.º 25
0
def get_charges(molecule, max_confs=800, strictStereo=True,
                normalize=True, keep_confs=None, legacy=True):
    """Generate charges for an OpenEye OEMol molecule.

    Parameters
    ----------
    molecule : OEMol
        Molecule for which to generate conformers.
        Omega will be used to generate max_confs conformations.
    max_confs : int, optional, default=800
        Max number of conformers to generate
    strictStereo : bool, optional, default=True
        If False, permits smiles strings with unspecified stereochemistry.
        See https://docs.eyesopen.com/omega/usage.html
    normalize : bool, optional, default=True
        If True, normalize the molecule by checking aromaticity, adding
        explicit hydrogens, and renaming by IUPAC name.
    keep_confs : int, optional, default=None
        If None, apply the charges to the provided conformation and return
        this conformation, unless no conformation is present.
        Otherwise, return some or all of the generated
        conformations. If -1, all generated conformations are returned.
        Otherwise, keep_confs = N will return an OEMol with up to N
        generated conformations.  Multiple conformations are still used to
        *determine* the charges.
    legacy : bool, default=True
        If False, uses the new OpenEye charging engine.
        See https://docs.eyesopen.com/toolkits/python/quacpactk/OEProtonFunctions/OEAssignCharges.html#

    Returns
    -------
    charged_copy : OEMol
        A molecule with OpenEye's recommended AM1BCC charge selection scheme.

    Notes
    -----
    Roughly follows
    http://docs.eyesopen.com/toolkits/cookbook/python/modeling/am1-bcc.html
    """

    # If there is no geometry, return at least one conformation.
    if molecule.GetConfs() == 0:
        keep_confs = 1

    oechem = import_("openeye.oechem")
    if not oechem.OEChemIsLicensed(): raise(ImportError("Need License for OEChem!"))
    oequacpac = import_("openeye.oequacpac")
    if not oequacpac.OEQuacPacIsLicensed(): raise(ImportError("Need License for oequacpac!"))

    if normalize:
        molecule = normalize_molecule(molecule)
    else:
        molecule = oechem.OEMol(molecule)

    charged_copy = generate_conformers(molecule, max_confs=max_confs, strictStereo=strictStereo)  # Generate up to max_confs conformers

    if not legacy:
        # 2017.2.1 OEToolkits new charging function
        status = oequacpac.OEAssignCharges(charged_copy, oequacpac.OEAM1BCCCharges())
        if not status: raise(RuntimeError("OEAssignCharges failed."))
    else:
        # AM1BCCSym recommended by Chris Bayly to KAB+JDC, Oct. 20 2014.
        status = oequacpac.OEAssignPartialCharges(charged_copy, oequacpac.OECharges_AM1BCCSym)
        if not status: raise(RuntimeError("OEAssignPartialCharges returned error code %d" % status))



    #Determine conformations to return
    if keep_confs == None:
        #If returning original conformation
        original = molecule.GetCoords()
        #Delete conformers over 1
        for k, conf in enumerate( charged_copy.GetConfs() ):
            if k > 0:
                charged_copy.DeleteConf(conf)
        #Copy coordinates to single conformer
        charged_copy.SetCoords( original )
    elif keep_confs > 0:
        logger.debug("keep_confs was set to %s. Molecule positions will be reset." % keep_confs)

        #Otherwise if a number is provided, return this many confs if available
        for k, conf in enumerate( charged_copy.GetConfs() ):
            if k > keep_confs - 1:
                charged_copy.DeleteConf(conf)
    elif keep_confs == -1:
        #If we want all conformations, continue
        pass
    else:
        #Not a valid option to keep_confs
        raise(ValueError('Not a valid option to keep_confs in get_charges.'))

    return charged_copy