Metadata-Version: 2.2
Name: Ripple-hpc
Version: 1.2.6
Summary: High-performance molecular dynamics trajectory analysis (RDF, SSF, VHF, MSD/cMSD, diffusion tensors).
Author: Frost research group
License: MIT License
         
         Copyright (c) 2025 Frost research group
         
         Permission is hereby granted, free of charge, to any person obtaining a copy
         of this software and associated documentation files (the "Software"), to deal
         in the Software without restriction, including without limitation the rights
         to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         copies of the Software, and to permit persons to whom the Software is
         furnished to do so, subject to the following conditions:
         
         The above copyright notice and this permission notice shall be included in all
         copies or substantial portions of the Software.
         
         THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         SOFTWARE.
         
Project-URL: Homepage, https://github.com/Frost-group/Ripple-hpc
Project-URL: Source, https://github.com/Frost-group/Ripple-hpc
Project-URL: Issues, https://github.com/Frost-group/Ripple-hpc/issues
Requires-Python: >=3.10
Requires-Dist: numpy>=1.26.4
Requires-Dist: tqdm>=4.66
Description-Content-Type: text/markdown

# Ripple

[![PyPI version](https://img.shields.io/pypi/v/ripple-hpc.svg)](https://pypi.org/project/ripple-hpc/)
[![Python versions](https://img.shields.io/pypi/pyversions/ripple-hpc.svg)](https://pypi.org/project/ripple-hpc/)
[![License](https://img.shields.io/badge/license-MIT-yellow.svg)](LICENSE)

Ripple is a high-performance Python package for molecular dynamics trajectory analysis.
It uses an ASE-friendly input model, memmap-backed preparation, and threaded C++ kernels
to accelerate large trajectory workflows on workstations and HPC systems.

## Features

- Radial distribution function (RDF)
- Static structure factor (SSF)
- Van Hove function, self and distinct parts (VHF)
- Intermediate scattering function, self and distinct parts (ISF)
- Mean-square displacement (MSD) and collective MSD (cMSD)
- Diffusion tensor estimation with OLS or block-covariance MCMC

## Installation

Install the published package from PyPI:

```bash
pip install ripple-hpc
```

The examples below use ASE to read trajectories:

```bash
pip install ase
```

Install the latest development version from GitHub:

```bash
pip install git+https://github.com/Frost-group/Ripple-hpc.git
```

## Workflow model

Ripple follows a two-step workflow:

1. `prepare_*` reads a trajectory and writes reusable memmap caches.
2. `*_cal()` runs the threaded analysis kernel and returns result objects in memory.

For repeated analyses on the same trajectory, pass `reuse_memmap=True` and keep a stable
`trajectory_tag`.

## Quick start

This example follows the same pattern as `tests/smoke_test.py`.

```python
from pathlib import Path

from ase.io import iread

from ripple.prepare_diffusion import prepare_diffusion
from ripple.prepare_isf import prepare_isf
from ripple.prepare_rdf import prepare_rdf
from ripple.prepare_ssf import prepare_ssf
from ripple.prepare_vhf import prepare_vhf_distinct, prepare_vhf_self

traj_path = Path("tests/MaceMD_444_0v_700K.xyz")
traj_factory = lambda: iread(str(traj_path), format="extxyz", index=":")

species = "Li"
n_frames = 1000
dt_ps = 0.1
n_workers = 8
save_dir = "ripple_outputs"
traj_tag = "smoke_test"
```

### RDF

```python
rdf_prepared = prepare_rdf(
    traj_factory,
    target_atoms1=species,
    target_atoms2=species,
    n_frames=n_frames,
    save_dir=save_dir,
    pos_dtype="float64",
    reuse_memmap=True,
    trajectory_tag=traj_tag,
)

rdf_res = rdf_prepared.rdf_cal(
    mode="abc",
    r_max=11.0,
    dr=0.05,
    n_workers=n_workers,
)

print(rdf_res.bins.shape)
print(rdf_res.rdf.shape)
```

### VHF

```python
vhf_self_prepared = prepare_vhf_self(
    traj_factory,
    target_atoms=species,
    n_frames=n_frames,
    save_dir=save_dir,
    pos_dtype="float64",
    reuse_memmap=True,
    trajectory_tag=traj_tag,
)

vhf_self_res = vhf_self_prepared.vhf_self_cal(
    mode="abc",
    r_max=36.0,
    dr=0.05,
    n_workers=n_workers,
    timestep_ps=dt_ps,
    lag_max=998,
    lag_stride=2,
)

vhf_distinct_prepared = prepare_vhf_distinct(
    traj_factory,
    target_atoms1=species,
    target_atoms2=species,
    n_frames=n_frames,
    save_dir=save_dir,
    pos_dtype="float64",
    reuse_memmap=True,
    trajectory_tag=traj_tag,
)

vhf_distinct_res = vhf_distinct_prepared.vhf_distinct_cal(
    mode="abc",
    r_max=6.0,
    dr=0.1,
    n_workers=n_workers,
    timestep_ps=dt_ps,
    lag_max=500,
    lag_stride=10,
    normalize=True,
)

print(vhf_self_res.Gs.shape)
print(vhf_distinct_res.Gd.shape)
```

### SSF and ISF

```python
ssf_prepared = prepare_ssf(
    traj_factory,
    target_atoms1=species,
    target_atoms2=species,
    n_frames=n_frames,
    save_dir=save_dir,
    pos_dtype="float64",
    reuse_memmap=True,
    trajectory_tag=traj_tag,
)

ssf_res = ssf_prepared.ssf_cal(
    k_max=5.0,
    dk_shell=0.5,
    n_workers=n_workers,
    max_points=20000,
)

isf_prepared = prepare_isf(
    traj_factory,
    target_atoms1=species,
    target_atoms2=species,
    n_frames=n_frames,
    save_dir=save_dir,
    pos_dtype="float64",
    reuse_memmap=True,
    trajectory_tag=traj_tag,
)

isf_self_res = isf_prepared.isf_self_cal(
    mode="abc",
    q_max=5.0,
    dq_shell=0.5,
    n_workers=n_workers,
    timestep_ps=dt_ps,
    lag_max=500,
    lag_stride=5,
    max_points=20000,
)

isf_distinct_res = isf_prepared.isf_distinct_cal(
    mode="abc",
    q_max=5.0,
    dq_shell=0.5,
    n_workers=n_workers,
    timestep_ps=dt_ps,
    lag_max=500,
    lag_stride=5,
    max_points=20000,
)

print(ssf_res.ssf.shape, ssf_res.shell.shape)
print(isf_self_res.Fs.shape, isf_self_res.lags.shape, isf_self_res.q_shell.shape)
print(isf_distinct_res.Fd.shape, isf_distinct_res.lags.shape, isf_distinct_res.q_shell.shape)
```

### Diffusion tensors from MSD and cMSD

```python
diff_prepared = prepare_diffusion(
    traj_factory,
    target_atoms=species,
    timestep_ps=dt_ps,
    n_frames=n_frames,
    save_dir=save_dir,
    trajectory_tag=traj_tag,
    pos_dtype="float64",
    reuse_memmap=True,
)

msd_res = diff_prepared.msd_cal(n_workers=n_workers)
cmsd_res = diff_prepared.cmsd_cal(n_workers=n_workers)

fit_self_ols = msd_res.diffusion_tensor(
    method="ols",
    fit_lag_frac=(0.05, 0.95),
    fit_n_lags=200,
    psd=False,
)

fit_sigma_mcmc = cmsd_res.diffusion_tensor(
    method="mcmc",
    fit_lag_frac=(0.05, 0.95),
    fit_n_lags=100,
    n_blocks=50,
    min_block_len=10,
    n_samples=1500,
    n_walkers=32,
    n_burn=400,
    n_thin=10,
    seed=42,
    progress=False,
)

print(msd_res.msd_tensor.shape)
print(fit_self_ols.D_tensor)
print(fit_sigma_mcmc.D_tensor)
```

## Input expectations

- Trajectories can be passed as a sequence, a single-pass iterable with `n_frames`, or a
  factory such as `lambda: ase.io.iread(...)`.
- ASE is not a mandatory package dependency, but it is the recommended reader in the examples.
- For very large datasets, prefer a trajectory factory plus `reuse_memmap=True`.

## Result objects

Ripple returns typed result objects instead of writing HDF5 files by default. Typical fields are:

- RDF: `rdf_res.rdf`, `rdf_res.bins`
- VHF: `vhf_self_res.Gs`, `vhf_distinct_res.Gd`, `times_ps`, `bins`
- SSF: `ssf_res.ssf`, `ssf_res.shell`
- ISF: `isf_self_res.Fs`, `isf_distinct_res.Fd`, `q_shell`
- Diffusion: `msd_res.msd_tensor`, `cmsd_res.cmsd_tensor`, `fit.D_tensor`

If you want to remove cached memmaps after analysis, call `.clean()` on the prepared object.

## License

MIT. See [LICENSE](LICENSE).
