1
"""
2
cp_openeye.py
3

4
Cheminformatics tools using OpenEye Toolkits
5

6
The classes provided here follow the structure in adapters.
7
This is a wrapper allowing our actual package to use openeye toolkits
8
"""
9

10 41
from chemper.mol_toolkits.adapters import MolAdapter, AtomAdapter, BondAdapter
11 41
from openeye import oechem
12

13

14
# Note - doc strings on these functions are inherited from
15
#        there Adapters. To read these strings see adapters.py.
16

17
# =======================================
18
# Molecule Class
19
# =======================================
20

21 41
class Mol(MolAdapter):
22 41
    def __init__(self, mol):
23
        """
24
        ChemPer created from an OEMol
25

26
        Parameters
27
        ----------
28
        mol : openeye OEMol object
29
            openeye molecule to convert to ChemPer Mol object
30
        """
31 41
        if not isinstance(mol, oechem.OEMolBase):
32 41
            raise TypeError("Expecting an OEMol object instead of %s" % type(mol))
33 41
        self.mol = mol
34

35 41
    def __str__(self): return self.get_smiles()
36

37 41
    @classmethod
38
    def from_smiles(cls, smiles):
39 41
        mol = oechem.OEMol()
40 41
        if not oechem.OESmilesToMol(mol, smiles):
41 41
            raise ValueError('Could not parse SMILES %s' % smiles)
42 41
        oechem.OEAddExplicitHydrogens(mol)
43 41
        return cls(mol)
44

45 41
    def set_aromaticity_mdl(self):
46 41
        oechem.OEClearAromaticFlags(self.mol)
47 41
        oechem.OEAssignAromaticFlags(self.mol, oechem.OEAroModel_MDL)
48 41
        oechem.OEAssignHybridization(self.mol)
49

50 41
    def get_atoms(self):
51 41
        return [Atom(a) for a in self.mol.GetAtoms()]
52

53 41
    def get_atom_by_index(self, idx):
54 41
        return Atom(self.mol.GetAtom(oechem.OEHasAtomIdx(idx)))
55

56 41
    def get_bonds(self):
57 41
        return [Bond(b) for b in self.mol.GetBonds()]
58

59 41
    def get_bond_by_index(self, idx):
60 41
        return Bond(self.mol.GetBond(oechem.OEHasBondIdx(idx)))
61

62 41
    def get_bond_by_atoms(self, atom1, atom2):
63 41
        if not atom1.is_connected_to(atom2):
64 41
            return None
65 41
        return Bond(self.mol.GetBond(atom1.atom, atom2.atom))
66

67 41
    def smirks_search(self, smirks):
68 41
        cmol = oechem.OEMol(self.mol)
69

70 41
        matches = list()
71

72 41
        ss = oechem.OESubSearch()
73 41
        if not ss.Init(smirks):
74 41
            raise ValueError("Error parsing SMIRKS %s" % smirks)
75

76
        # set maximum matches in substructure search to infinite (0 in API)
77 41
        ss.SetMaxMatches(0)
78 41
        for match in ss.Match(cmol, False):
79 41
            d = dict()
80 41
            for ma in match.GetAtoms():
81 41
                smirks_idx = ma.pattern.GetMapIdx()
82
                # if the map index is 0 then it isn't a "tagged" atom in the SMIRKS
83 41
                if smirks_idx !=0:
84 41
                    d[smirks_idx] = self.get_atom_by_index(ma.target.GetIdx())
85

86 41
            matches.append(d)
87

88 41
        return matches
89

90 41
    def get_smiles(self):
91 41
        smiles = oechem.OEMolToSmiles(self.mol)
92 41
        return smiles
93

94
# =======================================
95
# Atom Class
96
# =======================================
97

98 41
class Atom(AtomAdapter):
99 41
    def __init__(self, atom):
100
        """
101
        ChemPer Atom created from an OEAtom
102

103
        Parameters
104
        ----------
105
        atom: OEAtomBase
106
            Atom object from an OpenEye molecule
107
        """
108 41
        if not isinstance(atom, oechem.OEAtomBase):
109 41
            raise TypeError("Expecting an OEAtomBase object instead of %s" % type(atom))
110 41
        self.atom = atom
111 41
        self._idx = self.atom.GetIdx()
112

113 41
    def __str__(self): return "%i%s" % (self._idx,
114
                                        oechem.OEGetAtomicSymbol(self.atomic_number()))
115

116 41
    def atomic_number(self): return self.atom.GetAtomicNum()
117

118 41
    def degree(self): return self.atom.GetDegree()
119

120 41
    def connectivity(self):
121 41
        return len([b for b in self.atom.GetBonds()])
122

123 41
    def valence(self): return self.atom.GetValence()
124

125 41
    def formal_charge(self): return self.atom.GetFormalCharge()
126

127 41
    def hydrogen_count(self): return self.atom.GetTotalHCount()
128

