Skip to content

Units, indexing, and scientific conventions

Use these conventions when transferring data between matmalib, simulation engines, notebooks, and other analysis packages. Numeric arrays carry values; attributes such as time_unit describe those values and do not generally convert them.

Coordinates, indices, and shared objects

Concept Convention
Molecular coordinates Finite (n_atoms, 3) array, one row per atom.
Ring coordinates Finite (..., 5, 3) or (..., 6, 3) array in cyclic order.
Trajectory coordinates Full-system frames with a fixed atom count and order.
Glycan/conformer ring, membership, and selection indices Zero-based positions in state.atoms, independent of Atom.id.
Monomer indices Zero-based positions in glycan.monomers; used in link donor/acceptor fields, trajectory column names, and SNFG positions.
Cluster member/representative indices Positions in the original input ensemble, including when some states are excluded.
Glycan construction from a state Retains metadata and shares existing Atom objects.
Representative Space New container sharing the chosen State objects.

Legacy StateEditor distance/angle edits, determine_carried_atoms, and State.connectivity_matrix require each atom.id to equal its position in state.atoms. Dihedral measurements and edits use atom-list positions independently of Atom.id. See geometry prerequisites before editing a manually constructed or renumbered state.

Ring order is not just a set of vertices. Automatic sugar rings begin at O, continue to the anomeric carbon, then follow the remaining ring carbons. Aldoses begin at C1 after O; ketoses begin at C2. Monomers are sorted by their smallest ring atom index. Explicit rings must preserve a consistent starting point and traversal direction for meaningful comparisons.

Explicit monomer assignments do not automatically generate chemical atom names or link metadata. See Glycans for the distinction between geometric assignment and chemical detection.

State-based checks compare element sequences, but they cannot detect swapping two atoms of the same element. Arrays carry no element metadata. These interfaces do not perform symmetry matching, atom mapping, or topology repair.

Length, angle, time, and energy units

Quantity Convention
XYZ coordinates No unit conversion on reading; supplied geometries normally use angstroms.
Sugar bond detection distXX=1.65, distXH=1.15, assuming angstroms. Change cutoffs or supply trusted connectivity for other units.
CP Q, q2, q3 Same length unit as input coordinates.
CP planarity threshold planar_tolerance=1e-6 in coordinate length units.
CP angles Degrees by default; degrees=False selects radians.
Ring-classification distance and carppy_theta Always degrees, including with degrees=False.
StateEditor / State internal angles and dihedrals Always degrees; dihedrals use the signed atan2 convention below.
Glycosidic/backbone torsions Degrees by default; degrees=False selects radians; result records angle_unit.
RMSD and cluster threshold Input coordinate length units.
Trajectory timestep Interval between saved frames; default unit label fs.
Standalone times / time_unit Explicit values and descriptive unit; no rescaling just because the label changes.
CP2K XYZ CP reader Requires timestep; uses fs and ignores comment-line times.
Time-series plot display fs → ps, ps → ns, ns unchanged. The underlying Data values remain unchanged.
Cluster energy_unit Units of stored scalar state energies: hartree (default), kcal/mol, or kJ/mol.
Cluster energy_window Always kcal/mol above the minimum.
CP sphere temp Kelvin, default 300.
CP sphere energy_unit kcal/mol (default) or kJ/mol for the population-derived energy grid.

For mixed sources, normalize coordinates and energy values before combining them. A unit label does not make values compatible. The Data.from_file CP2K adapter does not expose arbitrary time units; use cremer_pople_trajectory for explicit nonuniform times and another unit label.

Cremer–Pople coordinates

For an ordered ring with positions indexed by j=0,...,N-1, coordinates are centered at the ring centroid. The mean-plane normal is the normalized cross product R_sine × R_cosine. Heights z_j are projections onto that normal. The second-mode components follow

q2 * cos(phi) =  sqrt(2/N) * sum_j(z[j] * cos(4*pi*j/N))
q2 * sin(phi) = -sqrt(2/N) * sum_j(z[j] * sin(4*pi*j/N))

For six-membered rings,

q3 = sum_j((-1)**j * z[j]) / sqrt(6)
Q = sqrt(q2**2 + q3**2)
theta = atan2(q2, q3)

Five-membered rings have Q=q2 and no q3 or theta. Phi is normalized to [0, 360) or [0, 2π); theta to [0, 180] or [0, π]. Starting-atom changes, traversal reversals, and reflections alter angular conventions. Proper rigid rotations and translations do not.

Undefined angles are represented by NaN: phi for a planar ring or pure chair, theta for a planar ring. Zero amplitude is different from an undefined mean plane: collapsed or collinear coordinates can make the plane degenerate and raise ValueError.

Canonical pucker names are positional

Six-membered classification uses 38 CarPpy reference vectors of three transformed diagonal dihedrals. Its carppy_theta is a three-component vector, not the scalar CP polar theta. Its reference distance is Euclidean distance in that three-angle space, in degrees.

For the standard oxygen-first six-membered order, labels use 1–5 for the carbon positions after O and 6 for O. For an aldopyranose these coincide with C1–C5. For a ketose, they describe ring positions rather than chemical carbon numbering. The sphere plot writes O instead of 6 in its ideal-position annotations.

Five-membered labels use positions 0–4 in supplied ring order and nearest envelope/twist phase. Their distance is the shortest wrapped phase difference in degrees. Do not compare the five- and six-membered distances as if they were the same metric.

