Core Crates
A selective deep-dive: of the 19 crates under core/, this section covers the seven a contributor touches most (backbone, query, selection-engine, render, edit, forcefield, periodic). Repository Layout lists them all in one line each, and Services Layer covers core/services.
5.1 Backbone (core/backbone/src/lib.rs)
- Defines newtype identifiers (
AtomId,BondId,FrameId,PropertyId) and element metadata (periodicmodule) used across the workspace. SceneBuilderconstructs snapshots with atoms, bonds, metadata, editableMolecularElectronicState, and derived data (electronic structure, vibrational modes, thermochemistry). The molecular state belongs to the current structure; parsedElectronicStructureremains evidence from the source calculation.SceneGraphwraps the snapshot with provenance hashing (SceneDigest) for change detection.PropertyRegistrystores globally registered per-atom or per-scene properties, enabling dynamic queries and render overlays.- Exports helpers such as
infer_covalent_bonds,AtomPopulation,FrequencyData,Trajectory, andUnitCell. Loader and renderer crates consume these types.
5.2 Query & Selection (core/query, core/selection-engine)
core/queryprovides the selection expression enum, parser, and evaluator. Supported primitives include element filters (element O, bare symbols,atomic_number == Z), distance shells, angle windows, nearest-neighbour queries, property comparisons, and residue terms (chain A,resname HIS,resid 42), and retained alternate locations (altloc B).- Residue terms read the same accessors as the grouping. There is no residue entity in the scene graph — a residue is a view over per-atom PDB/mmCIF annotation — and
orbitron_backbone::residuesis the one definition of(chain, seq, insertion code). Both the selection evaluator and any panel that reports a residue go throughResidueProperties, so they cannot come to disagree about whatHIS 42means. The insertion code is part of the identity: an antibody numbered 100, 100A, 100B is three residues, and dropping it merges them. The Scene panel’s Coordination readout is the other consumer: it names a metal’s site (Zn C1) and its donors (via HIS A1 NE, …) through the same accessors, and caches the formatted strings on the scene digest — resolving a donor id costs a lookup, and the panel redraws sixty times a second for text that only changes when the structure does. - The residue view also retains mmCIF label-chain and label-sequence identifiers, label-component identifiers, named alternate locations, and source atom IDs.
_chem_compdefinitions supply controlled component type, name, formula, mass, and standard parent identity.ResidueKindandResidue::one_letter_codesupply the compact protein/nucleic-acid labels used by the desktop navigator. Modified peptide and nucleic-acid monomers use their source type and parent, while unknown,peptide-like, and non-polymer components remainOtherrather than being guessed into a polymer sequence. Parsers store coordinate-independentDeclaredResiduerows underpdb:polymer_sequence.residue_sequencejoins them to observed residues by mmCIF label identity first and author identity second, then emits atom-free unresolved entries for unmatched source rows. This also keeps non-standard declared monomers in their polymer chain. The navigator caches the joined model by scene digest and emitsSelectionPanelAction::ApplyAtomSet, so it shares the canonical viewport selection. Per-digest egui memory retains the residue query and focused identity. The latest still-selected atom inselection_historysupplies a one-shot scroll target; recording the followed atom prevents the panel from snapping back on every frame. A second digest-keyed cache joinspdb:atom_namevalues to residue ids once per scene for live filtering. Search terms are ANDed; qualified author sites are exact, while plain residue and atom terms support partial matching. ResiduePropertiesalso owns alternate-location access. Bond inference uses it to reject contacts between different named locations in the same residue, while blank-location atoms remain compatible with every conformer.alternate_location_choicesandpreview_alternate_location_editinorbitron-editkeep alternate-location mutation residue-local. Keep-only removes other named conformers and clears the retainedpdb:alt_locvalues; delete removes only the selected conformer. Both preserve shared blank atoms, report incident and cross-residue bonds, reject stale previews, and restore deleted atoms, bonds, and property values exactly on Undo.water_ion_cleanup_selectiongroups candidates through the shared residue model and uses the query crate’s whole-residue, minimum-image contact search for Within/Beyond filters. Classification is conservative: named water must have water-site composition, while an ion must be monatomic and its component identity must agree with its metal or halide element. The preview pins exact residue, atom, charge, and bond removal before one undoable command.- Shared structure analyses live beside the selection evaluator in
core/query: residue contacts, ligand and chain interfaces, explicit-H hydrogen bonds, named salt bridges, disulfides, and steric clashes.steric_clashes_excludingreturns deterministic worst-first pair records with distance, the limit at 80% of the summed van der Waals radii, and positive overlap. It excludes bonded and 1-3 pairs, applies caller-supplied alternate-location exclusions, and uses Cartesian or periodic candidate bins before the exact distance test. The residue-mutation preview consumes these records rather than carrying a second clash implementation. ramachandran_residues_excludingbuilds complete protein triplets from the same residue model, converts the shared math crate’s dihedral sign to the PDB/CCTBX phi/psi convention, and unwraps periodic coordinates one backbone leg at a time. It bilinearly interpolates six Richardson Lab Top8000 grids bundled undercore/query/data/ramachandran/. The data directory pins the upstream commit, CC BY 4.0 license, binary layout, and regeneration command. Callers supply hidden alternate-location atoms; the result records residue identity, visible residue atoms, the five defining backbone atoms, reference class, angles, score, and favored/allowed/outlier category.missing_side_chain_residues_excludingcompares each retained amino-acid conformer with the expected heavy side-chain atom names from Orbitron’s standard residue templates. A retained CA atom distinguishes a coordinate-bearing residue from an unresolved entry or an isolated named donor. The result records residue and conformer identity, visible atom IDs, and missing atom names. It ignores backbone atoms and hydrogens, maps common protonation variants to their parent template, supports MSE and SEC, and omits residues without a known complete template. Caller-supplied exclusions keep the result aligned with the active alternate-location view.rotamer_residues_excludingmeasures CCTBX-defined chi angles for complete rotamer-bearing amino-acid side chains and unwraps each path in periodic structures. It interpolates 17 sparse Richardson Lab Top8000 grids bundled undercore/query/data/rotamer/; the data directory pins the upstream commit, CC BY 4.0 license, binary layout, and regeneration command. The result records residue and conformer identity, visible residue atoms, every chi-defining atom quartet, angles, score, and favored/allowed/outlier category. Callers supply alternate-location exclusions through the same interface used by the other structure analyses.- Primitives combine through the
And/Or/NotAST variants, plusWithinSelection(thewithin <R> of <selection>operator, evaluated as the set of atoms within the radius of any anchor matched by the sub-selection).parse_expression(core/query/src/query/parsing.rs) is a two-layer parser: a lexer keeps function-call parens and quoted property names inside one primitive token, and a recursive-descent layer handles the boolean operators, thewithin … ofprefix, and grouping (not>and>or). Element symbols resolve toAtomicNumberviaorbitron_backbone::atomic_number_for_symbol, so evaluation and formatting reuse the existing atomic-number path.PropertyComparecarries aCompareOp(>,>=,<,<=,==,!=). parse_expressionreturnsSelectionExprASTs; the UI’s command palette and CLI subcommands rely on it to turn input strings into programs.evaluate_selectionresolves expressions against aSceneGraph. Errors are surfaced viaQueryError(UnknownProperty,NonNumericProperty,Evaluation).core/selection-engine::SelectionProgramwraps expressions with digest-aware caching and optional scoring metadata (SelectionScore). This crate is responsible for keeping UI selection interactions performant.
5.3 Rendering Core (core/render)
Renderer::newinitialises a WGPU surface for awinit::window::Window. Headless rendering (headlessmodule) enables CLI exports without a window.RenderSceneDataaggregates instanced atoms, bonds, and labels ready for GPU upload. Helper functions (pick_atom,distance_between) are used by the viewer for hit-testing.- Lighting presets live in
lighting.rs;set_colorblind_safe(incore/render/src/lib.rs) toggles the Okabe–Ito palette globally. - Bonds are rendered as instanced quads with per-instance thickness, dash, and glossiness.
BondInstance::orderplusorbitron_viewer_core::render_styles::apply_theme_styles(shared by desktop + CLI;ui/shell/src/util/render_styles.rsis a re-export shim) expand double/triple/quad bonds into multiple lanes using theme-provided spacing and highlight scaling. - Mesh pipelines (
mesh::MeshRenderPipeline) handle GPU buffer management; renderer crates are the only place WGPU appears, keeping other crates backend-agnostic.
5.3.1 Embedding Orbitron Renderer (EmbeddedRenderer)
You can host Orbitron’s GPU renderer inside your own application window without using the egui UI shell. This is useful for Rust hosts (Tauri, winit, native desktop apps) that want to reuse Orbitron’s rendering pipeline.
Prerequisites
- Rust toolchain from
rust-toolchain.toml(or newer). - Access to a
SceneGraph(load viaorbitron-io-pipelines::load_scene, or viaOrbitronServices, or construct usingSceneBuilder).
Minimal integration
orbitron_render::EmbeddedRenderer wraps the renderer with a synchronous API. For a full runnable reference see examples/sdk/ (Rust SDK integration) and examples/web-embedding/ (WASM viewer).
The core steps are:
- Create an
EmbeddedRendererfrom your window. The constructors borrow the window (EmbeddedRenderer::new(&window)/new_async(&window)/with_mode_async(&window, mode)), so the window must outlive the renderer. - Call
prepare_scenewhenever the scene or highlight selection changes. - Call
render_preparedin your redraw loop with yourCamera.
Under winit 0.30 the event loop is driven by ApplicationHandler + run_app (there is no EventLoop::run closure, WindowBuilder, or Event::RedrawRequested anymore), and a window created in resumed() has to outlive a borrowed renderer stored beside it. The maintained reference for that pattern is the desktop shell (ui/shell/src/runner.rs), which owns the window as an Arc<Window> and builds the lower-level renderer via Renderer::new_owned for a 'static surface. For a headless SDK integration (no window/event loop), see examples/sdk/basic.rs.
5.4 Editing Engine (core/edit)
- Provides the edit-mode foundation:
EditableScene,EditCommandimplementations, ID helpers, and the geometry engine behind the molecular builder. command/holds the high-level actions, grouped by target (atom_commands.rs,bond_commands.rs,fragment_commands.rs,geometry_commands.rs,hydrogen_commands.rs,electronic_state_commands.rs,residue_commands.rs,residue_state_commands.rs,residue_state_definitions.rs,disulfide_commands.rs,disulfide_annotations.rs,terminal_cap_commands.rs,conformer_commands.rs,perception_commands.rs,wrap_commands.rs,cluster_commands.rs,cell_commands/), with theEditCommandtrait itself incommand/edit_command.rs.ops.rsexecutes mutations against editable scenes, ensuring invariants such as bond symmetry and selection history updates.- The viewer’s Edit Mode panels (
ui/shell/src/edit) invoke these commands viarun_edit_command_with_feedback, emitting undo/redo stacks and error toasts.
geometry/ — the builder. The pattern throughout is a pure planner plus a thin command: the planner takes coordinates and returns what should change, so it is testable without a scene, and the command applies the plan and reports it. plan_clean_geometry / CleanGeometryCommand is the reference example.
| Module | Role |
|---|---|
build_template.rs |
The nine BuildGeometry shapes, their substituent directions, AttachmentSites (non-empty only for the two five-coordinate shapes), and the staggering twist used when growing onto an existing atom |
ring.rs |
carbocycle(size) for MIN_RING..=MAX_RING (3–8): polygon, pucker, cap, then idealize_in_place, so a placed ring and a cleaned one agree by construction |
clean.rs |
plan_clean_geometry — angles, then coordination spheres, then the point-group fit, each gated by CleanGeometryOptions |
idealize.rs |
The Gauss–Seidel distance-constraint solver seeded at current coordinates. ANGLE_STIFFNESS = 0.1 makes a bond about ten times stiffer than an angle, which is why PASSES is 2000 |
cluster.rs |
plan_cluster_model — cutting a metal site out as a cluster model for a QM calculation. One rule does both cuts: grow outward from each donor and stop at TRUNCATION_STOP_ATOMS, so a histidine keeps its imidazole plus CB and a backbone carbonyl keeps the peptide unit, with no table of twenty residues. Takes a distance shell as well as the bond list, because a metal–ligand contact is longer than covalent radii reach and a catalytic water would otherwise be dropped |
sphere.rs, sphere_assessment.rs, shape_measure.rs |
Continuous shape measures against reference polyhedra, and the SphereVerdict the Scene panel reports |
coordination_template.rs |
Coordination geometry and Shannon-radius reach per element and oxidation state |
embed.rs, graph.rs, stereo.rs |
3D coordinates from a flat connection table, and handedness preservation / inverted-stereocentre repair |
conformer.rs |
Deterministic bounded torsion sampling, UFF relaxation/ranking, stereochemistry checks, and heavy-atom aligned-RMSD deduplication |
attach.rs, donors.rs, ops.rs, math.rs |
Ligand attachment, donor suggestion, and shared helpers |
smiles.rs sits beside geometry/. It converts Yowl’s parsed graph into an explicit-H SceneGraph or SmilesFragment, assigns molecular charge, and invokes the same 3D embedding path when requested. Unsupported stereochemistry, query syntax, maps, and metals are boundary errors. command/residue_commands.rs consumes the pinned CCD-derived templates in core/edit/data/standard-amino-acids.json; backbone identity and coordinates remain stable while side-chain atoms are replaced. command/residue_rotamers.rs reads the CC BY 4.0 Top8000 derivative under core/edit/data/rotamer/. It selects a smoothed 20° phi/psi bin, or a declared backbone-independent fallback when phi/psi cannot be measured, and supplies the named chi-angle candidates used by residue_preview.rs. The preview keeps the existing exact candidate application and undo transaction. Clash-free rows follow local library probability; clashing rows follow summed squared overlap and then probability. command/side_chain_repair.rs wraps that mutation path for a same-component repair. It requires a positive missing-side-chain finding, refuses alternate locations, ambiguous protonation aliases, active SSBOND endpoints, and any side-chain bond crossing the residue boundary, then ranks complete candidates by clash-free status and minimum-image RMS displacement from existing heavy side-chain atoms. The detached validation reports missing atoms, source atoms replaced, explicit hydrogens removed, formal charge, and clash scores before and after. RepairSideChainCommand retains the preview’s materialized source digest and delegates exact candidate application and undo to the existing mutation transaction. command/terminal_cap_commands.rs builds undoable heavy-atom ACE/NME caps from the shared protein_termini query. Its preview digest uses the materialized EditableScene representation because entering edit mode turns lazy inferred bonds into explicit session topology; comparing against the pre-session graph would reject an unchanged PDB preview as stale. command/residue_state_definitions.rs defines the supported ASP/ASH, GLU/GLH, CYS/CYM, and LYS/LYN hydrogen, charge, and bond-order patterns. The planner in residue_state_commands.rs materializes inferred bonds before recording its source digest and returns a detached scene plus residue and molecular charge changes. SetResidueProtonationCommand stores only the affected residue atoms and incident bonds for exact Apply, Undo, and Redo. Retained heavy-atom IDs and coordinates do not change; generated hydrogens use the shared approximate hydrogen placement code and stripped experimental/computed properties. command/disulfide_commands.rs plans explicit bridge creation and cleavage from two annotated CYS/CYX residues. Creation is bounded to a 1.7–2.5 Å minimum-image SG-SG distance and never moves heavy atoms. Cleavage creates two approximate thiol hydrogens. The command stores residue-local atoms, incident bonds, and the active SSBOND metadata string for exact Apply, Undo, and Redo. disulfide_annotations.rs is the one writer for pdb:ssbond_pairs; residue mutation uses the same helper when it removes a cysteine endpoint. Edited bond properties identify the live connection as disulf, while imported raw pdb:struct_conn data remains unchanged source provenance.
5.5 Force Field (core/forcefield)
A self-contained UFF implementation, split out of core/edit so the geometry planner and the minimiser stay independently testable. It is what Relax Geometry runs.
params.rsholds the UFF parameter table;typing.rsassigns atom types from geometry.- All five terms are present, each in its own module:
bond.rs(stretch),angle.rs(bend, including the periodic form metals need),torsion.rs(dispatching on hybridisation across all six cases),inversion.rs, andvdw.rs. topology.rsbuilds molecular or explicit-image periodic interaction graphs;system.rsevaluates them;minimise.rsruns the minimisation. Every analytic gradient is checked against a numerical one in the crate’s tests.
Van der Waals has two entry points, and the difference matters. vdw_energy is the bare Lennard-Jones with no cutoff. vdw_energy_switched tapers it to zero between VDW_TAPER_START (10 Å) and VDW_CUTOFF (12 Å) using the quintic S = 1 − 6x⁵ + 15x⁴ − 10x³, which has zero first and second derivative at both ends — a C² energy and a C¹ gradient, which is what a line search needs. A bare truncation steps the potential and a shifted-force form distorts it everywhere; both were rejected for those reasons. Below 10 Å the two functions agree exactly.
The 12 Å radius comes from the table rather than convention: UFF’s deepest pair is Fr–Fr at x1 = 4.9 Å, retaining 2.75% of its well depth at 10 Å and 0.92% at 12 Å, with ordinary organics at 0.37% and 0.12%. A test pins both figures.
The non-bonded pair list is bounded by distance as well as by connectivity. It used to hold every pair more than two bonds apart, which was quadratic and eagerly allocated — 800 MB at ten thousand atoms. A uniform grid now bounds it by VDW_CUTOFF + VDW_SKIN, so the count follows density. The topological exclusion is unchanged and still comes first: a 1-3 pair stays excluded however far its angle opens.
Fixed-cell periodic minimisation uses explicit lattice images in all five terms. Each interaction participant is an atom index plus an integer (a, b, c) image. Directed bond images compose into angles, torsions and inversions; gradients from every occurrence return to the one base-atom coordinate. This represents self-image bonds and several bonded images of one atom pair, which a minimum-image shortcut cannot.
Nonbonded terms enumerate one half-space of image shells to the 12 Å cutoff plus skin. Their 1-2 and 1-3 exclusions are a depth-two walk over (atom, accumulated image) states, so only the bonded image is excluded. A Cartesian grid bounds candidate work by density. Slab axes marked non-periodic are neither folded nor replicated, and singular cells fail explicitly.
System::new remains the molecular API; System::new_periodic is the fallible fixed-cell entry point. BondRecord is unchanged because it cannot distinguish two images of the same atom pair. Cross-face contacts are inferred internally and have single order. Preserving an aromatic or multiple bond through a face would require parser-supplied image-bearing topology. The implementation contract and validation evidence are in notes/periodic-minimisation-plan.md.
Relax entrenches the geometry it is given — it finds the nearest local minimum. Clean (core/edit/src/geometry/clean.rs) moves a structure onto what its connectivity implies instead. Keeping those two distinct is the load-bearing design decision in the builder; see notes/archive/PROJECT_PLAN-edit-builder.md for the reasoning.
5.6 Reciprocal-Space Analysis (core/periodic)
orbitron-periodic converts a canonical BandStructure plus its calculation cell into one ReciprocalScene shared by every presentation surface.
orbitron-symmetry::first_brillouin_zoneconstructs the exact Wigner-Seitz cell of the physical reciprocal lattice, including the2πfactor.ReciprocalScene::from_bandfolds every parsed sample into that zone while retaining its source index. A mesh remains independent points.- Declared paths are split at zone boundaries, so a renderer cannot draw a false chord across opposite faces.
projection.rssupplies the common orthographic projection used by the desktop painter and SVG/PNG exporters.
The crate owns geometry and selection state, not widgets. Desktop controls live in ui/shell/src/panels/analysis/bands_dos/brillouin.rs; the TUI summarizes the same scene; Python converts it to plain containers; the WASM custom element uses the same indexed zone and path records.