129 41
    def ring_connectivity(self):
130 41
        return len([b for b in self.atom.GetBonds(oechem.OEBondIsInRing())])
131

132 41
    def min_ring_size(self):
133 41
        return oechem.OEAtomGetSmallestRingSize(self.atom)
134

135 41
    def is_aromatic(self): return self.atom.IsAromatic()
136

137 41
    def get_index(self): return self._idx
138

139 41
    def is_connected_to(self, atom2):
140 41
        if not isinstance(atom2.atom, oechem.OEAtomBase):
141 0
            return False
142 41
        return self.atom.IsConnected(atom2.atom)
143

144 41
    def get_neighbors(self):
145 41
        return [Atom(a) for a in self.atom.GetAtoms()]
146

147 41
    def get_bonds(self):
148 41
        return [Bond(b) for b in self.atom.GetBonds()]
149

150 41
    def get_molecule(self):
151 41
        mol = oechem.OEMol(self.atom.GetParent())
152 41
        self.atom = mol.GetAtom(oechem.OEHasAtomIdx(self._idx))
153 41
        return Mol(mol)
154

155
# =======================================
156
# Bond Class
157
# =======================================
158

159

160 41
class Bond(BondAdapter):
161 41
    def __init__(self, bond):
162
        """
163
        ChemPer Bond created from an OEBond
164

165
        Parameters
166
        ----------
167
        bond: OEBondBase
168
            Bond object from an OpenEye molecule
169
        """
170 41
        if not isinstance(bond, oechem.OEBondBase):
171 41
            raise TypeError("Expecting an OEBondBase object instead of %s" % type(bond))
172 41
        self.bond = bond
173

174
        # save index
175 41
        self._idx = self.bond.GetIdx()
176

177
        # store order information
178 41
        self._order = self.bond.GetOrder()
179 41
        if self.is_aromatic():
180 41
            self._order = 1.5
181

182 41
        orders = {1:'-', 2:'=', 3:'#', 1.5:':'}
183 41
        self._order_symbol = orders.get(self._order, '~')
184

185
        # save atoms in bond
186 41
        self._beginning = Atom(self.bond.GetBgn())
187 41
        self._end = Atom(self.bond.GetEnd())
188

189 41
    def __str__(self):
190 0
        return "%i %s%s%s" % (self.get_index(), self._beginning,
191
                              self._order_symbol, self._end)
192

193 41
    def get_order(self): return self._order
194

195 41
    def get_atoms(self): return [self._beginning, self._end]
196

197 41
    def is_ring(self): return self.bond.IsInRing()
198

199 41
    def is_aromatic(self): return self.bond.IsAromatic()
200

201 41
    def is_single(self): return self._order == 1
202

203 41
    def is_double(self): return self._order == 2
204

205 41
    def is_triple(self): return self._order == 3
206

207 41
    def get_molecule(self):
208 41
        mol = oechem.OEMol(self.bond.GetParent())
209 41
        self.bond = mol.GetBond(oechem.OEHasBondIdx(self._idx))
210 41
        return Mol(mol)
211

212 41
    def get_index(self): return self._idx
213

214
# =====================================================================
215
# functions for importing molecules from files
216
# =====================================================================
217

218 41
def mols_from_mol2(mol2_file):
219 41
    return mols_from_file(mol2_file)
220

221 41
def mols_from_file(mol_file):
222
    """
223
    Parses a standard molecule file into ChemPer molecules using OpenEye toolkits
224

225
    Parameters
226
    ----------
227
    mol_file: str
228
              relative or full path to molecule containing the molecule file
229
              that is accessible from the current working directory
230

231
    Returns
232
    -------
233
    mols: list[ChemPer Mol]
234
          list of molecules in the mol2 file as ChemPer Mols
235
    """
236 41
    import os
237 41
    if not os.path.exists(mol_file):
238 41
        from chemper.chemper_utils import get_data_path
239 41
        mol_path = get_data_path(os.path.join('molecules', mol_file))
240

241 41
        if not os.path.exists(mol_path):
242 0
            raise IOError("File '%s' not found locally or in chemper/data/molecules." % mol_file)
243
        else:
244 41
            mol_file = mol_path
245

246 41
    molecules = list()
247

248
    # make Openeye input file stream
249 41
    ifs = oechem.oemolistream(mol_file)
250

251 41
    oemol = oechem.OECreateOEGraphMol()
252 41
    while oechem.OEReadMolecule(ifs, oemol):
253
        # if an SD file, the molecule name may be in the SD tags
254 41
        if oemol.GetTitle() == '':
255 0
            name = oechem.OEGetSDData(oemol, 'name').strip()
256 0
            oemol.SetTitle(name)
257
        # Append to list.
258 41
        molecules.append(Mol(oechem.OEMol(oemol)))
259 41
    ifs.close()
260

261 41
    return molecules
262

Read our documentation on viewing source code .

Loading