MobleyLab / chemper
1
"""
2
mol_toolkit is a set of factory methods which
3
allow the user to interact with ChemPer Mol, Atom, and Bond
4
objects without having to explicitly define which toolkit they
5
are using.
6

7
For example one user could be loading their molecules through openeye
8
and the others could be using RDKit to create what we would call a "user mol"
9

10
In this case they can call:
11
from chemper.mol_toolkits import mol_toolkit
12
mol = mol_toolkit.Mol(user_mol)
13
without needing to tell us what toolkit they are using or they
14
could specify
15
mol = mol_toolkit.Mol(user_mol, toolkit='openeye')
16

17
"""
18 2
import os
19 2
from chemper.chemper_utils import get_data_path
20 2
from chemper.mol_toolkits.adapters import MolAdapter, BondAdapter, AtomAdapter
21

22
# identify which toolkits are available
23 2
HAS_OE = False
24 2
HAS_RDK = False
25 2
try:
26 2
    from openeye import oechem
27 2
    if oechem.OEChemIsLicensed():
28 2
        from chemper.mol_toolkits import cp_openeye
29 2
        HAS_OE = True
30 0
except ImportError:
31 0
    HAS_OE = False
32

33 2
try:
34 2
    from rdkit import Chem
35 0
    from chemper.mol_toolkits import cp_rdk
36 0
    HAS_RDK = True
37 2
except ImportError:
38 2
    HAS_RDK = False
39

40

41
# ======================================================================
42
# Find super Mol/Atom/Bond classes
43
# ======================================================================
44

45 2
if not HAS_OE and not HAS_RDK:
46 0
    raise ImportWarning("No Cheminformatics toolkit was found." \
47
                        " currently ChemPer supports OpenEye and RDKit")
48

49

50 2
class Mol:
51 2
    def __init__(self, mol):
52
        # if it is already a chemper molecule return as is
53 2
        if isinstance(mol, MolAdapter):
54 2
            self.mol = mol.mol
55 2
            self.__class__ = mol.__class__
56

57
        # check if this is an Openeye molecule
58 2
        elif HAS_OE and isinstance(mol, oechem.OEMolBase):
59 0
            self.__class__ = cp_openeye.Mol
60 0
            self.__class__.__init__(self,mol)
61

62
        # check if it is an RDK molecule
63 2
        elif HAS_RDK and isinstance(mol, Chem.rdchem.Mol):
64 0
            self.__class__ = cp_rdk.Mol
65 0
            self.__class__.__init__(self, mol)
66

67
        else:
68 2
            err_msg = """
69
            Your molecule has the type %s.
70
            Currently ChemPer only supports OpenEye and RDKit.
71
            To add support to a new toolkit submit an issue on GitHub at
72
            github.com/MobleyLab/chemper
73
            """
74 2
            raise TypeError(err_msg % type(mol))
75

76 2
    @staticmethod
77
    def from_smiles(smiles):
78 2
        if HAS_OE:
79 2
            return cp_openeye.Mol.from_smiles(smiles)
80 0
        return cp_rdk.Mol.from_smiles(smiles)
81

82 2
class Atom:
83 2
    def __init__(self, atom):
84

85 2
        if isinstance(atom, AtomAdapter):
86 0
            self.atom = atom.atom
87 0
            self.__class__ = atom.__class__
88

89 2
        elif HAS_OE and isinstance(atom, oechem.OEAtomBase):
90 0
            self.__class__ = cp_openeye.Atom
91 0
            self.__class__.__init__(self, atom)
92

93 2
        elif HAS_RDK and isinstance(atom, Chem.rdchem.Atom):
94 0
            self.__class__ = cp_rdk.Atom
95 0
            self.__class__.__init__(self, atom)
96

97
        else:
98 2
            err_msg = """
99
            Your atom has the type %s.
100
            Currently ChemPer only supports OpenEye and RDKit.
101
            To add support to a new toolkit submit an issue on GitHub at
102
            github.com/MobleyLab/chemper
103
            """
104 2
            raise TypeError(err_msg % type(atom))
105

106

