mdanalysis/mdanalysis
MDAnalysis is a Python library to analyze molecular dynamics simulations.
12 hidden assumptions · 8-stage pipeline · 8 components
Like any codebase, this scientific computing makes assumptions it never checks — most are routine. The ones worth your attention are below.
Loads molecular dynamics trajectories and analyzes atom coordinates using NumPy arrays
Users create a Universe by loading topology and trajectory files through format-specific parsers that extract molecular structure and coordinate data. The Universe provides AtomGroups for atom selection, which are passed to analysis classes that inherit from AnalysisBase. During analysis execution, the system iterates through trajectory frames, applies analysis algorithms to atomic coordinates, and accumulates results in time-series arrays accessible after completion.
Under the hood, the system uses 2 feedback loops, 3 data pools, 3 control points to manage its runtime behavior.
A 8-component scientific computing. 453 files analyzed. Data flows through 8 distinct pipeline stages.
Hidden Assumptions
Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".
If atom counts differ, NumPy broadcasting will fail with dimension mismatch errors, or if counts match but atom ordering differs, the alignment will compute rotation matrices based on wrong atom correspondences, producing meaningless RMSD values and incorrect structural alignments
If trajectory coordinates are in nanometers but reference structure is in Angstroms (common with different MD packages), contact fractions will be completely wrong - a 4.5 Angstrom cutoff becomes 4.5 nanometers, missing most real contacts and detecting spurious long-range contacts
If _single_frame() calls trajectory.next() or changes the current frame, the iteration logic breaks, causing frames to be skipped or processed multiple times, leading to incorrect time-series data in results.times and analysis metrics
Show everything (9 more)
All AtomGroup objects and analysis parameters can be successfully pickled for inter-process communication - the multiprocessing backend serializes the entire analysis state to worker processes
If this fails: If AtomGroups contain unpicklable objects (like lambda functions in custom selections or certain topology attributes), multiprocessing will fail with PicklingError, forcing fallback to serial execution without warning the user about the performance degradation
package/MDAnalysis/analysis/backends.py:BackendMultiprocessing
Trajectory frames are accessed in sequential order during analysis - caching mechanisms expect forward iteration and may not handle random access efficiently
If this fails: If analysis algorithms jump between non-consecutive frames (like comparing frame 1000 to frame 10), the trajectory cache becomes ineffective, causing repeated disk I/O that can slow analysis by 10-100x for large trajectory files
package/MDAnalysis/coordinates/base.py:TrajectoryReader
Atomic coordinate arrays will fit in available memory as contiguous NumPy arrays - positions property returns the full coordinate array of shape (n_atoms, 3) for all atoms in the group
If this fails: For large systems (>1M atoms), coordinate arrays can exceed 24GB memory, causing MemoryError crashes during analysis. This hits protein complexes, membrane systems, and solvated systems without warning as array size scales with system complexity
package/MDAnalysis/core/groups.py:AtomGroup.positions
Atom ordering in GRO topology files matches the coordinate ordering in trajectory frames - parser creates atom index mappings based on file order without validation
If this fails: If topology and trajectory files have atoms in different orders (possible when files are generated by different tools or preprocessing steps), AtomGroup.positions will return coordinates for wrong atoms, making all spatial analysis incorrect while appearing to work normally
package/MDAnalysis/topology/GROParser.py:parse
GRO files use standard GROMACS formatting conventions with exact column positions - coordinate parsing depends on fixed-width format assumptions
If this fails: If GRO files are created by non-GROMACS tools with slightly different formatting (different precision, spacing, or column alignment), coordinate parsing will silently read wrong values, corrupting all subsequent analysis without raising parse errors
package/MDAnalysis/coordinates/GRO.py:GROReader
Periodic boundary conditions (PBC) are consistently applied or ignored across all distance calculations - algorithms assume box dimensions in trajectory frames represent the same coordinate system convention
If this fails: If some trajectory frames have PBC information in different conventions (box matrix vs box vectors) or missing PBC data, distance calculations become inconsistent across frames, causing spurious jumps in contact analysis, RMSD, and other spatial measurements
package/MDAnalysis/lib/distances.py:distance_functions
The mobile and reference AtomGroups passed to analysis classes belong to compatible Universe objects with the same topology structure - atom indices and properties should correspond between universes
If this fails: If analysis receives AtomGroups from different topology sources (e.g., comparing protein from one simulation to different protein variant), atom index references become invalid, leading to accessing wrong atoms or IndexError crashes during coordinate operations
package/MDAnalysis/analysis/base.py:AnalysisBase.__init__
Analysis results accumulate in frame order and the results.times array corresponds directly to the frame indices processed - time values are assumed to be monotonically increasing
If this fails: If trajectory frames have non-monotonic timestamps (from concatenated simulations with overlapping times, or restarted runs), the time series analysis becomes meaningless for temporal correlation calculations, and plotting results against time produces confusing non-linear time axes
package/MDAnalysis/analysis/base.py:Results
The testsuite GRO file size is representative of typical usage patterns for benchmarking - performance measurements use a fixed small test system
If this fails: Benchmark results may not reflect real-world performance for large systems (>100K atoms) where memory allocation patterns, I/O bottlenecks, and parsing complexity scale non-linearly, potentially misleading users about expected performance on production datasets
benchmarks/benchmarks/GRO.py:time_create_GRO_universe
Open the standalone hidden-assumptions report for mdanalysis →
How Data Flows Through the System
Users create a Universe by loading topology and trajectory files through format-specific parsers that extract molecular structure and coordinate data. The Universe provides AtomGroups for atom selection, which are passed to analysis classes that inherit from AnalysisBase. During analysis execution, the system iterates through trajectory frames, applies analysis algorithms to atomic coordinates, and accumulates results in time-series arrays accessible after completion.
- Load trajectory files — Format-specific parsers (GROParser, PDBParser, etc.) read molecular dynamics files to extract topology information (atom names, connectivity, residues) and coordinate data, creating TopologyData and TrajectoryFrame objects that represent the molecular system
- Create Universe — Universe.__init__() combines topology and trajectory data into a unified interface, setting up the coordinate reader, establishing atom-residue relationships, and preparing the system for frame iteration and analysis [TopologyData → Universe]
- Atom selection — Users apply selection strings (e.g., 'protein and name CA') to Universe.select_atoms(), which parses the query and returns AtomGroup objects containing the matching atoms with their properties and coordinate access methods [Universe → AtomGroup]
- Create analysis objects — Analysis classes (Contacts, AlignTraj, RMSD) are instantiated with AtomGroup arguments and analysis parameters, inheriting from AnalysisBase to gain trajectory iteration and results storage capabilities [AtomGroup → AnalysisBase]
- Analysis execution — AnalysisBase.run() iterates through trajectory frames, calling _single_frame() for each timestep to compute analysis metrics (distances, angles, contacts) using NumPy operations on atomic coordinates, with optional parallelization via BackendMultiprocessing [AnalysisBase → AnalysisResults]
- Access coordinate frames — During analysis, TrajectoryReader provides TrajectoryFrame objects containing positions, velocities, and box dimensions for each timestep, allowing algorithms to access current atomic coordinates through AtomGroup.positions arrays [Universe → TrajectoryFrame]
- Analysis calculations — Individual analysis algorithms compute structural properties by applying mathematical operations to coordinate arrays - distance calculations use lib.distances functions, alignment uses QCP algorithm for rotation matrices, contacts use distance thresholds [TrajectoryFrame → AnalysisResults]
- Results storage — Computed metrics are accumulated in AnalysisResults containers with time-series arrays (rmsd, contact_fractions, etc.) that can be accessed as analysis.results.attribute_name after run() completion [AnalysisResults]
Data Models
The data structures that flow between stages — the contracts that hold the system together.
package/MDAnalysis/core/universe.pycontainer with atoms: AtomGroup, trajectory: TrajectoryReader, dimensions: ndarray[6] (box dimensions), and topology information including bonds, angles, dihedrals
Created by parsing topology and coordinate files, provides interface to iterate through trajectory frames and access atomic data throughout analysis workflows
package/MDAnalysis/core/groups.pycollection with positions: ndarray[N, 3], masses: ndarray[N], names: ndarray[N] (dtype=str), residues: ResidueGroup, and selection methods returning new AtomGroups
Created through atom selection strings or indexing operations on Universe, provides NumPy array access to atomic properties and coordinates for analysis computations
package/MDAnalysis/analysis/base.pydictionary-like container with times: ndarray[n_frames], computed metrics as ndarrays (e.g., rmsd: ndarray[n_frames], distances: ndarray[n_frames, n_pairs]), and metadata
Populated during AnalysisBase.run() execution by calling _single_frame() for each trajectory frame, stores time-series data accessible after analysis completion
package/MDAnalysis/coordinates/base.pysnapshot with positions: ndarray[N, 3], velocities: ndarray[N, 3] (optional), forces: ndarray[N, 3] (optional), dimensions: ndarray[6] (box), time: float, frame: int
Created by TrajectoryReader when iterating through frames, represents single time snapshot of molecular system with all atomic coordinates and simulation metadata
package/MDAnalysis/topology/core.pystructured data with atoms: dict (names, types, masses, charges), bonds: ndarray[n_bonds, 2], angles: ndarray[n_angles, 3], residues: dict (names, numbers), and connectivity information
Extracted from topology files (PSF, TPR, PDB) by format-specific parsers, provides static structural information about molecular connectivity and atom properties
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
Caches recently accessed trajectory frames to avoid repeated file I/O when analysis algorithms access the same frames multiple times
Maps file extensions to appropriate topology parser classes, enabling automatic parser selection based on file format during Universe creation
Collection of reference molecular dynamics files used for testing parsers and validating analysis results across different file formats and molecular systems
Feedback Loops
- FrameIteration (training-loop, reinforcing) — Trigger: AnalysisBase.run() method call. Action: Advances trajectory to next frame, updates AtomGroup.positions with current coordinates, calls _single_frame() analysis method, stores results. Exit: Reaches end of trajectory or user-specified frame range.
- AlignmentIteration (convergence, balancing) — Trigger: Structural alignment algorithms. Action: Computes rotation matrix using QCP algorithm, applies transformation to coordinates, recalculates RMSD until convergence criteria met. Exit: RMSD minimization converges within tolerance.
Delays
- FileReading (async-processing, ~varies with file size) — Initial Universe creation waits for topology and first trajectory frame to be parsed from disk
- ProcessSpawning (warmup, ~~100ms per worker) — BackendMultiprocessing initialization creates worker processes before analysis begins, adding startup overhead
Control Points
- FrameRange (runtime-toggle) — Controls: Which trajectory frames are processed during analysis execution (start, stop, step parameters). Default: None (defaults to entire trajectory)
- ParallelBackend (architecture-switch) — Controls: Whether analysis runs serially, with multiprocessing, or with dask parallelization. Default: serial
- PrecisionMode (precision-mode) — Controls: Floating point precision for coordinate calculations and distance computations. Default: float64
Technology Stack
Provides ndarray data structures for atomic coordinates and vectorized mathematical operations for distance calculations, alignment algorithms, and structural analysis
Testing framework used throughout the testsuite package to validate file parsers, analysis algorithms, and coordinate transformations with parametrized test cases
Enables parallel analysis execution by distributing trajectory frame processing across multiple worker processes for computationally intensive analysis algorithms
Alternative parallelization backend that provides distributed computing capabilities with different serialization algorithms compared to standard multiprocessing
Key Components
- Universe (orchestrator) — Central coordinator that combines topology and trajectory data, manages frame iteration, and provides the primary interface for accessing molecular system information
package/MDAnalysis/core/universe.py - AnalysisBase (processor) — Abstract base class that provides the analysis execution framework with run() method, frame iteration, parallelization support, and results storage patterns
package/MDAnalysis/analysis/base.py - GROReader (adapter) — Parses GROMACS GRO format coordinate files, extracting atomic positions, velocities, and box dimensions into standardized TrajectoryFrame objects
package/MDAnalysis/coordinates/GRO.py - GROParser (transformer) — Reads GRO topology information including atom names, residue names, and coordinates to create TopologyData structures for Universe construction
package/MDAnalysis/topology/GROParser.py - BackendMultiprocessing (executor) — Parallelizes analysis execution across multiple processes using Python multiprocessing, distributing trajectory frame analysis tasks to worker processes
package/MDAnalysis/analysis/backends.py - AtomGroup (store) — Container for collections of atoms with NumPy array access to positions, properties, and selection methods that return new AtomGroups for analysis operations
package/MDAnalysis/core/groups.py - Contacts (processor) — Analyzes native contacts between atom groups over trajectory frames, computing contact fractions using hard cut, soft cut, or custom distance metrics
package/MDAnalysis/analysis/contacts.py - AlignTraj (transformer) — Performs trajectory alignment by calculating RMSD and rotation matrices using the QCP algorithm, applying transformations to minimize structural differences across frames
package/MDAnalysis/analysis/align.py
Package Structure
Python library for analyzing molecular dynamics simulation trajectories, providing parsers, coordinate readers, and analysis tools for computational chemistry.
Comprehensive test suite for MDAnalysis with benchmarks and validation tests for all analysis modules and file format parsers.
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaRelated Scientific Computing Repositories
Frequently Asked Questions
What is mdanalysis used for?
Loads molecular dynamics trajectories and analyzes atom coordinates using NumPy arrays mdanalysis/mdanalysis is a 8-component scientific computing written in Python. Data flows through 8 distinct pipeline stages. The codebase contains 453 files.
How is mdanalysis architected?
mdanalysis is organized into 4 architecture layers: File Format Layer, Core Data Layer, Analysis Layer, Test Layer. Data flows through 8 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through mdanalysis?
Data moves through 8 stages: Load trajectory files → Create Universe → Atom selection → Create analysis objects → Analysis execution → .... Users create a Universe by loading topology and trajectory files through format-specific parsers that extract molecular structure and coordinate data. The Universe provides AtomGroups for atom selection, which are passed to analysis classes that inherit from AnalysisBase. During analysis execution, the system iterates through trajectory frames, applies analysis algorithms to atomic coordinates, and accumulates results in time-series arrays accessible after completion. This pipeline design reflects a complex multi-stage processing system.
What technologies does mdanalysis use?
The core stack includes NumPy (Provides ndarray data structures for atomic coordinates and vectorized mathematical operations for distance calculations, alignment algorithms, and structural analysis), pytest (Testing framework used throughout the testsuite package to validate file parsers, analysis algorithms, and coordinate transformations with parametrized test cases), multiprocessing (Enables parallel analysis execution by distributing trajectory frame processing across multiple worker processes for computationally intensive analysis algorithms), Dask (Alternative parallelization backend that provides distributed computing capabilities with different serialization algorithms compared to standard multiprocessing). A lean dependency footprint.
What system dynamics does mdanalysis have?
mdanalysis exhibits 3 data pools (TrajectoryCache, TopologyRegistry), 2 feedback loops, 3 control points, 2 delays. The feedback loops handle training-loop and convergence. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does mdanalysis use?
4 design patterns detected: Format Registry Pattern, Template Method Pattern, Facade Pattern, Strategy Pattern.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.