Architecture (full)#
This page is the canonical architecture reference for MolSysViewer. It complements the short overview in Architecture. If you want a longer, implementation-oriented snapshot from the original devguide, see Architecture snapshot (2025-11).
Layers and responsibilities#
MolSysViewer is split into two runtime layers with a thin protocol between them.
Python layer (
molsysviewer/)Public API (
MolSysView), loaders, shapes APIs, regions/layers/whole.Owns the MolSysMT system and visibility masks.
Sends JSON-like messages to the frontend and stores a message history.
Exports HTML by replaying stored messages (standalone and docs-lite).
TypeScript/Mol* layer (
molsysviewer/js/src/)AnyWidget entrypoint, controller, handlers, and shape builders.
Owns the Mol* plugin, state tree, and WebGL rendering.
Applies representations, regions, layers, and shapes using Mol* internals.
Core data model#
MolSys payload schema (Python to JS)#
The payload is the stable contract when loading MolSysMT systems:
atoms: parallel arrays (atom_id,atom_name,residue_id,residue_name,chain_id,entity_id,element_symbol,formal_charge).structures: list, each with:coordinates: N x 3 array in Å.optional
box: three vectors in Å.optional
time: numeric value.
optional
bonds:indexA,indexB, optionalorder.
Do not reintroduce legacy names like positions or frames.
Message protocol#
Python sends operations as dictionaries:
{"op": "some_operation", "options": {...}}
The TypeScript union type ViewerMessage (molsysviewer/js/src/messages/viewer-messages.ts)
reflects the current contract.
JS to Python events#
The widget emits events back to Python via widget.on_msg:
ready: frontend initialized, pending messages flushed.region_ack,region_deletedlayer_ack,layer_deletedregistry_clearedcamera_snapshotjs_log(debug only)
Data flow#
MolSysMT native load#
You call
MolSysView.load(molecular_system, ...).MolSysMT converts to
molsysmt.MolSys.ViewerJSON is serialized into the MolSys payload.
Python sends
load_molsys_payload.TS builds Mol*
Topology,Coordinates,Trajectoryand applies a preset.The controller captures the structure and notifies state/trajectory handlers.
String/URL loads#
String, ID, and URL inputs are handled through MolSysMT in Python.
The Python layer sends load_molsys_payload for these inputs too.
Visibility model#
Python owns atom_mask (boolean per atom).
Python sends visible indices to TS.
TS computes hidden atoms and applies transparency via Mol* helpers.
Regions, layers, and whole#
Regions
A region is a structural subset identified by
tag.Python
Regionwraps a Mol* component plus its representations.JS tracks a region index and applies reps per region.
Layers
A layer is a tag-based group for non-structural visuals (shapes/overlays).
JS stores refs per tag and applies show/hide/delete to all refs under that tag.
Whole (global)
Wholecontrols the baseline/global representation for the full structure.show_global/hide_globaltarget eitherglobalonly orallreps.
Semantics to preserve
region.hide()remains hidden afterviewer.hide(); viewer.show().whole.hide()only affects the baseline/global reps, not regions.viewer.hide(selection=\"all\")hides all reps and masks;show()restores masks and re-applies the baseline visibility intent.
Shapes pipeline#
Python shape APIs normalize inputs and send
add_*operations.TS shape handlers delegate to Mol* shape builders under
molsysviewer/js/src/shapes/.Each shape registers refs under a tag to allow selective clear/hide.
Popup (popout) architecture#
The host stores a command log of Python → JS messages.
The popout initializes with the runtime (Blob or module URL).
The host sends initial sync (commands + camera + UI state), then streams ops.
Camera sync is bidirectional but only when the user is actively interacting.
Trajectory controls#
TS
TrajectoryHandlersmanages frame stepping and playback.The UI calls
step_trajectory,set_trajectory_frame,set_trajectory_playback.State is reflected in the on-canvas UI and in the popout mirror.
Implementation notes (detailed)#
This section preserves a more detailed implementation-oriented snapshot. It is useful when you need to match behavior to concrete message ops or debug a host↔frontend↔popup sync issue.
Python → JS operations (examples)#
You send actions as JSON-like dictionaries with an op field:
view._send({"op": "load_molsys_payload", "payload": payload, "label": label})
Common operations include:
Loading:
load_molsys_payloadload_structure_from_string(legacy path; prefer payloads when available)load_pdb_id,load_url(when delegating to Mol*)
Visibility:
update_visibilityshow_global,hide_global
Regions:
create_region,set_region_representationshow_region,hide_region,delete_region
Layers:
create_layer,show_layer,hide_layer,delete_layerset_layer_tag
Shapes:
add_*(sphere, spheres, pocket_surface, pocket_blob, channel_tube, …)
Reset/cleanup:
clear_all,clear_decorations,reset_viewer
The TypeScript union type ViewerMessage (molsysviewer/js/src/messages/viewer-messages.ts)
is the contract for the current set.
JS → Python events#
The widget emits events back to Python via widget.on_msg, including:
ready– frontend initialized; Python can flush pending messages.region_ack/region_deletedlayer_ack/layer_deletedregistry_clearedjs_log(debug only)
Regions & layers: semantics to preserve#
These semantics are user-visible and should remain stable:
region.hide()stays hidden afterviewer.hide(); viewer.show().whole.hide()only affects the baseline/global reps, not regions.viewer.hide(selection="all")hides all reps and masks;show()restores masks and re-applies the baseline visibility intent while respecting already-hidden regions.
Popup (popout) sync model#
The host keeps a command log of Python → JS messages.
The popout is initialized with the runtime (Blob or module URL for docs-lite).
The host sends an initial sync (commands + camera + UI state), then streams ops.
Camera sync is bidirectional but should only happen when the user is actively interacting (to avoid “camera fights”).