Skip to content

Implement iter_chromatograms: wire up existing Idx TIC data; BPC/SRM need new decode work #21

Description

@Nathan-D-R

Companion to Sigilweaver/OpenMassSpecCore#1 (the shared mzML writer now emits <chromatogramList> whenever a SpectrumSource yields anything from iter_chromatograms, but the trait's default impl returns an empty iterator) and precedent-setting sibling Sigilweaver/OpenWRaw#9 (same gap, Waters side). Reader in crates/opensxraw/src/reader.rs has no iter_chromatograms override in its SpectrumSource impl (line 186), so it falls through to the empty default - TIC/BPC/SRM chromatograms are currently absent from every mzML file OpenSXRaw produces.

Unlike OpenWRaw's chroms.rs, there is no dedicated chromatogram stream/module here. But partial TIC data for a chromatogram is already decoded and sitting unused:

  • crates/opensxraw/src/raw/idx.rs: IdxRecord (line 31) already parses, per scan, a tic: f64 field (line 42) read from offset 0x12..0x1A of every 54-byte Idx record (line 68), plus retention_time_min: f32 from offset 0x0C (line 65). Both are stored on every element of Reader.idx_records: Vec<IdxRecord> (reader.rs line 43), which is already a public field populated for every opened file.
  • crates/opensxraw/src/reader.rs lines 334-337 explicitly declines to feed IdxRecord.tic into SpectrumRecord.total_ion_current per-spectrum, with a comment noting the Idx TIC (cps, physically calibrated) doesn't match sum(raw intensities) and would fail the conformance suite's rel_close check on that field. That reasoning is about the per-spectrum field, not the chromatogram use case - a TIC chromatogram (time_sec = retention_time_min * 60.0, intensity = tic, one point per Idx record) is exactly the shape ChromatogramRecord wants and requires no new raw-format decode work, only wiring.

What would need net-new work:

  • BPC (basepeak chromatogram): base_peak_mz/base_peak_intensity are hardcoded None in SpectrumRecord (reader.rs lines 340-341) - nothing decodes a per-scan base peak today. It's derivable as a byproduct of points_to_arrays (reader.rs line 167) during iter_spectra's existing scan-block decode (max-intensity point per scan), but that's new logic, not a wire-up of an existing field.
  • SRM (selected reaction monitoring): no Q1/Q3 transition-level data is decoded anywhere in this reader - IdxRecord's MS-level flag (raw/idx.rs line 66) is a single bit (MS1 vs MS2) with no channel/transition identifiers, and DdeRecord (raw/dde.rs) only carries DDA precursor m/z, not MRM transitions. SRM chromatogram support would require identifying and reverse-engineering new stream structure and is out of scope for this issue.

Proposed scope for this issue: implement Reader::iter_chromatograms to emit one TIC ChromatogramRecord (chromatogram_type = "total ion current chromatogram", precursor_mz/product_mz = None, time_sec/intensity built from idx_records), matching the openmassspec_core::ChromatogramRecord schema (src/types.rs ~line 163). BPC and SRM chromatograms should be tracked as separate follow-up issues if pursued, since they involve materially different amounts of new work.

Per this repo's clean-room policy (CONTRIBUTING.md, "Vendor software and clean-room policy"): the TIC values used here come only from bytes already parsed from the .wiff container by this project's own code; no comparison against Analyst/SCIEX OS/MultiQuant/msconvert output is in scope or acceptable for verifying this feature.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions