From 8d2e7b7e608e901f07382e84143fb744cdc08e7e Mon Sep 17 00:00:00 2001 From: Hirotomo Moriwaki Date: Thu, 17 Aug 2017 01:07:13 +0900 Subject: [PATCH] add Result type --- docs/mordred.rst | 3 ++ mordred/__init__.py | 2 ++ mordred/_base/__init__.py | 43 ++-------------------- mordred/_base/calculator.py | 14 +++++--- mordred/_base/parallel.py | 2 +- mordred/_base/result.py | 63 +++++++++++++++++++++++++++++++++ mordred/_base/util.py | 41 +++++++++++++++++++++ scripts/requirements-flake8.txt | 2 +- 8 files changed, 124 insertions(+), 46 deletions(-) create mode 100644 mordred/_base/result.py create mode 100644 mordred/_base/util.py diff --git a/docs/mordred.rst b/docs/mordred.rst index d9794676..32529a31 100644 --- a/docs/mordred.rst +++ b/docs/mordred.rst @@ -3,6 +3,9 @@ mordred package .. automodule:: mordred +.. autoclass:: mordred.Result + :members: + .. autoclass:: mordred.Descriptor :members: diff --git a/mordred/__init__.py b/mordred/__init__.py index 86d5e942..e0f47465 100644 --- a/mordred/__init__.py +++ b/mordred/__init__.py @@ -6,6 +6,7 @@ Descriptor, get_descriptors_from_module, is_missing, + Result, ) from ._version import __version__ @@ -17,4 +18,5 @@ "all_descriptors", "get_descriptors_from_module", "is_missing", + "Result", ) diff --git a/mordred/_base/__init__.py b/mordred/_base/__init__.py index ee3dc822..b68f7e51 100644 --- a/mordred/_base/__init__.py +++ b/mordred/_base/__init__.py @@ -1,9 +1,5 @@ """Mordred base package.""" -import os -import warnings - -from importlib import import_module from ..error import MissingValueBase from .descriptor import ( @@ -12,6 +8,8 @@ ) from .calculator import Calculator, get_descriptors_from_module from .parallel import parallel +from .util import is_missing, all_descriptors +from .result import Result __all__ = ( @@ -20,32 +18,10 @@ "Calculator", "get_descriptors_from_module", "is_missing", + "Result", ) -def all_descriptors(): - r"""**[deprecated]** use mordred.descriptors module instead. - - yield all descriptor modules. - - :returns: all modules - :rtype: :py:class:`Iterator` (:py:class:`Descriptor`) - """ - warnings.warn( - "all_descriptors() is deprecated, use mordred.descriptors module instead", - DeprecationWarning, - stacklevel=2, - ) - base_dir = os.path.dirname(os.path.dirname(__file__)) - - for name in os.listdir(base_dir): - name, ext = os.path.splitext(name) - if name[:1] == "_" or ext != ".py" or name == "descriptors": - continue - - yield import_module(".." + name, __package__) - - def _Descriptor__call__(self, mol, id=-1): r"""Calculate single descriptor value. @@ -116,19 +92,6 @@ def _Descriptor_from_json(self, obj): return _from_json(obj, descs) -def is_missing(v): - """Check argument is either MissingValue or not. - - Parameters: - v(any): value - - Returns: - bool - - """ - return isinstance(v, MissingValueBase) - - Descriptor.__call__ = _Descriptor__call__ Descriptor.from_json = _Descriptor_from_json Calculator._parallel = parallel diff --git a/mordred/_base/calculator.py b/mordred/_base/calculator.py index f9723f8d..975898f1 100644 --- a/mordred/_base/calculator.py +++ b/mordred/_base/calculator.py @@ -9,6 +9,7 @@ from .._util import Capture, DummyBar, NotebookWrapper from ..error import Error, Missing, MultipleFragments, DuplicatedDescriptorName +from .result import Result from .context import Context from .descriptor import Descriptor, MissingValueException, is_descriptor_class @@ -235,16 +236,21 @@ def __call__(self, mol, id=-1): :type id: int :param id: conformer id - :rtype: [scalar or Error] + :rtype: Result[scalar or Error] :returns: iterator of descriptor and value """ - return list(self._calculate(Context.from_calculator(self, mol, id))) + return self._wrap_result( + self._calculate(Context.from_calculator(self, mol, id)), + ) + + def _wrap_result(self, r): + return Result(r, self._descriptors) def _serial(self, mols, nmols, quiet, ipynb, id): with self._progress(quiet, nmols, ipynb) as bar: for m in mols: with Capture() as capture: - r = list(self._calculate(Context.from_calculator(self, m, id))) + r = self._wrap_result(self._calculate(Context.from_calculator(self, m, id))) for e in capture.result: e = e.rstrip() @@ -314,7 +320,7 @@ def map(self, mols, nproc=None, nmols=None, quiet=False, ipynb=False, id=-1): id(int): conformer id to use. default: -1. Returns: - Iterator[scalar] + Iterator[Result[scalar]] """ if hasattr(mols, "__len__"): diff --git a/mordred/_base/parallel.py b/mordred/_base/parallel.py index e4422c13..e15cdf8c 100644 --- a/mordred/_base/parallel.py +++ b/mordred/_base/parallel.py @@ -50,7 +50,7 @@ def do_task(mol): bar.write(e) - yield r + yield self._wrap_result(r) bar.update() finally: diff --git a/mordred/_base/result.py b/mordred/_base/result.py new file mode 100644 index 00000000..3314685b --- /dev/null +++ b/mordred/_base/result.py @@ -0,0 +1,63 @@ +from .util import is_missing + + +class Result(list): + r"""Result type.""" + + def __init__(self, r, d): + super(Result, self).__init__(r) + self._descriptors = d + + def fillna(self, value=float('nan')): + r"""Replace missing value to 'value'. + + Parameters: + value: value that missing value is replaced + + Returns: + Result + + """ + return self.__class__( + [(value if is_missing(v) else v) for v in self], + self._descriptors, + ) + + def dropna(self): + r"""Delete missing value. + + Returns: + Result + + """ + newvalues = [] + newdescs = [] + for v, d in zip(self, self._descriptors): + if not is_missing(v): + newvalues.append(v) + newdescs.append(d) + + return self.__class__(newvalues, newdescs) + + def asdict(self, rawkey=False): + r"""Convert Result to dict. + + Parameters: + rawkey(bool): + * True: dict key is Descriptor instance + * False: dict key is str + + Returns: + dict + + """ + if rawkey: + def keyconv(k): + return k + else: + keyconv = str + + return { + keyconv(k): v + for k, v in zip(self._descriptors, self) + } diff --git a/mordred/_base/util.py b/mordred/_base/util.py new file mode 100644 index 00000000..b7fd798f --- /dev/null +++ b/mordred/_base/util.py @@ -0,0 +1,41 @@ +import os +import warnings +from importlib import import_module + +from ..error import MissingValueBase + + +def all_descriptors(): + r"""**[deprecated]** use mordred.descriptors module instead. + + yield all descriptor modules. + + :returns: all modules + :rtype: :py:class:`Iterator` (:py:class:`Descriptor`) + """ + warnings.warn( + "all_descriptors() is deprecated, use mordred.descriptors module instead", + DeprecationWarning, + stacklevel=2, + ) + base_dir = os.path.dirname(os.path.dirname(__file__)) + + for name in os.listdir(base_dir): + name, ext = os.path.splitext(name) + if name[:1] == "_" or ext != ".py" or name == "descriptors": + continue + + yield import_module(".." + name, __package__) + + +def is_missing(v): + """Check argument is either MissingValue or not. + + Parameters: + v(any): value + + Returns: + bool + + """ + return isinstance(v, MissingValueBase) diff --git a/scripts/requirements-flake8.txt b/scripts/requirements-flake8.txt index 0179f4f3..2e6a0c23 100644 --- a/scripts/requirements-flake8.txt +++ b/scripts/requirements-flake8.txt @@ -1,5 +1,5 @@ +pep8 flake8 -flake8-isort flake8-double-quotes flake8-print flake8-commas