Data Flow & Runtime Architecture
Loading:
OrbitronServices::loader()wraps the IO pipeline (io/pipelines/src/lib.rs) to parse source files intoSceneGraphinstances. The loader records provenance tags and infers covalent bonds viaorbitron_backbone::infer_covalent_bonds.The unit is a
Study, not a file.LoaderService::opentakes one source or many and returns aStudy(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)andopen(&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.Bundle format (
core/orbpack): the canonical document, the.orbpackcontainer, and the conversion to aSceneGraph. Split out ofio/pipelinesbecause that crate carries HDF5, memory mapping,directoriesandclapand can never build forwasm32, while the browser viewer has to read bundles. Parsing source files, the on-disk cache, and writing bundles stay inio/pipelines, where those dependencies belong.io/pipelinesre-exports the crate, socrate::canonical::…paths are unchanged.Scene Backbone:
SceneGraph(immutable, persistent) stores snapshots of atoms, bonds, trajectories, metadata, parsed electronic-structure evidence, and an optional editableMolecularElectronicState. The latter records builder charge and multiplicity without rewriting results parsed from a calculation. The GUI and CLI work againstSceneGraphplus derived render data (RenderSceneData).Query & Selection: Expressions parsed by
orbitron-query::parse_expressionare evaluated viaSelectionPrograminsideorbitron-selection-engine. Cached outputs and selection scoring drive the viewer highlights and CLI results.Rendering:
orbitron-render::RenderertranslatesRenderSceneDatainto GPU draw commands (instanced atoms/bonds, text overlays). Camera control lives inui/shell/src/camera.rs, but the renderer crate is UI-agnostic.Services Layer:
OrbitronServicescoordinates 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 fromio/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.Editing:
orbitron-editwraps aSceneGraphin anEditableSceneand appliesEditCommands against it, keeping the undo/redo stacks the desktop exposes. Itsgeometry/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.rsimports 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.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.External APIs: Downstream tools integrate via
OrbitronServices(Rust) or the Python bridge (Orbitronclass). 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.