An object-oriented toolkit to analyze molecular dynamics trajectories.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
This document covers the core functionality of MDAnalysis, focusing on the fundamental classes and operations that form the foundation of molecular dynamics analysis workflows.
The Universe class is the central object in MDAnalysis, representing a complete molecular system with both topology and coordinate information.
class Universe:
"""
The MDAnalysis Universe class ties a topology and trajectory together.
A Universe combines topology information (atoms, bonds, residues) with
coordinate data from one or more trajectory files.
"""
def __init__(self, topology, *coordinates, **kwargs):
"""
Create a Universe from topology and coordinate files.
Parameters
----------
topology : str or file-like or None
Topology file path or file-like object. Supported formats include
PSF, PDB, GRO, TPR, PRMTOP, and many others. Can be None to create
an empty Universe.
*coordinates : str or file-like, optional
Trajectory file(s) containing coordinate time series. Multiple
files will be concatenated. Supported formats include DCD, XTC,
TRR, NetCDF, and many others.
all_coordinates : bool, optional
Try to load all coordinate files found in the same directory.
Default is False.
guess_bonds : bool, optional
Whether to guess bonds from inter-atomic distances. Default is True.
vdwradii : dict, optional
Dictionary of van der Waals radii for bond guessing.
fudge_factor : float, optional
Tolerance factor for bond guessing (default 0.55).
is_anchor : bool, optional
Whether this Universe should be considered an anchor for
inter-Universe operations.
anchor_name : str, optional
Name for anchor Universe.
transformations : callable or list, optional
Transformation functions to apply on-the-fly.
in_memory : bool, optional
Whether to load trajectory into memory for faster access.
in_memory_step : int, optional
Step size for in-memory loading (default 1).
continuous : bool, optional
Whether to make coordinates continuous across periodic boundaries.
dt : float, optional
Time step between frames if not present in trajectory.
**kwargs
Additional keyword arguments passed to format-specific readers.
Examples
--------
>>> u = Universe("topology.psf", "trajectory.dcd")
>>> u = Universe("system.pdb") # Single frame
>>> u = Universe("topol.tpr", "traj1.xtc", "traj2.xtc") # Multiple trajs
>>> u = Universe(None, n_atoms=1000) # Empty universe
"""class Universe:
@property
def atoms(self):
"""
All atoms in the Universe.
Returns
-------
AtomGroup
AtomGroup containing all atoms in the system.
"""
@property
def residues(self):
"""
All residues in the Universe.
Returns
-------
ResidueGroup
ResidueGroup containing all residues in the system.
"""
@property
def segments(self):
"""
All segments in the Universe.
Returns
-------
SegmentGroup
SegmentGroup containing all segments in the system.
"""
@property
def trajectory(self):
"""
Trajectory reader object associated with the Universe.
Returns
-------
ReaderBase
Trajectory reader providing access to coordinate frames.
"""
@property
def dimensions(self):
"""
Unit cell dimensions of the current frame.
Returns
-------
numpy.ndarray or None
Array of [a, b, c, alpha, beta, gamma] where a,b,c are box
lengths and alpha,beta,gamma are box angles. None if no
unit cell information is available.
"""class Universe:
def copy(self):
"""
Create an independent copy of the Universe.
Returns
-------
Universe
Deep copy of the Universe with independent trajectory.
Examples
--------
>>> u_copy = u.copy()
>>> u_copy.trajectory[10] # Navigate independently
"""
@classmethod
def empty(cls, n_atoms, n_residues=1, n_segments=1, atom_resindex=None,
residue_segindex=None, trajectory=False, velocities=False,
forces=False, **kwargs):
"""
Create an empty Universe with specified number of components.
Parameters
----------
n_atoms : int
Number of atoms to create.
n_residues : int, optional
Number of residues to create (default 1).
n_segments : int, optional
Number of segments to create (default 1).
atom_resindex : array-like, optional
Mapping of atoms to residues.
residue_segindex : array-like, optional
Mapping of residues to segments.
trajectory : bool, optional
Whether to create a trajectory (default False).
velocities : bool, optional
Whether to include velocity information (default False).
forces : bool, optional
Whether to include force information (default False).
Returns
-------
Universe
Empty Universe ready for data population.
Examples
--------
>>> u = Universe.empty(1000, n_residues=100)
>>> u.atoms.positions = np.random.random((1000, 3)) * 100
"""
def select_atoms(self, *args, **kwargs):
"""
Select atoms using the selection language.
Parameters
----------
*args : str
Selection string(s) in MDAnalysis selection language.
updating : bool, optional
Whether the selection should update when topology changes.
periodic : bool, optional
Whether to account for periodic boundary conditions in
geometric selections.
rtol : float, optional
Relative tolerance for geometric selections.
atol : float, optional
Absolute tolerance for geometric selections.
Returns
-------
AtomGroup
Selected atoms matching the criteria.
Examples
--------
>>> protein = u.select_atoms("protein")
>>> ca_atoms = u.select_atoms("name CA")
>>> near_ligand = u.select_atoms("around 5.0 resname LIG")
>>> complex_sel = u.select_atoms("protein and not backbone")
"""
def load_new(self, filename, format=None, in_memory=False, **kwargs):
"""
Load a new trajectory into the Universe.
Parameters
----------
filename : str or file-like
Path to trajectory file or file-like object.
format : str, optional
File format, guessed from extension if not provided.
in_memory : bool, optional
Whether to load trajectory into memory.
**kwargs
Additional arguments for trajectory reader.
Examples
--------
>>> u.load_new("new_trajectory.xtc")
>>> u.load_new("production.dcd", in_memory=True)
"""
def transfer_to_memory(self, start=None, stop=None, step=None,
verbose=False):
"""
Transfer trajectory frames to memory for faster access.
Parameters
----------
start : int, optional
First frame to transfer (default None for beginning).
stop : int, optional
Last frame to transfer (default None for end).
step : int, optional
Step size for frame transfer (default None for 1).
verbose : bool, optional
Whether to show progress (default False).
Examples
--------
>>> u.transfer_to_memory() # Load all frames
>>> u.transfer_to_memory(0, 1000, 10) # Every 10th frame
"""
@classmethod
def from_smiles(cls, smiles, sanitize=True, addHs=True,
generate_coordinates=True, numConfs=1,
rdkit_kwargs=None, **kwargs):
"""
Create a Universe from a SMILES string using RDKit.
Parameters
----------
smiles : str
SMILES string representation of the molecule.
sanitize : bool, optional
Whether to sanitize the molecule (default True).
addHs : bool, optional
Whether to add hydrogens to the molecule (default True).
generate_coordinates : bool, optional
Whether to generate 3D coordinates (default True).
numConfs : int, optional
Number of conformers to generate (default 1).
rdkit_kwargs : dict, optional
Additional arguments for RDKit conformer generation.
**kwargs
Additional arguments for Universe creation.
Returns
-------
Universe
Universe object with topology and coordinates from SMILES.
Examples
--------
>>> u = Universe.from_smiles('CCO') # Ethanol
>>> u = Universe.from_smiles('c1ccccc1', numConfs=10) # Benzene conformers
"""
def add_TopologyAttr(self, topologyattr, values=None):
"""
Add a new topology attribute to the Universe.
Parameters
----------
topologyattr : str or TopologyAttr
Name of topology attribute or TopologyAttr object.
values : array-like, optional
Initial values for the attribute. If None, empty/zero values used.
Examples
--------
>>> u.add_TopologyAttr('tempfactors')
>>> u.add_TopologyAttr('charges', [0.5, -0.5, 0.0])
>>> u.atoms.tempfactors # Now available
"""
def del_TopologyAttr(self, topologyattr):
"""
Remove a topology attribute from the Universe.
Parameters
----------
topologyattr : str
Name of topology attribute to remove.
Examples
--------
>>> u.del_TopologyAttr('tempfactors')
"""The AtomGroup class represents a collection of atoms and provides the primary interface for molecular analysis operations.
class AtomGroup:
"""
A group of atoms that can be used for analysis and manipulation.
AtomGroups are created through atom selection or by combining existing
groups. They provide methods for geometric analysis, transformations,
and property access.
"""
def __init__(self, indices, universe):
"""
Create an AtomGroup from atom indices.
Parameters
----------
indices : array-like
Indices of atoms to include in the group.
universe : Universe
Universe object containing the atoms.
Note
----
AtomGroups are typically created through Universe.select_atoms()
rather than direct instantiation.
"""class AtomGroup:
@property
def positions(self):
"""
Coordinates of atoms in the current frame.
Returns
-------
numpy.ndarray
Array of shape (n_atoms, 3) containing x,y,z coordinates
in Angstrom units.
Examples
--------
>>> coords = protein.positions
>>> protein.positions += [10.0, 0.0, 0.0] # Translate
"""
@property
def velocities(self):
"""
Velocities of atoms in the current frame.
Returns
-------
numpy.ndarray or None
Array of shape (n_atoms, 3) containing velocity components
in Angstrom/ps units. None if no velocity data available.
"""
@property
def forces(self):
"""
Forces on atoms in the current frame.
Returns
-------
numpy.ndarray or None
Array of shape (n_atoms, 3) containing force components.
None if no force data available.
"""
@property
def masses(self):
"""
Masses of atoms in the group.
Returns
-------
numpy.ndarray
Array of atomic masses in amu units.
"""
@property
def charges(self):
"""
Partial charges of atoms in the group.
Returns
-------
numpy.ndarray or None
Array of atomic charges in elementary charge units.
None if no charge data available.
"""
@property
def names(self):
"""
Atom names in the group.
Returns
-------
numpy.ndarray
Array of string atom names (e.g., 'CA', 'CB', 'N').
"""
@property
def n_atoms(self):
"""
Number of atoms in the group.
Returns
-------
int
Count of atoms in this AtomGroup.
"""
@property
def residues(self):
"""
Unique residues containing atoms from this group.
Returns
-------
ResidueGroup
ResidueGroup containing the unique residues.
"""
@property
def segments(self):
"""
Unique segments containing atoms from this group.
Returns
-------
SegmentGroup
SegmentGroup containing the unique segments.
"""class AtomGroup:
def center_of_mass(self, wrap=False, unwrap=False, compound="group"):
"""
Calculate center of mass of the group.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates into primary unit cell.
unwrap : bool, optional
Whether to unwrap coordinates across periodic boundaries.
compound : {'group', 'segments', 'residues', 'molecules', 'fragments'}
How to treat the group for wrapping/unwrapping.
Returns
-------
numpy.ndarray
Center of mass coordinates as 3-element array.
Examples
--------
>>> com = protein.center_of_mass()
>>> com_wrapped = protein.center_of_mass(wrap=True)
"""
def center_of_geometry(self, wrap=False, unwrap=False, compound="group"):
"""
Calculate geometric center of the group.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates into primary unit cell.
unwrap : bool, optional
Whether to unwrap coordinates across periodic boundaries.
compound : {'group', 'segments', 'residues', 'molecules', 'fragments'}
How to treat the group for wrapping/unwrapping.
Returns
-------
numpy.ndarray
Geometric center coordinates as 3-element array.
"""
def radius_of_gyration(self, wrap=False, **kwargs):
"""
Calculate radius of gyration of the group.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates into primary unit cell.
**kwargs
Additional arguments for coordinate processing.
Returns
-------
float
Radius of gyration in Angstrom units.
Examples
--------
>>> rgyr = protein.radius_of_gyration()
>>> print(f"Radius of gyration: {rgyr:.2f} Å")
"""
def principal_axes(self, wrap=False):
"""
Calculate principal axes of the coordinate distribution.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates into primary unit cell.
Returns
-------
numpy.ndarray
Array of shape (3, 3) where rows are principal axes
ordered by decreasing eigenvalue.
"""
def moment_of_inertia(self, wrap=False):
"""
Calculate moment of inertia tensor.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates into primary unit cell.
Returns
-------
numpy.ndarray
3x3 moment of inertia tensor.
"""
def bbox(self, wrap=False):
"""
Calculate bounding box of atomic coordinates.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates into primary unit cell.
Returns
-------
numpy.ndarray
Array of shape (2, 3) containing minimum and maximum
coordinates: [[xmin, ymin, zmin], [xmax, ymax, zmax]].
"""
def bsphere(self, wrap=False):
"""
Calculate bounding sphere of atomic coordinates.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates into primary unit cell.
Returns
-------
tuple
(center, radius) where center is 3-element array of
sphere center and radius is the sphere radius.
"""class AtomGroup:
def __add__(self, other):
"""
Concatenate with another AtomGroup.
Parameters
----------
other : AtomGroup
AtomGroup to concatenate with.
Returns
-------
AtomGroup
New AtomGroup containing atoms from both groups.
Examples
--------
>>> combined = group1 + group2
>>> all_ca = ca_chain_a + ca_chain_b
"""
def __sub__(self, other):
"""
Remove atoms present in another AtomGroup.
Parameters
----------
other : AtomGroup
AtomGroup whose atoms should be removed.
Returns
-------
AtomGroup
New AtomGroup with specified atoms removed.
"""
def union(self, other):
"""
Return union of this group with another.
Parameters
----------
other : AtomGroup
AtomGroup to form union with.
Returns
-------
AtomGroup
New AtomGroup containing unique atoms from both groups.
"""
def intersection(self, other):
"""
Return intersection of this group with another.
Parameters
----------
other : AtomGroup
AtomGroup to intersect with.
Returns
-------
AtomGroup
New AtomGroup containing atoms present in both groups.
"""
def select_atoms(self, selection, **kwargs):
"""
Select a subset of atoms from this group.
Parameters
----------
selection : str
Selection string in MDAnalysis selection language.
**kwargs
Additional arguments for selection.
Returns
-------
AtomGroup
Subset of atoms matching the selection criteria.
Examples
--------
>>> ca_atoms = protein.select_atoms("name CA")
>>> backbone = protein.select_atoms("backbone")
"""
def split(self, level):
"""
Split group by connectivity or hierarchy level.
Parameters
----------
level : {'atoms', 'residues', 'segments', 'molecules', 'fragments'}
Level at which to split the group.
Returns
-------
list
List of AtomGroup objects split at specified level.
Examples
--------
>>> chains = protein.split('segments')
>>> fragments = system.split('fragments')
"""
def groupby(self, topattrs):
"""
Group atoms by topology attributes.
Parameters
----------
topattrs : str or list
Topology attribute name(s) to group by.
Returns
-------
dict
Dictionary mapping attribute values to AtomGroups.
Examples
--------
>>> by_resname = protein.groupby('resnames')
>>> by_element = system.groupby(['elements', 'names'])
"""class AtomGroup:
def translate(self, t):
"""
Translate atomic coordinates by a vector.
Parameters
----------
t : array-like
Translation vector as 3-element array.
Examples
--------
>>> protein.translate([10.0, 0.0, 0.0]) # Move 10 Å along x
>>> protein.translate(center_of_mass) # Translate by COM
"""
def rotate(self, R, point=(0, 0, 0)):
"""
Rotate coordinates using rotation matrix.
Parameters
----------
R : array-like
3x3 rotation matrix.
point : array-like, optional
Point about which to rotate (default origin).
Examples
--------
>>> import scipy.spatial.transform as st
>>> R = st.Rotation.from_euler('z', 90, degrees=True).as_matrix()
>>> protein.rotate(R)
"""
def rotateby(self, angle, axis, point=None):
"""
Rotate by angle around axis.
Parameters
----------
angle : float
Rotation angle in degrees.
axis : array-like
Rotation axis as 3-element unit vector.
point : array-like, optional
Point about which to rotate (default group center).
Examples
--------
>>> protein.rotateby(45.0, [0, 0, 1]) # 45° around z-axis
"""
def transform(self, M):
"""
Apply transformation matrix to coordinates.
Parameters
----------
M : array-like
4x4 transformation matrix or 3x3 rotation matrix.
Examples
--------
>>> # Apply combined rotation and translation
>>> M = np.eye(4)
>>> M[:3, :3] = rotation_matrix
>>> M[:3, 3] = translation_vector
>>> protein.transform(M)
"""
def wrap(self, compound="atoms", center="com", box=None, inplace=True):
"""
Wrap coordinates into primary unit cell.
Parameters
----------
compound : {'atoms', 'group', 'segments', 'residues', 'molecules', 'fragments'}
How to wrap the coordinates.
center : {'com', 'cog'} or array-like
Point around which to center the wrapping.
box : array-like, optional
Unit cell dimensions (default from trajectory).
inplace : bool, optional
Whether to modify coordinates in place (default True).
Returns
-------
numpy.ndarray or None
Wrapped coordinates if inplace=False, otherwise None.
"""
def unwrap(self, compound="fragments", reference="com", inplace=True):
"""
Unwrap coordinates across periodic boundaries.
Parameters
----------
compound : {'atoms', 'group', 'segments', 'residues', 'molecules', 'fragments'}
How to unwrap the coordinates.
reference : {'com', 'cog'} or array-like
Reference point for unwrapping.
inplace : bool, optional
Whether to modify coordinates in place (default True).
Returns
-------
numpy.ndarray or None
Unwrapped coordinates if inplace=False, otherwise None.
"""
def center_of_geometry(self, wrap=False, unwrap=False, compound="group"):
"""
Calculate geometric center (centroid) of atoms.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates before calculation (default False)
unwrap : bool, optional
Whether to unwrap coordinates before calculation (default False)
compound : str, optional
How to treat the AtomGroup as a compound ('group', 'segments', etc.)
Returns
-------
numpy.ndarray
Geometric center coordinates [x, y, z]
Examples
--------
>>> centroid = protein.center_of_geometry()
>>> centroid = ligand.center_of_geometry(wrap=True)
"""
def bbox(self, wrap=False):
"""
Calculate bounding box of atomic coordinates.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates before calculation (default False)
Returns
-------
numpy.ndarray
Bounding box as [[xmin, ymin, zmin], [xmax, ymax, zmax]]
Examples
--------
>>> box = protein.bbox()
>>> dimensions = box[1] - box[0] # Width, height, depth
"""
def bsphere(self, wrap=False):
"""
Calculate bounding sphere of atomic coordinates.
Parameters
----------
wrap : bool, optional
Whether to wrap coordinates before calculation (default False)
Returns
-------
tuple
(center, radius) where center is numpy.ndarray and radius is float
Examples
--------
>>> center, radius = protein.bsphere()
>>> volume = (4/3) * np.pi * radius**3
"""
def get_connections(self, typename, outside=True):
"""
Get connectivity information (bonds, angles, dihedrals) for the group.
Parameters
----------
typename : str
Type of connection ('bonds', 'angles', 'dihedrals', 'impropers')
outside : bool, optional
Whether to include connections to atoms outside the group (default True)
Returns
-------
TopologyGroup
Group of connections of the specified type
Examples
--------
>>> bonds = protein.get_connections('bonds')
>>> angles = residue.get_connections('angles', outside=False)
"""These classes provide similar interfaces to AtomGroup but operate at the residue and segment levels respectively.
class ResidueGroup:
"""
A group of residues with aggregate properties and analysis methods.
"""
@property
def atoms(self):
"""
All atoms belonging to residues in this group.
Returns
-------
AtomGroup
AtomGroup containing all atoms from these residues.
"""
@property
def n_atoms(self):
"""
Total number of atoms in all residues.
Returns
-------
int
Sum of atoms across all residues in the group.
"""
@property
def resnames(self):
"""
Residue names in the group.
Returns
-------
numpy.ndarray
Array of residue names (e.g., 'ALA', 'GLY', 'PRO').
"""
@property
def resids(self):
"""
Residue IDs in the group.
Returns
-------
numpy.ndarray
Array of residue ID numbers.
"""class SegmentGroup:
"""
A group of segments (chains/molecules) with aggregate properties.
"""
@property
def atoms(self):
"""
All atoms belonging to segments in this group.
Returns
-------
AtomGroup
AtomGroup containing all atoms from these segments.
"""
@property
def residues(self):
"""
All residues belonging to segments in this group.
Returns
-------
ResidueGroup
ResidueGroup containing all residues from these segments.
"""
@property
def segids(self):
"""
Segment IDs in the group.
Returns
-------
numpy.ndarray
Array of segment ID strings.
"""def Merge(*args, **kwargs):
"""
Create a new Universe by merging existing AtomGroups.
Parameters
----------
*args : AtomGroup
AtomGroups to merge into new Universe.
**kwargs
Additional arguments for Universe creation.
Returns
-------
Universe
New Universe containing merged atoms with combined topology.
Examples
--------
>>> u1 = Universe("protein.pdb")
>>> u2 = Universe("ligand.mol2")
>>> complex_u = Merge(u1.atoms, u2.atoms)
>>> # Merge specific selections
>>> protein = u.select_atoms("protein")
>>> waters = u.select_atoms("resname SOL")
>>> new_u = Merge(protein, waters)
"""# Create universe and basic selections
u = mda.Universe("topology.psf", "trajectory.dcd")
protein = u.select_atoms("protein")
waters = u.select_atoms("resname SOL")
# Trajectory iteration
for ts in u.trajectory:
# Calculate properties for current frame
protein_com = protein.center_of_mass()
protein_rgyr = protein.radius_of_gyration()
# Check if protein is compact
if protein_rgyr < 15.0:
print(f"Frame {ts.frame}: Compact conformation")# Select and analyze binding site
binding_site = u.select_atoms("resid 23 45 67 89 120")
ligand = u.select_atoms("resname LIG")
# Calculate distances
distances = []
for ts in u.trajectory:
# Distance between binding site and ligand centers
bs_center = binding_site.center_of_geometry()
lig_center = ligand.center_of_geometry()
dist = np.linalg.norm(bs_center - lig_center)
distances.append(dist)
# Group manipulation
ca_atoms = protein.select_atoms("name CA")
backbone = protein.select_atoms("backbone")
sidechain = protein - backbone # Remove backbone atoms
# Split into chains
chains = protein.split('segments')
for i, chain in enumerate(chains):
print(f"Chain {i}: {chain.n_atoms} atoms")# Center protein at origin
protein_center = protein.center_of_mass()
protein.translate(-protein_center)
# Align protein with reference
reference = u.select_atoms("name CA")
mobile = protein.select_atoms("name CA")
# Calculate optimal rotation matrix (requires additional imports)
from MDAnalysis.analysis.align import rotation_matrix
R, rmsd = rotation_matrix(mobile.positions, reference.positions)
protein.rotate(R)
# Wrap coordinates for visualization
system = u.atoms
system.wrap(compound="residues", center="com")Install with Tessl CLI
npx tessl i tessl/pypi-mdanalysis