BaseFilter.axes_names()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.125

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 2
ccs 1
cts 2
cp 0.5
rs 10
cc 1
crap 1.125
1
#! /usr/bin/env python
2
#
3
# Copyright (C) 2015-2016 Rich Lewis <[email protected]>
4
# License: 3-clause BSD
5
6 1
"""
7
# skchem.filters
8
9
Chemical filters are defined.
10
11
"""
12
13 1
import pandas as pd
0 ignored issues
show
Configuration introduced by
The import pandas 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
15 1
from ..base import BaseTransformer, Transformer
16 1
from .. import core
17 1
from ..utils import iterable_to_series, Defaults, optional_second_method
18
19
20 1
def not_all(x):
0 ignored issues
show
Coding Style Naming introduced by
The name x does not conform to the argument 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...
21
    """ Not all x """
22
    return not all(x)
23
24
25 1
def not_any(x):
0 ignored issues
show
Coding Style Naming introduced by
The name x does not conform to the argument 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...
26
    """ Not any x """
27 1
    return not any(x)
28
29
30 1
def identity(x):
0 ignored issues
show
Coding Style Naming introduced by
The name x does not conform to the argument 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...
31
    """ The identity """
32
    return x
33
34
35 1
AGGS = Defaults(defaults={
36
    'none': identity,
37
    'any': any,
38
    'all': all,
39
    'not all': not_all,
40
    'not any': not_any
41
})
42
43
44 1
class BaseFilter(BaseTransformer):
45
46
    """ The base Filter class. """
47
48 1
    def __init__(self, agg='any', **kwargs):
49 1
        self._agg = None
50 1
        super(BaseFilter, self).__init__(**kwargs)
51 1
        self.agg = agg
52
53 1
    def axes_names(self):
54
        return 'batch', self.columns.name
55
56 1
    @property
57
    def agg(self):
58
        """ callable: The aggregate function to use.  String aliases
59
        for `'any'`, `'not any'`, 'all', `'not all'` are available."""
60 1
        return self._agg
61
62 1
    @agg.setter
63
    def agg(self, val):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
64 1
        self._agg = AGGS.get(val)
65
66 1
    @property
67
    def columns(self):
68
69
        """ pd.Index: The column index to use. """
70
71 1
        return pd.Index([self.__class__.__name__])
72
73 1
    def _mask(self, mols=None, res=None, neg=False):
74
75
        """ Generate a mask from molecules, or from their result after transform.
76
77
        Args:
78
            mols (pd.Series<skchem.Mol>):
79
                The molecules to use to generate the mask.
80
            res (pd.Series):
81
                The result of a transform. Overrides mols.
82
            neg (bool):
83
                Whether the mask should be inversed.
84
85
        Returns:
86
            pd.Series<bool>
87
        """
88
89 1
        res = self.transform(mols, agg=False) if res is None else res
90 1
        res = (res != 0) & pd.notnull(res)
91 1
        if isinstance(res, pd.Series) and isinstance(mols, core.Mol):
92 1
            res = self.agg(res)
0 ignored issues
show
Bug introduced by
self.agg does not seem to be callable.
Loading history...
93 1
        if isinstance(res, pd.DataFrame):
94 1
            res = res.apply(self.agg, axis=1)
95 1
        return res == 0 if neg else res
96
97 1
    @optional_second_method
98 1
    def transform(self, mols, agg=True, **kwargs):
99
100
        # transform takes additional optional kwarg `agg`, that specifies to
101
        # transform to the aggregated value or return the full series.
102
103 1
        if agg:
104 1
            return self._mask(mols)
105
        else:
106 1
            return super(BaseFilter, self).transform(mols, **kwargs)
107
108 1
    def filter(self, mols, y=None, neg=False):
0 ignored issues
show
Coding Style Naming introduced by
The name y does not conform to the argument 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...
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
109
110 1
        mask = self._mask(mols=mols, neg=neg)
111
112 1
        if isinstance(mols, core.Mol):
113
            return mols if mask else None
114
115 1
        elif not isinstance(mols, pd.Series):
116 1
            mols = iterable_to_series(mols)
117
118 1
        if y is None:
119 1
            return mols[mask]
120
        else:
121
            return mols[mask], y[mask]
122
123
124 1
class Filter(BaseFilter, Transformer):
125
    """ Filter base class.
126
127
     Examples:
128
129
         >>> import skchem
130
131
         Initialize the filter with a function:
132
         >>> is_named = skchem.filters.Filter(lambda m: m.name is not None)
133
134
         Filter results can be found with `transform`:
135
         >>> ethane = skchem.Mol.from_smiles('CC', name='ethane')
136
         >>> is_named.transform(ethane)
137
         True
138
139
         >>> anonymous = skchem.Mol.from_smiles('c1ccccc1')
140
         >>> is_named.transform(anonymous)
141
         False
142
143
         Can take a series or dataframe:
144
         >>> mols = pd.Series({'anonymous': anonymous, 'ethane': ethane})
145
         >>> is_named.transform(mols)
146
         anonymous    False
147
         ethane        True
148
         Name: Filter, dtype: bool
149
150
         Using `filter` will drop out molecules that fail the test:
151
         >>> is_named.filter(mols)
152
         ethane    <Mol: CC>
153
         dtype: object
154
155
         Only failed are retained with the `neg` keyword argument:
156
         >>> is_named.filter(mols, neg=True)
157
         anonymous    <Mol: c1ccccc1>
158
         dtype: object
159
     """
160 1
    def __init__(self, func=None, agg='any', n_jobs=1, verbose=True):
161
162
        """ Initialize a `Filter` object.
163
164
             Args:
165
             func (function: Mol => bool):
166
                 The function to use to filter the arguments.
167
             agg (str or function: iterable<bool> => bool):
168
                 The aggregation to use in the filter. Can be 'any', 'all',
169
                 'not any', 'not all' or a callable, for example `any` or `all`.
170
        """
171
172 1
        super(Filter, self).__init__(agg=agg, n_jobs=n_jobs, verbose=verbose)
173 1
        if func is not None:
174 1
            self._transform_mol = func
175
176 1
    def _transform_mol(self, mol):
0 ignored issues
show
Bug introduced by
This method seems to be hidden by an attribute defined in skchem.filters.base on line 174.
Loading history...
177
        raise NotImplemented
0 ignored issues
show
Best Practice introduced by
NotImplemented raised - should raise NotImplementedError
Loading history...
178
179
180 1
class TransformFilter(BaseFilter):
181
182
    """ Transform Filter object.
183
184
     Implements `transform_filter`, which allows a transform, then a
185
     filter step returning the transformed values that are not `False`, `None`
186
     or `np.nan`.
187
188
     """
189
190 1
    def transform_filter(self, mols, y=None, neg=False):
0 ignored issues
show
Coding Style Naming introduced by
The name y does not conform to the argument 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...
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
191
192
        res = self.transform(mols)
193
        mask = self._mask(res=res, neg=neg)
194
195
        if isinstance(mols, core.Mol):
196
            return res if mask else None
197
198
        if y is None:
199
            return res[mask]
200
        else:
201
            return res[mask], y[mask]
202