107 2
class Bond:
108 2
    def __init__(self, bond):
109 2
        if isinstance(bond, BondAdapter):
110 0
            self.bond = bond.bond
111 0
            self.__class__ = bond.__class__
112

113 2
        elif HAS_OE and isinstance(bond, oechem.OEBondBase):
114 0
            self.__class__ = cp_openeye.Bond
115 0
            self.__class__.__init__(self,bond)
116

117 2
        elif HAS_RDK and isinstance(bond, Chem.rdchem.Bond):
118 0
            self.__class__ = cp_rdk.Bond
119 0
            self.__class__.__init__(self,bond)
120

121
        else:
122 2
            err_msg = """
123
            Your bond has the type %s.
124
            Currently ChemPer only supports OpenEye and RDKit.
125
            To add support to a new toolkit submit an issue on GitHub at
126
            github.com/MobleyLab/chemper
127
            """
128 2
            raise TypeError(err_msg % type(bond))
129

130
# =======================================
131
# check user specifications
132
# =======================================
133

134 2
def check_toolkit(toolkit=None):
135
    """
136

137
    Parameters
138
    ----------
139
    toolkit : str
140
              'openeye', 'rdkit', or None
141
              if None then the toolkit will be picked automatically
142

143
    Returns
144
    -------
145
    toolkit : str
146
              returns the name of the toolkit to be used.
147
              If the package isn't available for the specified toolkit
148
              then an error is raised instead
149
    """
150
    # check for a stable
151 2
    if toolkit is None:
152 2
        if HAS_OE:
153 2
            return 'openeye'
154 0
        elif HAS_RDK:
155 0
            return 'rdkit'
156

157 2
    if toolkit.lower() == 'openeye' and HAS_OE:
158 2
        return 'openeye'
159

160 2
    if toolkit.lower() == 'rdkit' and HAS_RDK:
161 0
        return 'rdkit'
162

163 2
    if toolkit.lower() == 'openeye' or toolkit.lower() == 'rdkit':
164 2
        raise ImportError("Toolkit (%s) was not importable" % toolkit)
165

166
    else:
167 2
        raise ImportError("The provided toolkit (%s) isn't supported,"\
168
                          " ChemPer only supports 'openeye' and 'rdkit'" \
169
                          % toolkit)
170

171 2
def check_mol_file(file_name):
172
    """
173

174
    Parameters
175
    ----------
176
    file_name : str
177
                path to a molecule file
178

179
    Returns
180
    -------
181
    path : str
182
           absolute path to a molecule file
183
           raises error if file isn't available
184
    """
185
    # is it a local file?
186 2
    if os.path.exists(file_name):
187 2
        return os.path.abspath(file_name)
188

189 2
    path = get_data_path(os.path.join('molecules', file_name))
190

191 2
    if not os.path.exists(path):
192 0
        raise IOError("Molecule file (%s) was not found locally or in chemper/data/molecules" % file_name)
193

194 2
    return path
195

196
# =======================================
197
# get molecules from files
198
# =======================================
199

200 2
def mols_from_mol2(mol2_file, toolkit=None):
201
    """
202
    Creates a list of ChemPer Mols from the provided mol2 file
203
    using a specified or default toolkit
204

205
    Parameters
206
    ----------
207
    mol2_file : str
208
                path to mol2 file, this can be a relative or absolute path locally
209
                or the path to a molecules file stored in ChemPer at chemper/data/molecules/
210
    toolkit : None or str
211
              'openeye' or 'rdkit' are the two supported toolkits
212
              if None then the first package available (in the order listed here)
213
              will be used
214

215
    Returns
216
    -------
217
    mol2s : list[ChemPer Mol]
218
            List of molecules in the provided mol2 file
219
    """
220 2
    toolkit = check_toolkit(toolkit)
221 2
    mol2_path = check_mol_file(mol2_file)
222

223 2
    if toolkit.lower() == 'openeye':
224 2
        return cp_openeye.mols_from_mol2(mol2_path)
225

226 0
    return cp_rdk.mols_from_mol2(mol2_path)
227

228

229

Read our documentation on viewing source code .

Loading