Skip to main content

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:

  1. 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.

  2. Full-range encoding: each atom's integer coordinates are encoded relative to the bounding box (minint/maxint) using a mixed-radix bit-packing scheme.

  3. 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.

  4. 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xtclib-0.1.0.tar.gz (184.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

xtclib-0.1.0-cp312-cp312-macosx_26_0_arm64.whl (267.5 kB view details)

Uploaded CPython 3.12macOS 26.0+ ARM64

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

Hashes for xtclib-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4b4133d8bc0488dcd4f90c26c0daec7989ab3ef0114e73cd4ac5cd8a9a557007
MD5 55a4a869a911ff6052450115b62683bc
BLAKE2b-256 df7cd74d33ef4c95ac6399e7e7e9a8f8754f02e4a2be4074e166a1036e0e20f7

See more details on using hashes here.

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

Hashes for xtclib-0.1.0-cp312-cp312-macosx_26_0_arm64.whl
Algorithm Hash digest
SHA256 99a8a8f08bd8a1509fe0d160ed85646528cd9c1ff75298f55c411f85922b2614
MD5 6d92da3c6f2d34231f481b380e84da69
BLAKE2b-256 c0b1672243eb15778e20f0873ab7f3b0e3e2ea1daec274d1dc8c9c809a05ed34

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page