Skip to main content
The I/O module provides utilities for opening trajectories with automatic format detection. It supports DCD, XTC, PDB, and PDBQT formats.

Quick Start

import warp_md as wp
from warp_md.io import open_trajectory

# Load system
sys = wp.System("topology.pdb")

# Open trajectory (format auto-detected from extension)
traj = open_trajectory("trajectory.dcd", sys)

# Read frames
for frame in traj:
    print(f"Frame {frame.step}, time {frame.time}")

Functions

open_trajectory_auto

Open trajectory with automatic format detection.
def open_trajectory_auto(
    path: str,
    system: System,
    *,
    format: Optional[str] = None,
    length_scale: Optional[float] = None,
    trajectory_cls: Optional[Any] = None
) -> Trajectory:
    """Open trajectory with format auto-detection.
    
    Args:
        path: Path to trajectory file
        system: System topology
        format: Override format detection ("dcd", "xtc", "pdb", "pdbqt")
        length_scale: Length unit conversion (for DCD)
        trajectory_cls: Custom Trajectory class (default: warp_md.Trajectory)
        
    Returns:
        Trajectory reader instance
        
    Raises:
        ValueError: If format cannot be determined or is unsupported
    """
path
str
required
Path to trajectory file
system
System
required
warp-md System object with topology information
format
str
Force specific format instead of auto-detection:
  • "dcd" - CHARMM/NAMD binary trajectory
  • "xtc" - GROMACS compressed trajectory
  • "pdb" - Multi-model PDB file
  • "pdbqt" - AutoDock multi-model file
  • "auto" or None - Detect from file extension
length_scale
float
Length unit scaling factor for DCD files. Default is None (Angstroms). Use 0.1 to convert Angstroms to nanometers.
trajectory_cls
Any
Custom Trajectory class to use instead of default warp_md.Trajectory
Basic Example:
import warp_md as wp
from warp_md.io import open_trajectory_auto

# Load topology
sys = wp.System("topology.pdb")

# Auto-detect format from extension
traj = open_trajectory_auto("trajectory.dcd", sys)

for i, frame in enumerate(traj):
    print(f"Frame {i}: {frame.coords.shape}")
    if i >= 10:  # Read first 10 frames
        break
Format Override:
# Force XTC format even if extension is wrong
traj = open_trajectory_auto(
    "trajectory.trr",  # Wrong extension
    sys,
    format="xtc"  # Override to XTC
)
Length Scale Conversion:
# Convert DCD from Angstrom to nanometers
traj = open_trajectory_auto(
    "trajectory.dcd",
    sys,
    length_scale=0.1  # Angstrom -> nm
)

frame = next(iter(traj))
print(f"Coordinates in nm: {frame.coords[:5]}")

open_trajectory

Alias for open_trajectory_auto with identical signature.
def open_trajectory(
    path: str,
    system: System,
    *,
    format: Optional[str] = None,
    length_scale: Optional[float] = None,
    trajectory_cls: Optional[Any] = None
) -> Trajectory:
    """Alias for open_trajectory_auto()."""
This is provided as a convenience alias. Both functions are identical:
from warp_md.io import open_trajectory, open_trajectory_auto

# These are exactly the same
traj1 = open_trajectory("traj.dcd", sys)
traj2 = open_trajectory_auto("traj.dcd", sys)

Supported Formats

DCD (CHARMM/NAMD)

Binary trajectory format used by CHARMM, NAMD, and other MD packages.
from warp_md.io import open_trajectory

sys = wp.System("topology.psf")
traj = open_trajectory("trajectory.dcd", sys)

# DCD files store coordinates in Angstroms by default
for frame in traj:
    print(frame.coords.shape)  # (n_atoms, 3) in Angstroms
Unit Conversion:
# Convert to nanometers
traj = open_trajectory("trajectory.dcd", sys, length_scale=0.1)
Direct Method:
# Using Trajectory class directly
sys = wp.System("topology.psf")
traj = wp.Trajectory.open_dcd("trajectory.dcd", sys, length_scale=0.1)

XTC (GROMACS)

GROMACS compressed trajectory format.
sys = wp.System("topology.gro")
traj = open_trajectory("trajectory.xtc", sys)

# XTC stores in nm, warp-md converts automatically
for frame in traj:
    print(f"Time: {frame.time} ps")
    print(f"Coords: {frame.coords.shape}")
Direct Method:
traj = wp.Trajectory.open_xtc("trajectory.xtc", sys)

PDB (Multi-model)

Multiple MODEL records in a single PDB file.
sys = wp.System("structure.pdb")
traj = open_trajectory("trajectory.pdb", sys)

# Each MODEL is a frame
for i, frame in enumerate(traj):
    print(f"Model {i}: {len(frame.coords)} atoms")
Direct Method:
traj = wp.Trajectory.open_pdb("trajectory.pdb", sys)

PDBQT (AutoDock)

AutoDock PDBQT format with multiple models.
sys = wp.System("receptor.pdb")
traj = open_trajectory("docking_poses.pdbqt", sys, format="pdbqt")

