Source code for ufp.analysis.inputs
"""Input-data analysis helpers for ASE-backed UFP workflows."""
from __future__ import annotations
from typing import Sequence
import ase
import ase.neighborlist
import numpy as np
[docs]
def pair_distance_histogram(
frames: Sequence[ase.Atoms],
*,
cutoff: float = 6.0,
max_frames: int = 1000,
seed: int = 7,
bins: int = 300,
) -> tuple[np.ndarray, np.ndarray]:
"""Collect a pair-distance histogram from ASE structures."""
rng = np.random.default_rng(seed)
sample_size = min(max_frames, len(frames))
frame_indices = rng.choice(len(frames), size=sample_size, replace=False)
distances: list[np.ndarray] = []
for frame_index in frame_indices:
atoms = frames[int(frame_index)]
i, j, d = ase.neighborlist.neighbor_list("ijd", atoms, cutoff=cutoff)
mask = i < j
if np.any(mask):
distances.append(np.asarray(d[mask], dtype=float))
if not distances:
raise ValueError("no pair distances were collected")
all_distances = np.concatenate(distances)
histogram, bin_edges = np.histogram(
all_distances,
bins=np.linspace(0.0, cutoff, bins),
density=True,
)
return histogram, bin_edges
__all__ = ["pair_distance_histogram"]