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.
Companion to Sigilweaver/OpenMassSpecCore#1 (the shared mzML writer now emits
<chromatogramList>whenever aSpectrumSourceyields anything fromiter_chromatograms, but the trait's default impl returns an empty iterator) and precedent-setting sibling Sigilweaver/OpenWRaw#9 (same gap, Waters side).Readerincrates/opensxraw/src/reader.rshas noiter_chromatogramsoverride in itsSpectrumSourceimpl (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, atic: f64field (line 42) read from offset0x12..0x1Aof every 54-byte Idx record (line 68), plusretention_time_min: f32from offset0x0C(line 65). Both are stored on every element ofReader.idx_records: Vec<IdxRecord>(reader.rs line 43), which is already a public field populated for every opened file.crates/opensxraw/src/reader.rslines 334-337 explicitly declines to feedIdxRecord.ticintoSpectrumRecord.total_ion_currentper-spectrum, with a comment noting the Idx TIC (cps, physically calibrated) doesn't matchsum(raw intensities)and would fail the conformance suite'srel_closecheck 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 shapeChromatogramRecordwants and requires no new raw-format decode work, only wiring.What would need net-new work:
base_peak_mz/base_peak_intensityare hardcodedNoneinSpectrumRecord(reader.rs lines 340-341) - nothing decodes a per-scan base peak today. It's derivable as a byproduct ofpoints_to_arrays(reader.rs line 167) duringiter_spectra's existing scan-block decode (max-intensity point per scan), but that's new logic, not a wire-up of an existing field.IdxRecord's MS-level flag (raw/idx.rsline 66) is a single bit (MS1 vs MS2) with no channel/transition identifiers, andDdeRecord(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_chromatogramsto emit one TICChromatogramRecord(chromatogram_type= "total ion current chromatogram",precursor_mz/product_mz=None,time_sec/intensitybuilt fromidx_records), matching theopenmassspec_core::ChromatogramRecordschema (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
.wiffcontainer by this project's own code; no comparison against Analyst/SCIEX OS/MultiQuant/msconvert output is in scope or acceptable for verifying this feature.