Source code for oddt.utils

"""Common utilities for ODDT"""
from itertools import islice
from types import GeneratorType

import numpy as np
import oddt


[docs]def is_molecule(obj): """Check whether an object is an `oddt.toolkits.{rdk,ob}.Molecule` instance. .. versionadded:: 0.6 """ return is_openbabel_molecule(obj) or is_rdkit_molecule(obj)
[docs]def is_openbabel_molecule(obj): """Check whether an object is an `oddt.toolkits.ob.Molecule` instance. .. versionadded:: 0.6 """ return (hasattr(oddt.toolkits, 'ob') and isinstance(obj, oddt.toolkits.ob.Molecule))
[docs]def is_rdkit_molecule(obj): """Check whether an object is an `oddt.toolkits.rdk.Molecule` instance. .. versionadded:: 0.6 """ return (hasattr(oddt.toolkits, 'rdk') and isinstance(obj, oddt.toolkits.rdk.Molecule))
[docs]def check_molecule(mol, force_protein=False, force_coords=False, non_zero_atoms=False): """Universal validator of molecule objects. Usage of positional arguments is allowed only for molecule object, otherwise it is prohibitted (i.e. the order of arguments **will** change). Desired properties of molecule are validated based on specified arguments. By default only the object type is checked. In case of discrepancy to the specification a `ValueError` is raised with appropriate message. .. versionadded:: 0.6 Parameters ---------- mol: oddt.toolkit.Molecule object Object to verify force_protein: bool (default=False) Force the molecule to be marked as protein (mol.protein). force_coords: bool (default=False) Force the molecule to have non-zero coordinates. non_zero_atoms: bool (default=False) Check if molecule has at least one atom. """ # TODO 2to3 force only one positional argument by adding * to args if not is_molecule(mol): raise ValueError('Molecule object was expected, insted got: %s' % str(mol)) if force_protein and not mol.protein: raise ValueError('Molecule "%s" is not marked as a protein. Mark it by ' 'setting the protein property to `True` (`mol.protein ' '= True)' % mol.title) if force_coords and (not mol.coords.any() or np.isnan(mol.coords).any()): raise ValueError('Molecule "%s" has no 3D coordinates. All atoms are ' 'located at (0, 0, 0).' % mol.title) if non_zero_atoms and len(mol.atoms) == 0: raise ValueError('Molecule "%s" has zero atoms.' % mol.title)
[docs]def compose_iter(iterable, funcs): """Chain functions and apply them to iterable, by exhausting the iterable. Functions are executed in the order from funcs. .. versionadded:: 0.6 """ for func in funcs: iterable = func(iterable) return list(iterable)
[docs]def chunker(iterable, chunksize=100): """Generate chunks from a generator object. If iterable is passed which is not a generator it will be converted to one with `iter()`. .. versionadded:: 0.6 """ # ensure it is a generator if not isinstance(iterable, GeneratorType): iterable = iter(iterable) chunk = list(islice(iterable, chunksize)) while chunk: yield chunk chunk = list(islice(iterable, chunksize))
# TODO 2to3 remove it when support for Python 2.7 is dropped
[docs]def method_caller(obj, methodname, *args, **kwargs): """Helper function to workaround Python 2 pickle limitations to parallelize methods and generator objects""" return getattr(obj, methodname)(*args, **kwargs)