RmsdPlan
Compute RMSD relative to a reference structure.
Constructor
from warp_md import RmsdPlan
plan = RmsdPlan(
selection,
reference_mode="first",
fit=True,
mass_weighted=False,
pbc="none"
)
Atoms to calculate RMSD for
Reference frame selection: "first", "average", or custom frame index
Whether to superpose structures before RMSD calculation
Periodic boundary conditions: "none" or "orthorhombic"
run() Method
Returns: 1D array of RMSD values in Å (one per frame)
Example
import warp_md as wmd
system = wmd.System("system.pdb")
traj = wmd.open_trajectory("traj.xtc", system)
# Backbone RMSD relative to first frame
backbone = system.select("backbone")
plan = wmd.RmsdPlan(backbone, reference_mode="first", fit=True)
rmsd = plan.run(traj, system)
print(f"Max RMSD: {rmsd.max():.2f} Å")
SymmRmsdPlan
Compute RMSD accounting for molecular symmetry.
Constructor
plan = SymmRmsdPlan(
selection,
reference_mode="first",
fit=True,
pbc="none"
)
Automatically detects symmetric atoms and finds the optimal permutation.
Example
# RMSD of benzene ring accounting for 6-fold symmetry
ring = system.select("resname BNZ")
plan = wmd.SymmRmsdPlan(ring, fit=True)
rmsd = plan.run(traj, system)
DistanceRmsdPlan
Compute RMSD based on pairwise distances (coordinate-free).
Constructor
plan = DistanceRmsdPlan(
selection,
reference_mode="first",
pbc="none"
)
Periodic boundary conditions
Example
# Distance RMSD for domain comparison
domain = system.select("resid 100:200")
plan = wmd.DistanceRmsdPlan(domain, reference_mode="average")
drmsd = plan.run(traj, system)
Distance RMSD is rotation-invariant and sensitive to internal conformational changes.
PairwiseRmsdPlan
Compute all-vs-all pairwise RMSD matrix.
Constructor
plan = PairwiseRmsdPlan(
selection,
fit=True,
mass_weighted=False
)
run() Method
Returns: 2D array of shape (n_frames, n_frames) with pairwise RMSD values
Example
# Create pairwise RMSD matrix for clustering
ca_atoms = system.select("name CA")
plan = wmd.PairwiseRmsdPlan(ca_atoms, fit=True)
rmsd_matrix = plan.run(traj, system)
# Use for hierarchical clustering
from scipy.cluster.hierarchy import linkage, dendrogram
import matplotlib.pyplot as plt
linkage_matrix = linkage(rmsd_matrix, method='average')
dendrogram(linkage_matrix)
plt.ylabel("RMSD (Å)")
plt.show()
Pairwise RMSD has O(N²) complexity. For large trajectories, consider downsampling frames.
RmsdPerResPlan
Calculate per-residue RMSD to quantify flexibility of individual residues.
Constructor:
from warp_md import RmsdPerResPlan
plan = RmsdPerResPlan(
selection, # Selection: residues to analyze
reference_frame=0, # int: reference frame index
mass_weighted=False, # bool: use mass-weighted RMSD
device="auto" # str: execution device
)
Residue selection to calculate per-residue RMSD
Frame index to use as reference structure
Whether to use mass-weighted RMSD
Returns: ndarray[frames, residues] — Per-residue RMSD in Ångströms
Example:
from warp_md import System, Trajectory, RmsdPerResPlan
system = System.from_pdb("protein.pdb")
traj = Trajectory.open_xtc("traj.xtc", system)
protein = system.select("protein")
plan = RmsdPerResPlan(protein, reference_frame=0)
per_res_rmsd = plan.run(traj, system)
# Identify most flexible residues
mean_rmsd = per_res_rmsd.mean(axis=0)
print(f"Most flexible residue: {mean_rmsd.argmax()}, RMSD: {mean_rmsd.max():.2f} Å")
TrajectoryClusterPlan
Cluster trajectory frames using DBSCAN or k-means based on RMSD.
Constructor:
from warp_md import TrajectoryClusterPlan
plan = TrajectoryClusterPlan(
selection, # Selection: atoms for alignment
method="dbscan", # str: "dbscan" or "kmeans"
eps=2.0, # float: DBSCAN epsilon (Å)
min_samples=5, # int: DBSCAN min_samples
n_clusters=None, # int: k-means cluster count
metric="rmsd", # str: distance metric
mass_weighted=False, # bool: mass-weighted RMSD
device="auto" # str: execution device
)
Atoms used for RMSD calculation and alignment
Clustering method: "dbscan" or "kmeans"
DBSCAN epsilon parameter (maximum distance in Ångströms)
DBSCAN minimum samples per cluster
Number of clusters for k-means (required if method=“kmeans”)
Distance metric (currently only “rmsd” supported)
Whether to use mass-weighted RMSD
Returns: ndarray[frames] — Cluster labels for each frame (-1 for noise in DBSCAN)
Example:
from warp_md import System, Trajectory, TrajectoryClusterPlan
system = System.from_pdb("protein.pdb")
traj = Trajectory.open_xtc("traj.xtc", system)
backbone = system.select("protein and backbone")
# DBSCAN clustering
plan = TrajectoryClusterPlan(backbone, method="dbscan", eps=1.5, min_samples=10)
labels = plan.run(traj, system)
print(f"Found {len(set(labels)) - (1 if -1 in labels else 0)} clusters")
print(f"Noise points: {(labels == -1).sum()}")
# k-means clustering
plan_kmeans = TrajectoryClusterPlan(backbone, method="kmeans", n_clusters=5)
kmeans_labels = plan_kmeans.run(traj, system)