# Each model is a docking pose
for i, pose in enumerate(traj):
    print(f"Pose {i}: {pose.coords.shape}")

Format Detection

Format is automatically detected from file extension:
ExtensionFormatDescription
.dcdDCDCHARMM/NAMD binary
.xtcXTCGROMACS compressed
.pdbPDBMulti-model PDB
.pdbqtPDBQTAutoDock format
If extension is missing or ambiguous, use the format parameter:
# No extension or wrong extension
traj = open_trajectory("trajectory", sys, format="dcd")

Common Patterns

Reading Specific Frames

from warp_md.io import open_trajectory

sys = wp.System("topology.pdb")
traj = open_trajectory("trajectory.dcd", sys)

# Read frames 10-20
for i, frame in enumerate(traj):
    if i < 10:
        continue
    if i >= 20:
        break
    print(f"Frame {i}: time={frame.time}")

Trajectory Analysis

import numpy as np

sys = wp.System("topology.pdb")
traj = open_trajectory("trajectory.xtc", sys)

# Calculate RMSD over trajectory
ca_indices = sys.select("name CA").indices
ref_coords = traj[0].coords[ca_indices]

rmsds = []
for frame in traj:
    ca_coords = frame.coords[ca_indices]
    rmsd = np.sqrt(np.mean((ca_coords - ref_coords)**2))
    rmsds.append(rmsd)

print(f"Average RMSD: {np.mean(rmsds):.2f} Angstrom")

Converting Trajectory Formats

from warp_md.io import open_trajectory

sys = wp.System("topology.pdb")

# Read DCD
input_traj = open_trajectory("input.dcd", sys)

# Write to XTC
output_traj = wp.Trajectory.open_xtc_write("output.xtc", sys)

for frame in input_traj:
    output_traj.write_frame(frame.coords)

output_traj.close()

Filtering Trajectories

sys = wp.System("topology.pdb")
traj = open_trajectory("trajectory.dcd", sys)

# Save every 10th frame
output = wp.Trajectory.open_dcd_write("filtered.dcd", sys)

for i, frame in enumerate(traj):
    if i % 10 == 0:
        output.write_frame(frame.coords)

output.close()

Multiple Trajectories

from warp_md.io import open_trajectory

sys = wp.System("topology.pdb")

# Concatenate multiple trajectories
traj_files = ["run1.dcd", "run2.dcd", "run3.dcd"]

all_coords = []
for traj_file in traj_files:
    traj = open_trajectory(traj_file, sys)
    for frame in traj:
        all_coords.append(frame.coords)

print(f"Total frames: {len(all_coords)}")

Error Handling

from warp_md.io import open_trajectory

sys = wp.System("topology.pdb")

try:
    traj = open_trajectory("trajectory.xyz", sys)
except ValueError as e:
    print(f"Unsupported format: {e}")
    # Try with explicit format
    traj = open_trajectory("trajectory.xyz", sys, format="dcd")

try:
    traj = open_trajectory("missing.dcd", sys)
except FileNotFoundError:
    print("Trajectory file not found")

try:
    # Wrong number of atoms
    wrong_sys = wp.System("wrong_topology.pdb")
    traj = open_trajectory("trajectory.dcd", wrong_sys)
    frame = next(iter(traj))
except RuntimeError as e:
    print(f"Atom count mismatch: {e}")

Integration with warp-md

import warp_md as wp
from warp_md.io import open_trajectory

# Load system and trajectory
sys = wp.System("topology.pdb")
traj = open_trajectory("trajectory.dcd", sys)

# Set coordinates from specific frame
frame = traj[10]
sys.set_coords(frame.coords)

# Continue simulation from frame
integrator = sys.integrator(
    wp.INTEGRATOR_LANGEVIN,
    timestep=0.002,
    temperature=300.0
)

sys.simulate(integrator, steps=1000)

Custom Trajectory Class

import warp_md as wp
from warp_md.io import open_trajectory

class CustomTrajectory(wp.Trajectory):
    def __iter__(self):
        """Custom iteration with progress."""
        for i, frame in enumerate(super().__iter__()):
            if i % 100 == 0:
                print(f"Reading frame {i}")
            yield frame

sys = wp.System("topology.pdb")
traj = open_trajectory(
    "trajectory.dcd",
    sys,
    trajectory_cls=CustomTrajectory
)

for frame in traj:
    pass  # Prints progress every 100 frames

Performance Tips

from warp_md.io import open_trajectory

sys = wp.System("topology.pdb")
traj = open_trajectory("large_trajectory.dcd", sys)

# Process in chunks to manage memory
chunk_size = 100
chunk = []

for i, frame in enumerate(traj):
    chunk.append(frame.coords.copy())
    
    if len(chunk) >= chunk_size:
        # Process chunk
        process_chunk(chunk)
        chunk.clear()

# Process remaining frames
if chunk:
    process_chunk(chunk)

See Also

Build docs developers (and LLMs) love