# How to compute RMSD and RMSF ## Goal Measure structural deviation across frames (RMSD) or per-atom positional fluctuation over a trajectory (RMSF). ## Minimal example ```python from moleculekit.molecule import Molecule from moleculekit.util import molRMSD mol = Molecule("3PTB") ref = mol.copy() # Select Cα indices for both molecule and reference ca_idx = mol.atomselect("protein and name CA", indexes=True) # RMSD of all frames against the reference (returns one value per frame) rmsd = molRMSD(mol, ref, ca_idx, ca_idx) print(rmsd) ``` ## Parameters that matter | Parameter | Type | What it does | |---|---|---| | `mol` | {py:class}`~moleculekit.molecule.Molecule` | Trajectory to analyse | | `refmol` | {py:class}`~moleculekit.molecule.Molecule` | Reference structure | | `rmsdsel1` | integer `np.ndarray` | Atom indices in `mol` | | `rmsdsel2` | integer `np.ndarray` | Matching atom indices in `refmol` | ## Common variations ```python import numpy as np # RMSF per Cα atom over a trajectory from moleculekit.projections.metricfluctuation import MetricFluctuation # .project returns squared per-atom displacement (shape (n_frames, n_CA), # units Ų). RMSF = sqrt(mean over frames of the squared displacement). sq_disp = MetricFluctuation("protein and name CA").project(mol) rmsf = np.sqrt(sq_disp.mean(axis=0)) # shape (n_CA,), units Å ``` ```python # Align before computing RMSD to separate rotation from internal motion mol.align("protein and name CA", refmol=ref) rmsd_aligned = molRMSD(mol, ref, ca_idx, ca_idx) ``` ## Gotchas - {py:func}`~moleculekit.util.molRMSD` computes raw (non-mass-weighted) RMSD; align the structures first if you want to remove rigid-body motion. - RMSF is per-atom and depends on the choice of reference (mean structure); the result is sensitive to conformational heterogeneity. - Both `mol` and `refmol` must have the same number of selected atoms. - {py:class}`~moleculekit.projections.metricfluctuation.MetricFluctuation` returns **squared** per-atom displacement (`(n_frames, n_atoms)`, units Ų) — as its own docstring states ("to get the RMSD you need to compute the square root of the mean of the results this projection returns"). For RMSF take `np.sqrt(sq_disp.mean(axis=0))`; `sq_disp.mean(axis=0)` alone is mean-squared-fluctuation, not RMSF. ## See also - [How to align structures](align-structures.md) - [How to compute projections](compute-projections.md)