Skip to main content

Module projector

Module projector 

Source
Expand description

Instrument-dispatch P2: the projector.

Turns the vendor-neutral trunk (scalar PeptideScalar / IonScalar physics) into device-sampled signal, parameterised by the instrument’s sampling geometry and an absolute event timeline derived from the AcquisitionScheme. This replaces the two device-projection jobs that the legacy pipeline baked into the DB (frame_occurrence/abundance and scan_occurrence/abundance) with a render-time computation:

  • time projection (all instruments): the EMG RT profile integrated over each event’s true [start, end] interval — mscore’s project_emg_over_events (the corrected, non-fixed-cycle kernel).
  • mobility projection (IMS only): the ion mobility Gaussian sampled onto the scan grid via the existing gaussian kernels; for a non-IMS instrument (MobilityModality::None) the distribution is marginalised onto a single scan, conserving total signal.

P2 builds and verifies these projections in isolation. Wiring assemble_frames onto them (with a DB fallback) and the byte-parity proof are P3.

Structs§

EventSlot
One concrete acquisition event placed on the absolute run timeline, with its [start_s, end_s] exposure interval (the input to the time projection).
EventTimeline
The full run as an ordered list of EventSlots.
InstrumentConfig
The vendor-specific configuration the render core dispatches on (P6c). Bundles the three orthogonal axes that decide how a vendor-neutral trunk is recorded:
ProjectionParams
Parameters the projector needs to reproduce / improve the legacy distribution jobs. Defaults mirror the simulator’s config defaults (target_p=0.999, sampling_step_size=0.001, scan step 0.0001, n_steps=1000, remove_epsilon=1e-4).
RenderedSpectrum
A spectrum tagged with where it sits in the coordinate/intensity pipeline, so writers and the detector model never double-apply a transform.
SamplingGeometry
The instrument’s mobility sampling geometry. For Tims, inv_mobility holds the per-scan 1/K0 grid in ascending order (the order the gaussian occurrence kernel expects internally). project_mobility_ion returns scan indices as positions into this ascending vector; callers that need native (descending) Bruker scan numbers map at the device boundary.

Enums§

DistributionSource
Where the per-analyte occurrence/abundance distributions come from when constructing the builder entities (P4 canonical-state contract).
IntensityStage
Point on the intensity-conservation chain (mirrors the Python dispatch.IntensityStage; see plan §3.5).
MobilityModality
Ion-mobility separation modality. Only the cases the engine handles today are listed; DriftTube/Faims are reserved for later instruments.
MzCoordSpace
Which coordinate space a rendered spectrum’s m/z values are in.
ProjectionMode
Which projection math to use.
RenderedEvent
One acquisition event’s rendered signal. Scan for non-IMS instruments; MobilityFrame for IMS (preserving per-scan simultaneity rather than flattening + rebundling).

Functions§

project_mobility_accurate_par
Batched + parallel Accurate mobility projection over many ions sharing one ascending mobility grid. means/sigmas are per-ion 1/K0 mean+std. Returns one (ascending_scan_index, abundance) list per ion.
project_mobility_gaussian
Accurate mobility projection core: a Gaussian (mean, sigma) in 1/K0 onto an ascending mobility grid, returning (ascending_scan_index, abundance) where each occupied scan’s abundance is the CDF over that scan’s own midpoint-bounded bin (correct on non-uniform grids). σ ≤ 0 is a point mass at the nearest scan; empty/singleton grids are handled.
project_mobility_ion
Mobility projection for a single ion: (scan_index, abundance) over the geometry’s scan grid, scan indices being positions into the ascending geometry.inv_mobility (per the SamplingGeometry contract).
project_mobility_ion_legacy
LegacyCompat mobility projection for one ion: reproduce scan_occurrence/scan_abundance exactly as simulate_scan_distributions_with_variance did — calculate_scan_occurrence_ gaussian with n_lower/upper = 5, and calculate_abundance_gaussian over the fixed im_cycle_length bin. mean/sigma are the original stored 1/K0 mean + std at f64 (NOT a CCS round-trip). scan_mobilities must be ascending with scan_ids aligned (exactly as the legacy job feeds scans sorted so im_cycle_length > 0); a descending grid makes the occurrence kernel return nothing. The occurrence kernel’s indices are the values the legacy job stored directly, so they are returned as-is. Returns (scan, abundance).
project_mobility_legacy_par
Batched + parallel LegacyCompat scan projection over many ions (the kernels the legacy job used). means/sigmas are the original per-ion 1/K0 mean+std; scan_ids/scan_mobilities ascending+aligned (shared by all ions). Returns one (scan, abundance) list per ion. Requires positive sigmas (real data); use project_mobility_ion_legacy for the point-mass-guarded single- ion path.
project_time
Time projection: for each peptide, the (global_event_index, abundance) list over every acquisition event in the run (MS1 and MS2 alike), integrating the EMG over each event’s true [start, end] exposure interval. The index is the position in timeline.events (i.e. EventSlot::global_index), so MS2 events receive their own RT abundance rather than reusing the MS1 value — this matches the legacy frame_occurrence/frame_abundance, which span all frames.
project_time_legacy
LegacyCompat time projection: reproduce frame_occurrence/frame_abundance over the full frames table, exactly as simulate_frame_distributions_emg did. Inputs are taken at f64 (the precision the legacy pipeline used) — NOT the f32 trunk entities — so the result is bit-faithful: rt_mus, rt_sigmas, rt_lambdas are per-peptide EMG params (rt_mu, not the GRU apex); frame_ids/frame_times are the whole frames table ascending by id. Occurrence positions (1-indexed into frame_times) are translated to frame ids via frame_ids[pos-1]; the remove_epsilon filter drops frames whose abundance is <= remove_epsilon (matching the legacy job). Returns (frame_id, abundance) per peptide.