Source code for mordred.MomentOfInertia

import numpy as np

from ._base import Descriptor
from ._util import atoms_to_numpy

__all__ = ("MomentOfInertia",)


class MomentOfInertiaBase(Descriptor):
    __slots__ = ()
    require_3D = True

    def _numpy(self):
        ws = atoms_to_numpy(lambda a: a.GetMass(), self.mol)
        ps = self.coord - np.sum(ws[:, np.newaxis] * self.coord, axis=0) / np.sum(ws)

        return ws, ps


class PrincipalAxis(MomentOfInertiaBase):
    __slots__ = ()

    def parameters(self):
        return ()

    def calculate(self):
        ws, ps = self._numpy()

        I = np.sum(
            -ws[:, np.newaxis, np.newaxis] *
            (ps[:, np.newaxis] * ps[:, :, np.newaxis]),
            axis=0,
        )

        diag = np.sum(
            ws[:, np.newaxis] *
            (np.sum(ps ** 2, axis=1)[:, np.newaxis] - ps ** 2),
            axis=0,
        )

        np.fill_diagonal(I, diag)
        return np.sort(np.linalg.eig(I)[0])[::-1]


[docs]class MomentOfInertia(MomentOfInertiaBase): __slots__ = "_axis",
[docs] def description(self): return "moment of inertia (axis = {})".format(self._axis)
@classmethod def preset(cls): return map(cls, cls.axes) def __str__(self): return "MOMI-{}".format(self._axis) def parameters(self): return self._axis, axes = ("X", "Y", "Z") _axis_to_index = {a: i for i, a in enumerate(axes)} def __init__(self, axis="X"): assert axis in self.axes self._axis = axis def dependencies(self): return {"I": PrincipalAxis()} def calculate(self, I): return I[self._axis_to_index[self._axis]] rtype = float