Source code for mordred.BCUT
import numpy as np
from ._base import Descriptor
from ._util import to_ordinal
from ._atomic_property import AtomicProperty, get_properties
__all__ = ("BCUT",)
class BCUTBase(Descriptor):
__slots__ = ()
explicit_hydrogens = False
require_connected = True
class Burden(BCUTBase):
__slots__ = ()
def parameters(self):
return ()
def calculate(self):
N = self.mol.GetNumAtoms()
mat = 0.001 * np.ones((N, N))
for bond in self.mol.GetBonds():
a = bond.GetBeginAtom()
b = bond.GetEndAtom()
i = a.GetIdx()
j = b.GetIdx()
try:
w = bond.GetBondTypeAsDouble() / 10.0
except RuntimeError:
self.fail(ValueError("unknown bond type"))
if a.GetDegree() == 1 or b.GetDegree() == 1:
w += 0.01
mat[i, j] = w
mat[j, i] = w
return mat
class BurdenEigenValues(BCUTBase):
__slots__ = ("_prop",)
def parameters(self):
return (self._prop,)
def __init__(self, prop):
self._prop = prop
def dependencies(self):
return {"burden": Burden(), "ps": self._prop}
def calculate(self, burden, ps):
bmat = burden.copy()
np.fill_diagonal(bmat, ps)
ev = np.linalg.eig(bmat)[0]
if np.iscomplexobj(ev):
ev = ev.real
return np.sort(ev)[-1::-1]
[docs]
class BCUT(BCUTBase):
r"""BCUT descriptor.
:type prop: :py:class:`str` or :py:class:`function`
:param prop: :ref:`atomic_properties`
:type nth: int
:param nth: n-th eigen value. 0 is highest, -1 is lowest.
:returns: NaN when
* any atomic properties are NaN
* :math:`\left| nth \right| > A`
"""
since = "1.0.0"
__slots__ = ("_prop", "_nth")
[docs]
def description(self):
return "{} {} eigenvalue of Burden matrix weighted by {}".format(
to_ordinal(np.abs(self._nth) if self._nth < 0 else 1 + self._nth),
"lowest" if self._nth < 0 else "heighest",
self._prop.get_long(),
)
@classmethod
def preset(cls, version):
return (
cls(a, n)
for a in get_properties(valence=True, charge=True)
for n in [0, -1]
)
def __str__(self):
if self._nth < 0:
return "BCUT{}-{}l".format(self._prop.as_argument, np.abs(self._nth))
else:
return "BCUT{}-{}h".format(self._prop.as_argument, self._nth + 1)
def parameters(self):
return self._prop, self._nth
def __init__(self, prop="m", nth=0):
self._prop = AtomicProperty(self.explicit_hydrogens, prop)
self._nth = nth
def dependencies(self):
return {"bev": BurdenEigenValues(self._prop)}
def calculate(self, bev):
try:
return bev[self._nth]
except IndexError:
self.fail(ValueError("nth greater then atom count"))
rtype = float