Source code for dynsight._internal.descriptors.tica

"""tICA functions."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from numpy.typing import NDArray

import numpy as np

try:
    from deeptime.decomposition import TICA
except ImportError:
    TICA = None


[docs] def many_body_tica( data: NDArray[np.float64], lag_time: int, tica_dim: int, ) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]: """Perform tICA on trajectories from a many-body system. The tICA model is fitted on the entire dataset, concatenating different atoms one after the other. Then, with this model, the trajectories of the individual atoms are trnsformed individually. The model is fitted using the 'kinetic_map' scaling, which is the suggested one if data are subsequently clustered. This function uses the TICA module from the deeptime package; refer to `Moritz Hoffmann et al 2022 Mach. Learn.: Sci. Technol. 3 015009 <https://iopscience.iop.org/article/10.1088/2632-2153/ac3de0/meta>`_. Parameters: data: shape (n_atoms, n_frames, n_dims) The multivariated data for tICA dimensionality reduction. lag_time The lagtime under which time correlations are maximized. tica_dim The number of dimensions to keep. Returns: * The typical relaxation time-scale of each tIC * The coefficient matrix for the tICA projection; shape (tica_dim, n_dims) * The original dataset projected onto tICs; shape (n_atoms, n_frames, tica_dim) Example: .. code-block:: python import numpy as np from dynsight.descriptors import many_body_tica np.random.seed(42) random_array = np.random.rand(100, 100, 10) relax_times, coeffs, tica_data = many_body_tica( random_array, lag_time=10, tica_dim=3) """ *_, n_dim = data.shape if TICA is None: msg = "Please install deeptime using pip or conda." raise ModuleNotFoundError(msg) tica = TICA(lagtime=lag_time, dim=tica_dim) full_dataset = data.reshape(-1, n_dim) tica.fit(full_dataset, scaling="kinetic_map") koopman_model = tica.fetch_model() relax_times = koopman_model.timescales() eigenvectors = koopman_model.instantaneous_coefficients tica_data = np.array([tica.transform(atom) for atom in data]) return relax_times, eigenvectors[:tica_dim], tica_data