Structural analysis
Use selected coordinates for geometry and atom-contact analysis.
Geometry
The molframe.geometry module provides centroid, pairwise distance matrix, and RMSD functions. Inputs are coordinate arrays with shape (N, 3).
from molframe import geometry
ca = structure.select("name CA")
xyz = ca.to_coordinates()
centre = geometry.centroid(xyz)
distances = geometry.distance_matrix(xyz)
self_rmsd = geometry.rmsd(xyz, xyz)centroid() returns None for an empty coordinate set. RMSD compares rows by position: select and order equivalent atoms in both inputs before interpreting a result. Distances and RMSD are in Å.
Atom contacts
Use molframe.analysis.atom_contacts() to find atom pairs at or below a cutoff. It accepts a structure or selection and returns a ContactTable with first, second, and distance columns.
from molframe import analysis
protein = structure.select("protein")
contacts = analysis.atom_contacts(protein, cutoff=4.0)
print(len(contacts))
print(contacts.distance.shape)The cutoff is in Å. Contact counts depend strongly on alternate locations, model choice, solvent inclusion, and which atoms you pass. Make those choices explicit in a scientific workflow.
Chemistry provenance
Chemistry-dependent workflows use the native component-chemistry pipeline. Its report records the provider and coverage used to annotate the structure, atom roles and bonds that were applied, and provenance for the reference data. A missing component or incomplete provider coverage is reported as a diagnostic; MolFrame does not invent atom roles or bonds to fill the gap. Preserve the returned provenance with derived contacts, geometry, or rendered annotations so the result can be traced to the coordinate and chemistry inputs.
The public Python facade exposes chemistry operations through molframe.chemistry when the chemistry feature is enabled. The adapter's direct network boundary is separate: an already-known URL requires an authoritative SHA-256 digest and explicit size/timeout controls, while identifier acquisition is unavailable until an authoritative provider manifest exists.
Secondary structure
Automatic enrichment and explicit role-backed analysis now share one native DSSP 4 kernel. It returns AlphaHelix, ThreeTenHelix, PiHelix, PolyProline, BetaBridge, Strand, Turn, Bend and Coil; missing heavy backbone atoms, including carbonyl oxygen, yield Unknown. OtherHelix remains a distinct deposited-file state. Explicit analysis requires semantic polymer-role annotations and rejects ambiguous roles, rather than guessing names.
The classifier searches hydrogen bonds across chains within a model, retains each donor’s two strongest acceptors, rounds energies to 0.001 kcal/mol, and applies continuous peptide-span guards to local patterns. Beta ladders span supported bulges. Alpha helices require two consecutive four-turns; an occupied position rejects an entire three-ten stretch, and an accepted pi stretch may replace alpha. Polyproline-II requires at least three consecutive phi/psi windows centred at −75°/145° with inclusive ±29° limits, irrespective of residue name, and is assigned only to otherwise unassigned coil: it never overwrites turns or bends. This modern definition follows DSSP 4.
The native kernel is available from Rust:
use molframe_analysis::{secondary_structure, DsspOptions};
let options = DsspOptions::default();
let table = secondary_structure(structure.engine(), &options)?;
for (residue, kind) in table.placements() {
println!("{residue:?}: {kind:?}");
}Every read also carries a per-residue state and its source on the structure
(secondary_structure() and secondary_source()): the file's HELIX/SHEET or
struct_conf ranges with source File (the helix class picks α, 3₁₀, π or an
unnamed helix), and the automatic assignment with source Dssp, or CaOnly
for a Cα trace. Where both exist the file wins.
Native assignment needs no external executable. The optional explicit run_dssp adapter remains available for caller-selected DSSP 4 execution and typed mmCIF segment parsing; it never locates or downloads an executable.
Validation reference inputs
The validation kernels carry no built-in scientific reference. A reference
distribution, a rotamer profile, a set of plane restraints or a set of TLS
groups is data the caller supplies, and molframe reads it from JSON or TOML
(chosen by the file suffix, case-insensitively) with strict schemas: an unknown
key is an error. Failures are ValidationInputError, which names the field.
| Reader | Returns | Needs |
|---|---|---|
read_reference_library(path) | ReferenceLibrary | the file |
read_rotamer_profile(path) | RotamerProfile | the file |
read_plane_restraints(path, structure, policy) | Vec<PlaneRestraint> | a structure and the policy that reads its identifiers |
read_tls_groups(path, structure, policy) | Vec<TlsGroup> | a structure and the policy that reads its identifiers |
Keys equal the parameters of the constructors they feed.
# Reference library: a scalar histogram and a two-dimensional grid.
[library]
id = "bond-deviation"
version = "2026-10"
[[distribution]] # histogram: edges, one weight per interval
name = "c-n"
edges = [-0.1, 0.0, 0.1]
weights = [1.0, 3.0]
[[distribution]] # grid: weights are row-major, x outermost
name = "rama"
x_edges = [-180.0, 0.0, 180.0]
y_edges = [-180.0, 0.0, 180.0]
weights = [1.0, 2.0, 3.0, 4.0]# Rotamer profile: one component-local torsion per definition.
[profile]
id = "chi-wells"
version = "2026-10"
[[definition]]
component_id = "SER"
chi_index = 1 # one-based
atoms = ["N", "CA", "CB", "OG"] # CCD atom names defining the dihedral
distribution = "ser-chi1" # a histogram in the paired library# Plane restraints: unique ids, selections in the query language.
[[plane]]
id = "peptide-1"
selection = "resid 1:2 and name CA C O N"
# TLS groups: tensors are three rows of three numbers.
[[group]]
id = "A-1"
selection = "chain A"
origin = [0.0, 0.0, 0.0]
t = [[0.1, 0.0, 0.0], [0.0, 0.1, 0.0], [0.0, 0.0, 0.1]]
l = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]
s = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]A selection that matches no atom is refused: a restraint that silently covers
nothing would pass every structure. The policy argument decides which
identifier namespace chain A reads. The readers check shape, finiteness and
uniqueness; whether a TLS tensor is admissible, or a torsion path exists in the
dictionary, is decided by the validation kernel that consumes it.
Choosing a method
| Goal | API |
|---|---|
| Centre a selected coordinate set | geometry.centroid() |
| Inspect all pairwise distances in a small set | geometry.distance_matrix() |
| Compare already-corresponding coordinate rows | geometry.rmsd() |
| Find nearby atom pairs in a structure or selection | analysis.atom_contacts() |
For larger contact analyses, prefer passing a narrow selection to avoid doing work on atoms that cannot affect the answer.
Implementation and verification status
The native secondary-structure classifier was compared directly, without deposited-file precedence or alphabet collapse, with mkdssp 4.5.0 on the RCSB 1AON and 7QPD mmCIF files: 8015/8015 and 1544/1544 reference residues matched in exact H/G/I/P/E/B/T/S/blank state (100% each). Identity joins used author chain, residue number and insertion code, and checked component identity; no reference proteins were excluded. Native assignments for the 14 nonprotein 1AON residues and ten nonprotein 7QPD residues were Unknown. This is evidence for these fixtures, not universal byte-exact compatibility.
Input SHA-256: 1AON 6b202f340ffb9a1924d5315ce9e837e02cee1dbd745df675be76f6d4e1b8e66f; 7QPD 6cd4e30194caf887b75198e04e7e9afcce1445ec28aa331f6b38c8d323627104. Reference command: mkdssp --output-format=dssp INPUT OUTPUT with default minimum PPII stretch 3. Reference output SHA-256: 1AON 1f42dc9ca3b299eb7e624b293e37689023d08de975234f9bb22a6362ccebf483; 7QPD 16159bcb0f175e1a67c21fea8a04428f212222fb01866ae606861be2c52c4faf. The permanent native 1AON regression pins all 8015 author identities and exact states; tests also cover PPII geometry, stretch precedence, interchain bridges, bulge interiors and peptide breaks. The scientific rules were independently implemented; upstream DSSP source was consulted to establish reference conventions, not copied or adapted.
Other interaction analyses, performance and Python/browser round trips require their own evidence; the secondary-structure comparison does not validate those surfaces.