planar indicates amplitude below the configured tolerance. unassigned means the closest reference exceeded max_distance; nearest_label and the nearest family remain available. These are shape classifications, not energy estimates, proof of stability, or population measurements.

See Puckering for synthetic examples that reproduce known coordinates and demonstrate rejection tolerances.

Torsion definitions

StateEditor.get_dihedral, four-atom measure/measure_internal calls, and glycan torsions use the same signed convention. For coordinates a, b, c, d, let u be the unit vector from b toward c, and project the two terminal vectors onto the plane perpendicular to u:

u = (c - b) / norm(c - b)
v = (a - b) - dot(a - b, u) * u
w = (d - c) - dot(d - c, u) * u
dihedral = atan2(dot(cross(u, v), w), dot(v, w))

Convert the result to degrees for StateEditor; its range is [-180, 180]. Positive angles follow a right-handed rotation from v toward w about u. For a=(0,1,0), b=(0,0,0), c=(1,0,0), and d=(1,0,1), the result is +90°. Reflecting all z coordinates changes it to −90°; a rigid translation or proper rotation preserves it. Reversing the entire four-atom order also preserves the angle. Exact 0° and ±180° are valid; coincident central atoms or collinear triples make a torsion undefined and raise ValueError.

The legacy StateEditor sign has been corrected to this convention, including a translation-dependent sign bug. Glycan and ring-analysis conventions are unchanged. For saved legacy measurements, recompute from coordinates rather than assuming every value needs only a sign flip. The interactive geometry tutorial demonstrates the corrected sign and translation invariance.

Glycosidic phi is donor ring O–anomeric C–linking O–acceptor C. Psi continues through the preceding acceptor backbone carbon, using its ring O for an anomeric acceptor. Terminal-carbon glycosidic omega is linking O–terminal C–ring C–ring O. Hydroxymethyl backbone omega lists those four atoms in the reverse order.

Always compare the reported atom_indices quadruplets as well as angle names. “Phi,” “psi,” and “omega” do not by themselves establish a universal definition across programs. Backbone omega is None for missing or ambiguous terminal oxygens; a glycosidic omega key is absent when that linkage has no corresponding terminal-carbon torsion.

Periodic boundaries and trajectories

Puckering, RMSD, and glycan torsion routines do not apply periodic-boundary corrections. Supply whole, unwrapped molecules or rings. Atoms split across a cell boundary may look far apart, break bond detection, or generate meaningless geometrical values even if all entries are finite.

Trajectory assignments are fixed at the reference/first frame. They are appropriate for a consistent atom ordering and topology, not a reactive trajectory that changes connectivity. Coordinate generators are consumed once; results retain the numeric analysis rows but not every input geometry. Space.from_xyz instead loads every coordinate frame into memory.

Glycan.from_file uses the last XYZ/CP2K frame. Space.from_xyz loads all frames. Automatic trajectory detection uses the first frame. Choose the entry point deliberately when a file contains more than one geometry.

Counts and free energy on the sphere

Plot.cremer_pople_sphere pools one count per valid row into (phi, theta) angular bins. The displayed map has longitude 180° − phi and latitude 90° − theta. Histograms are stored in (latitude, longitude) order; stored edges are radians. Five-membered rings cannot use this projection.

Pure chairs contribute to a pole using arbitrary phase 180°; planar and other undefined-angle frames are omitted. Each valid frame receives equal weight, regardless of time spacing, frame order, or dataset length. Longer datasets therefore contribute more counts when pooled.

The default map computes ΔG = −R T ln(N/Nmax) using R=8.314 J/(mol K). Empty bins are masked, and the most populated bin is zero. This is free energy per angular cell, without spherical-area correction or reweighting. Interpolated drawing grids affect only rendering; conformer_counts and free_energy keep the original bin resolution.

A reference library or biased/unequally sampled collection does not automatically represent equilibrium populations. Use quantity="counts" for a descriptive view of such data. See Trajectories for plotting and export examples.

RMSD and clustering

Aligned RMSD uses translation removal and a proper Kabsch rotation. It does not allow reflections or symmetry-based atom permutations. The fit and distance use the same atom selection. Single-pair rmsd defaults to all atoms; pairwise matrices and clustering default to heavy atoms.

Clustering uses SciPy hierarchical linkage on condensed RMSD distances. All cluster indices refer back to original inputs; energy-excluded labels are -1. With complete finite energies, representatives minimize the chosen energy attribute. Otherwise they minimize summed within-cluster RMSD (medoids). energy=None explicitly selects medoids.

The complete distance matrix is quadratic in the number of inputs and is calculated before energy filtering. Duplicate removal uses complete linkage, ensuring every pair in a duplicate group is within the threshold. Neither clustering nor duplicate removal changes coordinates or reorders the source Space.

Reference-data provenance

The four bundled carbohydrate fixtures come from the CarPpy benchmark set at commit 4589b228cf8772b0f2bd6ccae8bb2f41ad1e7d70. The coordinates and atom order are retained; XYZ comment lines record source paths. glucose_puckers.xyz concatenates 38 reference conformations in source-path order and is not a molecular dynamics trajectory.

The repository's tests/data/README.md documents upstream paths and algorithm provenance. The adaptation adds matmalib object integration, fixed trajectory assignments, ambiguity checks, supported five-membered phase classification, medoid selection, and complete-linkage duplicate removal. CarPpy is not required at runtime. Source tests verify reference atom assignments, all 38 canonical labels, stereochemistry, torsions, cluster behavior, and SNFG drawing geometry.