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
"""
warp-md System object with topology information
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 unit scaling factor for DCD files. Default is None (Angstroms).
Use 0.1 to convert Angstroms to nanometers.
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)
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 is automatically detected from file extension:
| Extension | Format | Description |
|---|
.dcd | DCD | CHARMM/NAMD binary |
.xtc | XTC | GROMACS compressed |
.pdb | PDB | Multi-model PDB |
.pdbqt | PDBQT | AutoDock 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")
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
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