GROMACS and MD Trajectories

Orbitron supports GROMACS .gro coordinate files and read-only .xtc trajectories. It reads one GRO structure or a short trajectory formed by concatenating GRO frames, and it writes one GRO structure. XTC stays lazy and requires a companion topology-bearing GRO, PDB, mmCIF, or other structure that Orbitron can load. TPR, TRR, TOP, and ITP are not supported.

For a reproducible three-frame XTC workflow, run examples/biology-and-md/run.sh trajectory from a source checkout. The compact examples page describes the generated CSV, PNG, GRO, and bundle outputs.

If the only available structure is a TPR, use GROMACS itself to extract a coordinate-only GRO before opening the trajectory:

gmx editconf -f topol.tpr -o topol.gro
orbitron view production.xtc --topology topol.gro

This conversion does not preserve molecule definitions, exclusions, constraints, virtual sites, interaction functions, or force-field parameters. Keep the original TPR with the simulation. Orbitron does not parse TPR because its current scene model cannot represent those fields faithfully and the versioned reader is not a stable external GROMACS API.

Data Read Write Notes
Positions Yes Yes GRO nm values become Å inside Orbitron and are converted back on export
Residue and atom identity Yes Yes Five-column source numbers are retained; logical residue numbering is unwrapped internally
Velocities Yes Yes Units remain nm/ps; a write includes them only when every atom has a complete vector
Time in the title Yes As title Each trajectory frame retains t= as gromacs:time_ps metadata; export preserves the frame title but has no separate time-setting option
Orthorhombic and triclinic box Yes Yes Three- and nine-value GRO records are supported
Bonds and force-field topology No No Display bonds may be inferred after loading, but they did not come from GRO
Charges, isotopes, molecular charge/spin No No Export reports these losses
XTC positions, time/step, precision, and box Yes No Indexed with cancellable progress, then read lazily; coordinates and boxes become Å at the codec boundary
XTC atom identity and bonds From companion No XTC has none; --topology or the desktop pairing dialog is mandatory

Open and inspect

Open the file in the desktop:

orbitron view system.gro

The desktop exposes concatenated frames through its trajectory controls and draws the current periodic cell. File → Export → Export GROMACS GRO… writes the base scene. Visible comparison overlays are excluded because they do not belong to the system’s residue table or box. Any topology, charge, isotope, or other unsupported field appears as a warning toast.

The TUI uses the same loader:

orbitron view system.gro --tui

Move to the Sequence pane and use n/p or the arrow keys to step frames. The pane shows the current cell lengths and periodic axes. Space starts or stops playback for a concatenated GRO trajectory. For MD trajectories, u cycles the periodic-coordinate view. Pick atoms with Space in the Atoms pane, then use c to center on the picked atoms, f to fit with three or more picked atoms, or x to clear centering or fitting. With no picked atoms, c uses the current atom-list cursor.

Open a compressed XTC in the CLI or TUI by naming its topology:

orbitron view production.xtc --topology system.gro
orbitron view production.xtc --topology system.gro --tui
orbitron info production.xtc --topology system.gro --frame 500 --json
orbitron convert production.xtc --topology system.gro --frame 500 -o frame-501.xyz

The same named views are available to every CLI command that loads an MD trajectory:

orbitron info production.xtc --topology system.gro \
  --trajectory-pbc whole-molecules --frame 500 --json
orbitron convert production.xtc --topology system.gro \
  --trajectory-pbc no-jump --trajectory-center 'resname SOL' \
  --frame 500 -o centered.xyz
orbitron render production.xtc --topology system.gro \
  --trajectory-fit 'chain A and not element H' \
  --trajectory-fit-reference 100 --frame 500 -o fitted.png

--trajectory-pbc accepts as-stored, whole-molecules, or no-jump. Center and fit selections use Orbitron’s selection language. Fit reference and frame indices are zero-based. Centering and fitting conflict because they are the same post-transform slot; both compose with the selected PBC mode.

The desktop asks for the topology after an XTC is selected. It then offers strict coordinate verification or explicit atom-order confirmation. Use the confirmation choice only when the topology describes another frame and its atom order is known to be identical.

After loading, open Analysis → Trajectory. The periodic-boundary menu has three reconstruction choices:

  • As stored shows the decoded coordinates without reconstruction.
  • Whole molecules rebuilds each bonded component through the full triclinic cell.
  • No-jump / unwrapped accumulates minimum-image motion from frame 1.

A second menu applies Center current selection or Fit to current frame after reconstruction. Centering needs at least one selected atom and an invertible periodic cell. Fitting needs at least three selected atoms. The fit selection and current frame become the stored reference.

Whole-molecule and no-jump views need explicit bonds from the companion structure. Their entries are disabled when the loaded topology has no cell or no bonds. Sequential no-jump playback and full export retain a bounded cursor, so each new frame is decoded once. A backward seek restarts reconstruction at frame 1 because unwrapped coordinates depend on the preceding path.

For scripts, inspect the last structure or convert the complete text trajectory to multiframe XYZ:

orbitron info system.gro --json
orbitron convert system.gro -o system.xyz --trajectory
orbitron convert system.gro -o frame-51.gro --frame 50

Frame indices are zero-based in --frame. GRO output is deliberately single-frame. --trajectory with a GRO destination is refused instead of silently dropping frames.

Python

The Python bridge follows the same scene/trajectory split:

import orbitron

orb = orbitron.Orbitron()
scene = orb.load("system.gro")
trajectory = orb.load_trajectory("system.gro")
xtc = orb.load_trajectory("production.xtc", topology="system.gro")

print(scene.atom_count())
print(trajectory.frame_count())
print(trajectory.frame(0).unit_cell())

