Completed
Push — master ( 2bc047...202252 )
by Rich
01:16
created

skchem.core.Mol   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 158
Duplicated Lines 0 %
Metric Value
dl 0
loc 158
rs 9.6
wmc 32

13 Methods

Rating   Name   Duplication   Size   Complexity  
A Mol.conformers() 0 7 1
A Mol.to_dict() 0 14 2
B Mol._to_dict_chemdoodle() 0 13 5
B Mol.atom_props() 0 12 5
A Mol.bonds() 0 6 1
A Mol.__init__() 0 3 1
A Mol._two_d() 0 7 2
A Mol.atoms() 0 6 1
A Mol.props() 0 6 1
A Mol.name() 0 9 2
A Mol.to_json() 0 5 1
A Mol.to_inchi_key() 0 5 1
A Mol.to_formula() 0 5 1
1
#! /usr/bin/env python
2
#
3
# Copyright (C) 2007-2009 Rich Lewis <[email protected]>
4
# License: 3-clause BSD
5
6
"""
7
skchem.core.mol
8
9
Defining molecules in scikit-chem.
10
"""
11
12
import rdkit.Chem
0 ignored issues
show
Configuration introduced by
The import rdkit.Chem could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
13
from rdkit.Chem.rdDepictor import Compute2DCoords
0 ignored issues
show
Configuration introduced by
The import rdkit.Chem.rdDepictor could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
14
from rdkit.Chem.rdMolDescriptors import CalcMolFormula
0 ignored issues
show
Configuration introduced by
The import rdkit.Chem.rdMolDescriptors could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
15
16
import json
17
18
from skchem.core import ChemicalObject, Atom, Bond, Conformer
19
20
class Mol(rdkit.Chem.rdchem.Mol, ChemicalObject):
21
22
    """
23
    Class representing a Molecule in scikit-chem.
24
    """
25
26
    def __init__(self, *args, **kwargs):
27
        super(Mol, self).__init__(*args, **kwargs)
28
        self.__two_d = None #set in constructor
29
30
    @property
31
    def name(self):
32
33
        """ Return the name of the molecule. """
34
35
        try:
36
            return self.GetProp('_Name')
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named GetProp.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
37
        except KeyError:
38
            return None
39
40
    @name.setter
41
    def name(self, value):
42
43
        """ Set the name of the molecule. """
44
45
        if value is None:
46
            self.ClearProp('_Name')
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named ClearProp.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
47
        else:
48
            self.SetProp('_Name', value)
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named SetProp.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
49
50
    @property
51
    def atoms(self):
52
53
        """ return an iterable over the atoms of the molecule. """
54
55
        return [Atom.from_super(self.GetAtomWithIdx(i)) for i in range(self.GetNumAtoms())]
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named GetAtomWithIdx.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Bug introduced by
The Instance of Mol does not seem to have a member named GetNumAtoms.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
56
57
    @atoms.setter
58
    def atoms(self, value):
59
60
        """ Set the atoms of a molecule.  Not implemented. """
61
62
        raise NotImplementedError
63
64
    @property
65
    def bonds(self):
66
67
        """ Return an iterable over the bonds of the molecule. """
68
69
        return [Bond.from_super(self.GetBondWithIdx(i)) for i in range(self.GetNumBonds())]
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named GetBondWithIdx.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Bug introduced by
The Instance of Mol does not seem to have a member named GetNumBonds.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
70
71
    @bonds.setter
72
    def bonds(self, value):
73
74
        """ Set the bonds of the molecule. Not implemented. """
75
76
        raise NotImplementedError
77
78
    # use a view to easily set properties?
79
    @property
80
    def props(self):
81
82
        """ Return a dictionary of the properties of the molecule. """
83
84
        return {i: self.GetProp(i) for i in self.GetPropNames()}
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named GetProp.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
Bug introduced by
The Instance of Mol does not seem to have a member named GetPropNames.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
85
86
    @props.setter
87
    def props(self, value):
88
89
        """ Set the properties of the molecule. Not implemented. """
90
91
        raise NotImplementedError
92
93
    @property
94
    def atom_props(self):
95
96
        """ Return a dict of lists of properties on atoms of the molecule. """
97
98
        if not hasattr(self, '_atom_prop_names'):
99
            res = set()
100
            for atom in self.atoms:
101
                res = res.union(set(atom.props.keys()))
102
            self._atom_prop_names = list(res)
0 ignored issues
show
Coding Style introduced by
The attribute _atom_prop_names was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
103
        return {prop: [atom.props.get(prop, None) for atom in self.atoms]
104
                                        for prop in self._atom_prop_names}
0 ignored issues
show
Coding Style introduced by
Wrong continued indentation.
for prop in self._atom_prop_names}
| ^
Loading history...
105
106
    @property
107
    def conformers(self):
