Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Data Flow

Overview

                       ┌──────────────┐
 PDB / mmCIF / BCIF ──>│              ├──> Vec<MoleculeEntity>
 MRC / CCP4         ──>│   Adapters   ├──> Density (wraps VoxelGrid)
 DCD                ──>│              ├──> Vec<DcdFrame>
                       └──────┬───────┘
                              │
                              v
                  ┌───────────────────────┐
                  │       Assembly        │
                  │  (entities + opt-in   │
                  │   ss + connections)   │
                  └──┬────────┬────────┬──┘
                     │        │        │
                     v        v        v
              ┌──────────┐ ┌──────────┐ ┌───────────┐
              │ Analysis │ │Transform │ │   Wire    │
              │          │ │          │ │           │
              │ dssp     │ │ kabsch   │ │ assembly  │
              │ bonds    │ │ align    │ │  bytes    │
              │ disulfide│ │ rmsd     │ │    +      │
              │ sasa     │ │          │ │  delta    │
              └──────────┘ └──────────┘ └─────┬─────┘
                                              │
                                              v
                                     FFI / IPC / Python

Analysis, Transform, and Wire are independent; use any combination depending on what you need.

1. Parsing

Every structure adapter returns Vec<MoleculeEntity>:

let entities = Assembly::from_file(Path::new("1ubq.pdb"))?.into_entities();
let entities = Assembly::from_file(Path::new("3nez.cif"))?.into_entities(); // mmCIF by extension
// BinaryCIF parses from bytes (no path-taking entry point):
let bytes = std::fs::read("1ubq.bcif")?;
let entities = Assembly::from_bcif(&bytes)?.into_entities();

Density and trajectory adapters return their own types:

let density = mrc_file_to_density(Path::new("emd_1234.map"))?;
let frames = dcd_file_to_frames(Path::new("trajectory.dcd"))?;

2. Entity construction

Each parser tokenizes its input and pushes one AtomRow per atom into an EntityBuilder. EntityBuilder is the single point of classification: it groups rows by chain plus residue scope, joins mmCIF _entity / _entity_poly hints when present, and emits one MoleculeEntity per logical molecule (protein chain, NA chain, ligand instance, water bulk, solvent bulk) at finish(). Each emitted entity carries a freshly allocated EntityId.

For NMR ensembles or multi-model trajectories, the adapter-level *_to_all_models entry points (pdb_str_to_all_models, mmcif_str_to_all_models, bcif_to_all_models, plus the matching _file_* variants) return one Vec<MoleculeEntity> per MODEL.

3. Analysis

use molex::{detect_disulfides, Assembly};
use molex::analysis::{infer_bonds, DEFAULT_TOLERANCE};

// Secondary structure is opt-in: build, then recompute.
let mut assembly = Assembly::new(entities);
assembly.recompute_ss();
let ss = assembly.ss_types(entity_id);

// Disulfide + backbone-H-bond geometry is computed on demand for
// rendering, not stored on the Assembly:
let connections = assembly.detect_fallback_connections();

// Or call the building blocks directly:
let bonds      = infer_bonds(atoms, DEFAULT_TOLERANCE);   // distance-based
let disulfides = detect_disulfides(&entities);             // CYS SG-SG

4. Transforms

molex::ops exposes Kabsch alignment and superposition RMSD; nothing else lives in the transform surface.

use molex::ops::kabsch_alignment;
use molex::ops::transform::rmsd;

let aligned = kabsch_alignment(&reference, &target); // Option<(Mat3, Vec3)>
let deviation = rmsd(&a, &b);                         // Option<f32>

5. Serialization

For sending to C/C++/Python consumers, assembly_bytes is the only public wire entry point (it serializes a raw entity slice). Decode with Assembly::from_bytes, which returns a secondary-structure-free assembly; call recompute_ss() if you need SS.

use molex::ops::wire::assembly_bytes;

let bytes = assembly_bytes(&entities)?;
let mut assembly = molex::Assembly::from_bytes(&bytes)?; // ss_types empty
assembly.recompute_ss();