The Trajectory class provides efficient reading and streaming of molecular dynamics trajectory files in multiple formats.
Opening Trajectories
open_xtc
Trajectory.open_xtc(path: str , system: System) -> Trajectory
Open a GROMACS XTC (compressed trajectory) file.
System object with matching atom count
from warp_md import System, Trajectory
system = System.from_pdb( "protein.pdb" )
traj = Trajectory.open_xtc( "trajectory.xtc" , system)
open_dcd
Trajectory.open_dcd(
path: str ,
system: System,
length_scale: float | None = None
) -> Trajectory
Open a CHARMM/NAMD DCD trajectory file.
System object with matching atom count
Optional scaling factor for coordinates. Use 1.0 for Angstroms (CHARMM/NAMD), 10.0 for nanometers.
from warp_md import System, Trajectory
system = System.from_pdb( "protein.pdb" )
# CHARMM/NAMD format (Angstroms)
traj = Trajectory.open_dcd( "trajectory.dcd" , system)
# If DCD is in nanometers
traj = Trajectory.open_dcd( "trajectory.dcd" , system, length_scale = 10.0 )
open_pdb
Trajectory.open_pdb(path: str , system: System) -> Trajectory
Open a multi-model PDB file as a trajectory.
Path to the PDB file with multiple MODEL records
System object with matching atom count
from warp_md import System, Trajectory
system = System.from_pdb( "first_frame.pdb" )
traj = Trajectory.open_pdb( "trajectory.pdb" , system)
open_pdbqt
Trajectory.open_pdbqt(path: str , system: System) -> Trajectory
Open a PDBQT file as a trajectory (typically for docking poses).
System object with matching atom count
from warp_md import System, Trajectory
system = System.from_pdbqt( "ligand.pdbqt" )
traj = Trajectory.open_pdbqt( "docking_poses.pdbqt" , system)
Reading Frames
read_chunk
traj.read_chunk(
max_frames: int | None = None ,
include_box: bool = True ,
include_box_matrix: bool = True ,
include_time: bool = True ,
atom_indices: list[ int ] | None = None
) -> dict | None
Read a chunk of frames from the trajectory.
Maximum number of frames to read. If None, uses an automatic chunk size optimized for the trajectory format.
Include periodic box dimensions (lx, ly, lz) if available
Include full 3x3 box matrix for triclinic cells
Include simulation time in picoseconds
Optional list of atom indices to read (subset selection). If None, reads all atoms.
Dictionary containing:
coords: np.ndarray of shape (frames, atoms, 3) - coordinates in Angstroms
box: np.ndarray of shape (frames, 3) - box dimensions [lx, ly, lz] or None
box_matrix: np.ndarray of shape (frames, 3, 3) - full box matrix or None
time_ps: np.ndarray of shape (frames,) - time in picoseconds or None
frames: int - number of frames read
Returns None when end of trajectory is reached.
Basic Usage
Optimized Reading
Subset Selection
# Read all frames in chunks
while (chunk := traj.read_chunk()) is not None :
coords = chunk[ 'coords' ] # (frames, atoms, 3)
print ( f "Read { chunk[ 'frames' ] } frames" )
print ( f "Coords shape: { coords.shape } " )
Automatic chunk sizing optimizes memory usage and I/O performance based on the trajectory format and number of atoms.
read_chunk_into
traj.read_chunk_into(
coords: np.ndarray,
box_out: np.ndarray | None = None ,
time_out: np.ndarray | None = None ,
max_frames: int | None = None ,
atom_indices: list[ int ] | None = None
) -> int
Read frames directly into pre-allocated NumPy arrays (zero-copy for XTC/DCD).
Pre-allocated float32 array of shape (max_frames, n_atoms, 3) to store coordinates
Optional pre-allocated float32 array of shape (max_frames, 3) for box dimensions
Optional pre-allocated float32 array of shape (max_frames,) for time values
max_frames
int
default: "coords.shape[0]"
Maximum number of frames to read (defaults to size of coords array)
Optional list of atom indices to read
Number of frames actually read (0 when end of trajectory reached)
Zero-Copy Reading
Memory-Efficient Processing
import numpy as np
# Pre-allocate buffers
n_atoms = system.n_atoms()
max_chunk = 1000
coords = np.empty((max_chunk, n_atoms, 3 ), dtype = np.float32)
box = np.empty((max_chunk, 3 ), dtype = np.float32)
# Read without intermediate allocations
while (n_read := traj.read_chunk_into(coords, box_out = box)) > 0 :
# Process only the frames actually read
process_frames(coords[:n_read], box[:n_read])
Arrays must be C-contiguous float32. The atom dimension must match the trajectory or the requested atom_indices.
Trajectory Control
reset
Reset the trajectory reader to the beginning.
# First pass
while (chunk := traj.read_chunk()) is not None :
first_pass_analysis(chunk)
# Reset and second pass
traj.reset()
while (chunk := traj.read_chunk()) is not None :
second_pass_analysis(chunk)
n_atoms
Get the number of atoms in the trajectory.
Number of atoms per frame
count = traj.n_atoms()
assert count == system.n_atoms(), "Atom count mismatch!"
Complete Example
Full Trajectory Processing
from warp_md import System, Trajectory
import numpy as np
# Setup
system = System.from_pdb( "protein.pdb" )
traj = Trajectory.open_xtc( "trajectory.xtc" , system)
backbone = system.select( "backbone" )
# Method 1: Simple chunked reading
all_coords = []
while (chunk := traj.read_chunk( atom_indices = backbone.indices)) is not None :
all_coords.append(chunk[ 'coords' ])
print ( f "Read { chunk[ 'frames' ] } frames, time: { chunk[ 'time_ps' ] } " )
coords = np.concatenate(all_coords, axis = 0 )
print ( f "Total frames: { coords.shape[ 0 ] } " )
# Reset for second analysis
traj.reset()
# Method 2: Zero-copy for memory efficiency
n_backbone = len (backbone.indices)
coords_buffer = np.empty(( 1000 , n_backbone, 3 ), dtype = np.float32)
frame_count = 0
while (n := traj.read_chunk_into(
coords_buffer,
atom_indices = backbone.indices
)) > 0 :
frame_count += n
# Process in-place
rmsd = compute_rmsd(coords_buffer[:n])
print ( f "Processed { frame_count } frames with zero-copy" )
Helper Functions
open_trajectory_auto
from warp_md.io import open_trajectory_auto
traj = open_trajectory_auto(
path: str ,
system: System,
format : str | None = None ,
length_scale: float | None = None
) -> Trajectory
Automatically detect trajectory format from file extension and open it.
Path to trajectory file (.xtc, .dcd, .pdb, .pdbqt)
Force specific format (“xtc”, “dcd”, “pdb”, “pdbqt”). If None, detects from extension.
Length scale for DCD files (ignored for other formats)
from warp_md import System
from warp_md.io import open_trajectory_auto
system = System.from_pdb( "protein.pdb" )
# Auto-detect format
traj = open_trajectory_auto( "trajectory.xtc" , system)
# Force format for non-standard extension
traj = open_trajectory_auto( "traj.dat" , system, format = "dcd" )