Source code for mordred.MoRSE

from __future__ import division

from itertools import chain

import numpy as np

from ._graph_matrix import DistanceMatrix3D
from ._atomic_property import AtomicProperty
from ._base.descriptor import Descriptor

__all__ = ("MoRSE",)


[docs] class MoRSE(Descriptor): since = "1.0.0" __slots__ = ("_prop", "_distance") require_3D = True
[docs] def description(self): return "3D-MoRSE{} (distance = {})".format( "" if self._prop is None else " weighted by {}".format(self._prop.get_long()), self._distance, )
@classmethod def preset(cls, version): return chain( (cls(None, i) for i in range(1, 33)), (cls("m", i) for i in range(1, 33)), (cls("v", i) for i in range(1, 33)), (cls("se", i) for i in range(1, 33)), (cls("p", i) for i in range(1, 33)), ) def __str__(self): p = "" if self._prop is None else self._prop.as_argument return "Mor{:02d}{}".format(self._distance, p) def parameters(self): p = None if self._prop is None else self._prop.as_argument return p, self._distance def __init__(self, prop=None, distance=2): if prop is None: self._prop = None else: self._prop = AtomicProperty(self.explicit_hydrogens, prop) self._distance = distance def dependencies(self): d = {"D": DistanceMatrix3D(self.explicit_hydrogens)} if self._prop is not None: d["A"] = self._prop return d def calculate(self, D, A=None): if D.shape[0] <= 1: self.fail(ValueError("require 2 or more atoms")) N = D.shape[0] if A is None: A = np.ones(N) else: A = A / self._prop.carbon A = A.reshape(1, -1) if self._distance == 1: n = np.ones((N, N), dtype="float") else: with self.rethrow_zerodiv(): sr = (self._distance - 1) * D np.fill_diagonal(sr, 1) n = np.sin(sr) / sr np.fill_diagonal(n, 0) return float(0.5 * np.ravel(A.dot(n).dot(A.T))[0]) rtype = float