Fast, standalone reader/writer for GROMACS XTC trajectory files
Project description
xtclib
A fast, standalone Python library for reading and writing GROMACS XTC trajectory files. The coordinate compression and decompression are implemented in C and wrapped with Cython, giving performance close to the native GROMACS routines while requiring only NumPy at runtime.
Features
- Read XTC files frame-by-frame (iterator) or all-at-once into NumPy arrays.
- Write XTC files with full compression, producing output that is bit-identical to GROMACS.
- Zero runtime dependencies beyond NumPy — no GROMACS installation, no MDTraj, no MDAnalysis required.
- Handles both small systems (intrinsically disordered proteins) and large solvated systems (50 k+ atoms) correctly.
- Pure-C compression core with Cython bindings — no external shared libraries to manage.
Installation
pip install -e .
# or with uv:
uv pip install -e .
Build requirements (setuptools, Cython, numpy) are declared in
pyproject.toml and installed automatically during the build.
Quick start
Reading a trajectory
from xtclib import read_xtc
data = read_xtc("trajectory.xtc")
data["coords"] # ndarray, shape (nframes, natoms, 3), float32, in nm
data["time"] # ndarray, shape (nframes,), float32
data["step"] # ndarray, shape (nframes,), int32
data["box"] # ndarray, shape (nframes, 3, 3), float32
data["natoms"] # int
Writing a trajectory
from xtclib import write_xtc
write_xtc(
"output.xtc",
coords, # (nframes, natoms, 3) array in nm
time=times, # optional, defaults to [0, 1, 2, ...]
step=steps, # optional, defaults to [0, 1, 2, ...]
box=boxes, # optional, defaults to zeros
precision=1000.0, # optional, default 1000.0
)
Frame-by-frame iteration
For large trajectories where loading everything into memory at once
is impractical, use the XTCReader iterator:
from xtclib import XTCReader
with XTCReader("large_trajectory.xtc") as reader:
for frame in reader:
print(frame.step, frame.time, frame.coords.shape)
# frame.coords is (natoms, 3) float32
# frame.box is (3, 3) float32
Round-tripping a file
from xtclib import read_xtc, write_xtc
data = read_xtc("input.xtc")
write_xtc("copy.xtc", data["coords"],
time=data["time"], step=data["step"], box=data["box"])
The output file will be byte-identical to the input.
API reference
read_xtc(filename)
Read an entire XTC file and return a dict of NumPy arrays.
| Key | Type | Description |
|---|---|---|
"coords" |
ndarray (nframes, natoms, 3) float32 |
Atom coordinates in nm |
"time" |
ndarray (nframes,) float32 |
Simulation time (usually ps) |
"step" |
ndarray (nframes,) int32 |
Integration step number |
"box" |
ndarray (nframes, 3, 3) float32 |
Unit-cell box vectors in nm |
"natoms" |
int |
Number of atoms per frame |
write_xtc(filename, coords, time=None, step=None, box=None, precision=1000.0)
Write coordinates to an XTC file with compression.
| Parameter | Type | Default | Description |
|---|---|---|---|
filename |
str |
— | Output file path |
coords |
array-like (nframes, natoms, 3) |
— | Coordinates in nm |
time |
array-like (nframes,) |
[0, 1, 2, ...] |
Frame times |
step |
array-like (nframes,) |
[0, 1, 2, ...] |
Step numbers |
box |
array-like (nframes, 3, 3) or (3, 3) |
zeros | Box vectors |
precision |
float |
1000.0 |
Precision factor |
XTCReader(filename)
Iterator-based reader. Yields XTCFrame objects with attributes
step, time, box, coords, and natoms. Can be used as a
context manager. Also provides a read_all() method that returns the
same dict as read_xtc().
How XTC compression works
The XTC format uses a lossy compression scheme for 3-D coordinates:
-
Float → integer: each coordinate is multiplied by a precision factor (default 1000) and rounded to the nearest integer. This gives ~0.001 nm (1 pm) resolution.
-
Full-range encoding: each atom's integer coordinates are encoded relative to the bounding box (
minint/maxint) using a mixed-radix bit-packing scheme. -
Run-length delta encoding: consecutive atoms whose inter-atom distances are "small" are encoded as differences from the previous atom, using a smaller bit range. The small range adapts up or down across the trajectory to track typical bond lengths.
-
Water optimisation: within small-delta runs, the first two atoms are swapped (O-H → H-O order) to make the deltas even smaller for water molecules. This is reversed transparently on reading.
The result is typically 10–20× smaller than raw float arrays for solvated biomolecular systems.
Precision and lossy encoding
XTC is a lossy format. The maximum per-coordinate rounding error is
0.5 / precision nm:
| Precision | Max error (nm) | Max error (Å) |
|---|---|---|
| 1000 (default) | 0.0005 | 0.005 |
| 10000 | 0.00005 | 0.0005 |
| 100 | 0.005 | 0.05 |
When reading a file that was written with a given precision, read_xtc
returns the exact integer-reconstructed values — there is no
additional loss on read. A read → write → read round-trip with the
same precision produces bit-identical coordinate arrays.
Compatibility
Files written by xtclib are fully compatible with:
- GROMACS (
gmx trjconv,gmx trajcat, etc.) - MDTraj (
mdtraj.load_xtc) - MDAnalysis (
MDAnalysis.coordinates.XTC) - Any tool that reads standard XTC (magic number 1995)
This has been validated by round-trip testing: files written by xtclib
produce byte-identical coordinate arrays when read back by MDTraj.
Project structure
xtclib/
├── xtclib/
│ ├── __init__.py # Package entry point
│ ├── reader.py # XTCReader, read_xtc()
│ ├── writer.py # write_xtc()
│ ├── _xtc_core.pyx # Cython wrapper
│ ├── xdr_xtc.c # C compression/decompression
│ └── xdr_xtc.h # C header
├── tests/
│ └── test_xtclib.py # 21 tests (pytest)
├── example/
│ ├── synuclein_STARLING.xtc # 140-atom IDP, 400 frames
│ ├── synuclein_STARLING.pdb # Reference structure
│ └── lysozyme_md.xtc # 50,949-atom solvated system, 101 frames
├── setup.py
└── pyproject.toml
Running tests
python -m pytest tests/ -v
The test suite validates:
- Reading both example files (shapes, metadata)
- Exact round-trip (read → write → read) for coords, time, step, box
- Byte-identical file sizes after round-trip
- PDB cross-validation (atom count, first-frame coordinates)
- MDTraj compatibility (our written files read back identically)
- Compression of synthetic/random coordinate data
License
The C compression algorithm is based on the XTC specification as implemented in GROMACS (LGPL-2.1+).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xtclib-0.1.0.tar.gz.
File metadata
- Download URL: xtclib-0.1.0.tar.gz
- Upload date:
- Size: 184.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b4133d8bc0488dcd4f90c26c0daec7989ab3ef0114e73cd4ac5cd8a9a557007
|
|
| MD5 |
55a4a869a911ff6052450115b62683bc
|
|
| BLAKE2b-256 |
df7cd74d33ef4c95ac6399e7e7e9a8f8754f02e4a2be4074e166a1036e0e20f7
|
File details
Details for the file xtclib-0.1.0-cp312-cp312-macosx_26_0_arm64.whl.
File metadata
- Download URL: xtclib-0.1.0-cp312-cp312-macosx_26_0_arm64.whl
- Upload date:
- Size: 267.5 kB
- Tags: CPython 3.12, macOS 26.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99a8a8f08bd8a1509fe0d160ed85646528cd9c1ff75298f55c411f85922b2614
|
|
| MD5 |
6d92da3c6f2d34231f481b380e84da69
|
|
| BLAKE2b-256 |
c0b1672243eb15778e20f0873ab7f3b0e3e2ea1daec274d1dc8c9c809a05ed34
|