Data Flow & Runtime Architecture

  1. Loading: OrbitronServices::loader() wraps the IO pipeline (io/pipelines/src/lib.rs) to parse source files into SceneGraph instances. The loader records provenance tags and infers covalent bonds via orbitron_backbone::infer_covalent_bonds.

    The unit is a Study, not a file. LoaderService::open takes one source or many and returns a Study (core/services/src/study/): the members in the order the caller gave them, a task list spanning all of them, one member shown, and any warnings the sources raised about each other. open(path) and open(&paths) are the same call and a study of one behaves exactly as loading that file did. This exists because a resubmitted HPC job spans several outputs and because unrelated runs are often looked at together, and those turn out to be one structure — three tasks in one file and three tasks in three files read the same. Nothing merges the members’ structures. See Services Layer for the join rule, the grouping, and why member order comes from the caller rather than from mtime.

  2. Bundle format (core/orbpack): the canonical document, the .orbpack container, and the conversion to a SceneGraph. Split out of io/pipelines because that crate carries HDF5, memory mapping, directories and clap and can never build for wasm32, while the browser viewer has to read bundles. Parsing source files, the on-disk cache, and writing bundles stay in io/pipelines, where those dependencies belong. io/pipelines re-exports the crate, so crate::canonical::… paths are unchanged.

  3. Scene Backbone: SceneGraph (immutable, persistent) stores snapshots of atoms, bonds, trajectories, metadata, parsed electronic-structure evidence, and an optional editable MolecularElectronicState. The latter records builder charge and multiplicity without rewriting results parsed from a calculation. The GUI and CLI work against SceneGraph plus derived render data (RenderSceneData).

  4. Query & Selection: Expressions parsed by orbitron-query::parse_expression are evaluated via SelectionProgram inside orbitron-selection-engine. Cached outputs and selection scoring drive the viewer highlights and CLI results.

  5. Rendering: orbitron-render::Renderer translates RenderSceneData into GPU draw commands (instanced atoms/bonds, text overlays). Camera control lives in ui/shell/src/camera.rs, but the renderer crate is UI-agnostic.

  6. Services Layer: OrbitronServices coordinates loader/analyzer/exporter/renderer operations and abstracts data sources. It owns the generic load/analyze/export/render path and is the single front door for opening a file into a scene. Format-specific parsing (format sniffers, companion-file parsers, per-format run-summaries) is used directly from io/pipelines, which is a shared layer rather than a hidden internal; the desktop additionally keeps its own background streaming loader (ui/shell/.../path_loader.rs) for local files with progress/cancel.

  7. Editing: orbitron-edit wraps a SceneGraph in an EditableScene and applies EditCommands against it, keeping the undo/redo stacks the desktop exposes. Its geometry/ module is the molecular builder: build templates and generated rings for placement, a pure planner per geometry command, coordination-sphere assessment, 3D embedding from a flat connection table, bounded conformer search, and residue mutation. smiles.rs imports the supported SMILES subset through Yowl and returns an explicit-H scene or fragment. Minimisation is a separate crate, orbitron-forcefield (UFF), so the planner and the minimiser stay independently testable. Its fixed-cell periodic path carries explicit lattice images in every interaction while retaining one Cartesian coordinate per base atom.

  8. Frontends: The GUI viewer (ui/shell) embeds the renderer and services within an egui event loop (viewer_loop::ViewerLoop). The CLI and TUI use the same services for loading, analysis, and export, so a behaviour added in a core crate reaches all three.

  9. External APIs: Downstream tools integrate via OrbitronServices (Rust) or the Python bridge (Orbitron class). Core behavior is shared, but each frontend still owns command wiring, presentation, and error reporting. A new core feature therefore needs an explicit surface and test in every frontend that claims to expose it.

Binary scene and trajectory compatibility

SceneGraph::to_bytes and Trajectory::to_bytes use named MessagePack so adding a defaulted field does not shift positional data. Trajectory bytes begin with ORBITRON_TRAJECTORY_MSGPACK_V1\0; Trajectory::from_bytes retains a read-only fallback for the former bincode layout. New writers must not emit the legacy form.