Source code for mordred.TopologicalCharge

from itertools import chain

import numpy as np
from six import integer_types

from ._base import Descriptor
from ._graph_matrix import DistanceMatrix, AdjacencyMatrix

__all__ = ("TopologicalCharge",)


class ChargeTermMatrix(Descriptor):
    __slots__ = ()
    explicit_hydrogens = False

    def parameters(self):
        return ()

    def dependencies(self):
        return {
            "A": AdjacencyMatrix(self.explicit_hydrogens),
            "D": DistanceMatrix(self.explicit_hydrogens),
        }

    def calculate(self, A, D):
        D2 = D.copy()
        D2[D2 != 0] **= -2
        np.fill_diagonal(D2, 0)

        M = A.dot(D2)
        return M - M.T


[docs]class TopologicalCharge(Descriptor): r"""topological charge descriptor. :type type: str :param type: * "raw": sum of order-distance atom pairs coefficient * "mean": mean of order-distance atom pairs coefficient * "global": sum of mean-topoCharge over 0 to order :type order: int :param order: int References * :doi:`10.1021/ci00019a008` """ since = "1.0.0" __slots__ = ("_type", "_order") explicit_hydrogens = False tc_types = ("global", "mean", "raw")
[docs] def description(self): return "{}-ordered {} topological charge".format( self._order, self._type, )
@classmethod def preset(cls, version): return chain( (cls(t, o) for t in ("raw", "mean") for o in range(1, 11)), [cls("global", 10)], ) def __str__(self): if self._type == "global": return "JGT{}".format(self._order) elif self._type == "mean": return "JGI{}".format(self._order) else: return "GGI{}".format(self._order) def parameters(self): return self._type, self._order def __init__(self, type="global", order=10): assert type in self.tc_types assert type == "global" or isinstance(order, integer_types) self._type = type self._order = order def dependencies(self): return { "CT": ChargeTermMatrix(), "D": DistanceMatrix(self.explicit_hydrogens), } def calculate(self, CT, D): D = D * np.tri(*D.shape) D[D == 0] = np.inf f = D <= self._order if self._type == "global" else D == self._order CT = CT[f] if self._type == "raw": return np.abs(CT).sum() # create frequency vector Df = D[f] C = Df.copy() for i in np.unique(Df): C[Df == i] = len(Df[Df == i]) return np.abs(CT / C).sum() rtype = float