orb.export(trajectory.frame(0), "frame-1.gro")

load() returns the canonical structure, which is the last frame for a concatenated GRO source. load_trajectory() retains every frame, and the desktop and TUI initially present frame zero for an MD trajectory. Exporting a selected frame also uses that frame’s velocity metadata. Orbitron omits the velocity columns when the selected frame lacks a complete vector for every atom.

Topology and periodic-boundary boundary

A GRO file cannot supply force-field bonds, masses, molecule definitions, or exclusions. Orbitron currently infers ordinary display bonds from geometry. Do not treat those bonds as a GROMACS topology or use them to reproduce a simulation.

XTC contains no atom identity. Orbitron refuses every atom-count mismatch. If the companion’s coordinates match frame 1 within the XTC precision, the pair is recorded as coordinate-verified. Otherwise the load fails unless the user sets --confirm-xtc-atom-order, chooses Confirm atom order in the desktop, or passes confirm_atom_order=True from Python. That weaker evidence remains in the trajectory metadata and produces a warning.

Periodic-boundary reconstruction and centering/alignment are separate, composable view settings. Switching either setting rematerializes the frame from the original trajectory, so transforms never compound and the source coordinates stay unchanged. Sessions retain both settings.

Exporting the visible transformed frame to XYZ, PDB, GRO, or Molfile records the frame, time, step, PBC mode, post-transform, one-based selection, reference frame, source-frame digest, and topology digest. PNG exports carry the same fields as JSON metadata.

MD analysis

orbitron analyze md makes one bounded-memory pass over the requested frames. It can compute RMSD, atom- or residue-level RMSF, mass-weighted radius of gyration, distance/angle/dihedral series, residue-contact occupancy, explicit-hydrogen bond occupancy, and cross-chain interface persistence.

orbitron --topology system.gro analyze md production.xtc \
  --selection 'chain A and not element H' \
  --start 100 --stop 1000 --stride 10 \
  --reference-frame 100 --rmsd --rmsf residue \
  --radius-of-gyration --distance 10,42 \
  --contacts 4.0 --hydrogen-bonds --interfaces 4.0 \
  --output analysis.json

Frame indices are zero-based and --stop is exclusive. Atom numbers in --distance, --angle, and --dihedral are one-based scene positions. Repeat a measurement flag to request more than one series. Output paths must end in .json or .csv; --json writes the complete report to stdout.

Geometry series default to minimum-image measurements. Use --measurement-pbc as-coordinates to measure the coordinates as presented by the selected trajectory view. This distinction matters for a pair split across a periodic boundary. --trajectory-pbc, --trajectory-center, and --trajectory-fit still run first and are recorded separately.

RMSD is unweighted; the independent GROMACS comparison therefore uses gmx rms -nomw. Radius of gyration uses natural element masses. Residue RMSF is the root mean square of the constituent atoms’ RMSF values.

Use --reference-structure to compare with a separately loaded structure:

orbitron --topology system.gro analyze md production.xtc \
  --selection 'chain A and not element H' \
  --rmsd --reference-structure experimental.pdb \
  --reference-selection 'chain A and not element H' \
  --output rmsd-to-experiment.json

Orbitron pairs the two selections by scene order. It refuses unequal atom counts or an atomic-number mismatch at any paired position. The report records the reference path, SHA-256 digest, and one-based selected reference atoms. This is a direct, unweighted coordinate comparison. Supply a coordinate-aligned reference, or choose the trajectory’s named fit view before analysis when that is the intended comparison.

Every report records units, the half-open frame range, stride, exact analyzed frame count, one-based selection, PBC view, post-transform and fit definition, measurement PBC mode, topology digest, and trajectory SHA-256 digest. Orbitron does not create the final CSV or JSON until analysis completes. The shared engine accepts cooperative cancellation and retains only online RMSF state, occupancy counters, requested time-series rows, and the trajectory source’s bounded frame cache.

Independent validation

The checked-in corpus covers velocities, variable coordinate precision, concatenated triclinic frames, ions, and residue-number rollover. Its persistent differential test normalizes the same files through GROMACS 2026.3, compares all retained frames, and asks gmx check to accept Orbitron’s writes:

python scripts/gromacs_gro_differential.py \
  io/pipelines/tests/fixtures/gromacs \
  --binary target/release/orbitron \
  --report notes/gromacs-gro-differential-report.json

The report classifies every source as agree, disagree, tool_refused, or reference_refused. A passing run has only agree results.

The XTC gate compares every decoded position, triclinic cell component, time, step, and precision against both GROMACS 2026.3 and Chemfiles 0.10.4:

python scripts/gromacs_xtc_differential.py \
  --orbitron target/release/orbitron \
  --trajectory io/pipelines/tests/fixtures/gromacs/xtc-reference.xtc \
  --topology io/pipelines/tests/fixtures/gromacs/xtc-topology.gro \
  --report notes/gromacs-xtc-differential-report.json

The MD-analysis gate has 11 cases. It compares unfitted, fitted, and separately loaded reference RMSD, atom RMSF, mass-weighted radius of gyration, raw/minimum-image boundary distances, and non-empty residue-contact and hydrogen-bond occupancies with GROMACS 2026.3. The occupancy fixture has four frames with events that appear and disappear. The gate compares exact per-frame counts and exact identity present-frame counts, so an empty result cannot pass. It generates its XTC and TPR reference inputs from pinned text fixtures and classifies every case explicitly:

conda run -n orbitron-dev python scripts/gromacs_md_analysis_differential.py \
  --orbitron target/release/orbitron \
  --repository "$PWD" \
  --work-dir "$HOME/scratch/orbitron-md-differential" \
  --report notes/gromacs-md-analysis-differential-report.json