Source code for pimms.lemonade.trajectory

"""
LatticeTrajectory - the top of the lemonade object hierarchy.

    LatticeTrajectory  ->  Frame  ->  Polymer            (one chain in one frame)
                                  ->  Cluster -> Polymer  (connected group)

Indexing a trajectory by an integer yields a :class:`Frame` view; slicing yields a
new LatticeTrajectory over that frame range (sharing the topology, no re-parse).
Trajectory-level analysis methods return whole ``(n_frames, n_chains)`` arrays in a
handful of vectorised numpy operations.
"""

import numpy as np

from .frame import Frame


[docs] class LatticeTrajectory: __slots__ = ("_store",) def __init__(self, store): self._store = store # -- metadata ---------------------------------------------------------- @property def store(self): return self._store @property def dimensions(self): return self._store.dimensions @property def n_dim(self): return self._store.n_dim @property def hardwall(self): return self._store.hardwall @property def spacing(self): return self._store.spacing @property def temperature(self): """Simulation temperature (== k_B T in PIMMS reduced units), or None.""" return self._store.temperature @property def n_frames(self): return self._store.n_frames @property def n_chains(self): return self._store.n_chains @property def n_atoms(self): return self._store.n_atoms @property def topology(self): return self._store.topology @property def times(self): return self._store.times @property def sequences(self): return list(self._store.topology.sequences) @property def chain_types(self): return self._store.topology.chain_types # -- navigation -------------------------------------------------------- def __len__(self): return self._store.n_frames def __getitem__(self, key): if isinstance(key, (int, np.integer)): i = int(key) if i < 0: i += self._store.n_frames if not 0 <= i < self._store.n_frames: raise IndexError(f"frame index {key} out of range (0..{self._store.n_frames - 1})") return Frame(self._store, i) # slice or fancy index -> a real sub-trajectory sharing the topology return LatticeTrajectory(self._store.subset(key)) def __iter__(self): for i in range(self._store.n_frames): yield Frame(self._store, i) # -- raw arrays -------------------------------------------------------- @property def positions(self): """Raw integer positions, ``(n_frames, n_atoms, 3)``.""" return self._store.positions
[docs] def whole_positions(self): """Positions with every chain made whole across PBC, ``(n_frames, n_atoms, 3)``.""" return self._store.whole_positions()
# -- batched analyses (whole trajectory at once) -----------------------
[docs] def radius_of_gyration(self): """``(n_frames, n_chains)`` per-chain Rg for every frame.""" return self._store.radius_of_gyration()
[docs] def center_of_mass(self): """``(n_frames, n_chains, n_dim)`` per-chain COM for every frame.""" return self._store.centers_of_mass()
[docs] def asphericity(self): """``(n_frames, n_chains)`` per-chain asphericity for every frame.""" return self._store.asphericity()
[docs] def end_to_end_distance(self): """``(n_frames, n_chains)`` per-chain end-to-end distance for every frame.""" return self._store.end_to_end()
def __repr__(self): return (f"<LatticeTrajectory {self._store.n_frames} frames, " f"{self._store.n_chains} chains, {self._store.n_atoms} beads, " f"box {self._store.dimensions}>")