108
109
        """ Return a list of conformers of the molecule. """
110
111
        return [Conformer.from_super(self.GetConformer(i)) \
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named GetConformer.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
112
            for i in range(len(self.GetConformers()))]
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named GetConformers.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
113
114
    @conformers.setter
115
    def conformers(self, value):
116
117
        """ Set the conformers of the molecule.  Not implemented. """
118
119
        raise NotImplementedError
120
121
    def to_formula(self):
122
123
        """ Return the chemical formula of the molecule. """
124
125
        return CalcMolFormula(self)
126
127
    def _two_d(self):
128
129
        """ Return a conformer with coordinates in two dimension. """
130
131
        if not hasattr(self, '__two_d'):
132
            self.__two_d = Compute2DCoords(self)
133
        return self.conformers[self.__two_d]
134
135
    def to_dict(self, kind="chemdoodle"):
136
137
        """
138
        Return a dictionary representation of the molecule.
139
140
        TODO
141
142
        """
143
144
        if kind == "chemdoodle":
145
            return self._to_dict_chemdoodle()
146
147
        else:
148
            raise NotImplementedError
149
150
    def _to_dict_chemdoodle(self):
151
152
        """ Return a chemdoodle dict representation of the molecule. """
153
154
        atom_positions = [p.to_dict() for p in self._two_d().atom_positions]
155
        atom_elements = [a.element for a in self.atoms]
156
157
        for i, atom_position in enumerate(atom_positions):
158
            atom_position['l'] = atom_elements[i]
159
160
        bonds = [b.to_dict() for b in self.bonds]
161
162
        return {"m": [{"a": atom_positions, "b": bonds}]}
163
164
    def to_json(self, kind='chemdoodle'):
165
166
        """ Return a JSON representation of the molecule. """
167
168
        return json.dumps(self.to_dict(kind=kind))
169
170
    def to_inchi_key(self, *args, **kwargs):
171
172
        """ Return the INCHI key of the molecule. """
173
174
        return rdkit.Chem.InchiToInchiKey(self.to_inchi(), *args, **kwargs)
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named to_inchi.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
175
176
    def __repr__(self):
177
        return '<{klass} name="{name}" formula="{formula}" at {address}>'.format(
178
            klass=self.__class__.__name__,
179
            name=self.name,
180
            formula=self.to_formula(),
181
            address=hex(id(self)))
182
183
    def _repr_javascript(self):
184
185
        """ Rich printing in javascript. """
186
187
        return self.to_json()
188
189
    def __str__(self):
190
        return '<Mol: {}>'.format(self.to_smiles())
0 ignored issues
show
Bug introduced by
The Instance of Mol does not seem to have a member named to_smiles.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
191
192
def bind_constructor(constructor_name, name_to_bind=None):
193
194
    """ Bind an (rdkit) constructor to the class """
195
196
    @classmethod
197
    def constructor(_, in_arg, name=None, *args, **kwargs):
198
199
        """ The constructor to be bound. """
200
201
        m = getattr(rdkit.Chem, 'MolFrom' + constructor_name)(in_arg, *args, **kwargs)
0 ignored issues
show
Coding Style Naming introduced by
The name m does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
202
        if m is None:
203
            raise ValueError('Failed to parse molecule, {}'.format(in_arg))
204
        m = Mol.from_super(m)
0 ignored issues
show
Coding Style Naming introduced by
The name m does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
205
        m.name = name
206
        return m
207
208
    setattr(Mol, 'from_{}'.format(constructor_name).lower() \
209
        if name_to_bind is None else name_to_bind, constructor)
210
211
def bind_serializer(serializer_name, name_to_bind=None):
212
213
    """ Bind an (rdkit) serializer to the class """
214
215
    def serializer(self, *args, **kwargs):
216
217
        """ The serializer to be bound. """
218
        return getattr(rdkit.Chem, 'MolTo' + serializer_name)(self, *args, **kwargs)
219
220
    setattr(Mol, 'to_{}'.format(serializer_name).lower() \
221
        if name_to_bind is None else name_to_bind, serializer)
222
223
CONSTRUCTORS = ['Inchi', 'Smiles', 'Mol2Block', 'Mol2File', 'MolBlock', \
224
                    'MolFile', 'PDBBlock', 'PDBFile', 'Smarts', 'TPLBlock', 'TPLFile']
225
SERIALIZERS = ['Inchi', 'Smiles', 'MolBlock', 'PDBBlock', 'Smarts', 'TPLBlock', 'TPLFile']
226
227
list(map(bind_constructor, CONSTRUCTORS))
0 ignored issues
show
introduced by
Used builtin function 'map'
Loading history...
228
list(map(bind_serializer, SERIALIZERS))
0 ignored issues
show
introduced by
Used builtin function 'map'
Loading history...
229