Implement SRM/PRM chromatogram traces for mzML export#30
Open
Nabejo wants to merge 1 commit into
Open
Conversation
Wire the remaining piece of iter_chromatograms scoped out of Sigilweaver#26: one SRM-shaped ChromatogramRecord ("selected reaction monitoring chromatogram", MS:1001473) per scheduled PrmTarget, built on top of the TIC/BPC traces Sigilweaver#26 already wired up. For each PrmTarget, walk every msms_type == 10 (prm-PASEF) frame, decode its peak payload via the same per-frame decode path iter_spectra already uses (Reader::decode_peaks), sum the decoded intensity restricted to that target's PrmFrameMsMsInfo scan-number range, and append one point per frame. A target with a genuine zero-intensity frame keeps that point (real data, unlike a frame missing a Frames column); a target absent from every PrmFrameMsMsInfo row is omitted rather than emitted with an empty trace, matching the TIC/BPC no-empty-chromatogram contract. precursor_mz is the target's scheduled PrmTargets.MonoisotopicMz. product_mz is left unset: prm-PASEF records a full fragment-ion scan per precursor rather than a discrete triple-quadrupole product-ion transition, and the TDF schema has no product-ion m/z field to report - populating one would mean inventing a value with no schema backing, which the clean-room policy in CONTRIBUTING.md rules out. New pure helpers (sum_intensity_in_range, build_srm_record) are unit tested directly; the frame-walking orchestration (srm_chromatograms_for) follows the same shape as the existing spectra_for_frame and isn't unit tested in isolation for the same reason that one isn't - it's thin glue over already-tested pieces and a live Reader/bundle. The existing cache-gated prm_pasef_pxd028279 test in tests/roundtrip.rs already exercises the metadata this relies on (PrmFrameMsMsInfo/PrmTargets shape) and continues to pass. Distinct from Sigilweaver#13 (prm-PASEF frames skipped in the mzML *spectrum* projection): that issue is about spectra, this is about the chromatogram trace. Addresses the remaining SRM/PRM scope of Sigilweaver#25 (TIC/BPC portion done in Sigilweaver#26). Claude-Session: https://claude.ai/code/session_018ijUinjq3SKNZXFNWqTTmV
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Issue #25 originally described three pieces of
iter_chromatogramswork (TIC, BPC, SRM/PRM). PR #26 already implemented and merged the TIC and BPC pieces, and the issue was retitled to track only the remaining SRM/PRM chromatogram work (it was also briefly auto-closed by an accidental "Closes #25" keyword match in #26's original commit message, then manually reopened for this remaining scope).This PR implements only that remaining SRM/PRM piece, built on top of #26 rather than duplicating it (branched from current
mainpost-#26-merge; confirmed viagh pr view 26and readingmzml.rsthat TIC/BPC were already present and left untouched). Addssrm_chromatograms_for: for eachPrmTarget, walksmsms_type == 10frames, looks upPrmFrameMsMsInforows, decodes peaks via the samedecode_peakspathiter_spectrauses, sums intensity within the target's scan range, and accumulates one point per frame per target. Emits aChromatogramRecordper target withchromatogram_type=MS:1001473("selected reaction monitoring chromatogram") andprecursor_mzfromPrmTarget::monoisotopic_mz. A new combining wrapper concatenates TIC/BPC with the new SRM records and renumbersindexcontiguously, since mzML requires unique/contiguous indices across the whole<chromatogramList>; bothTdfSource/OwnedTdfSourceiter_chromatogramsimpls now point at this wrapper.product_mzis deliberately leftNone: the TDF schema has no discrete product-ion m/z field for prm-PASEF (a full fragment-ion scan per precursor, not a triple-quadrupole transition) - populating it would mean inventing an unbacked value, which the clean-room policy forbids. Genuine zero-intensity frames are kept as real points; targets never appearing inPrmFrameMsMsInfoare omitted rather than emitted empty. Correctness is argued from self-consistency and the PSI-MS mzML schema only, per CONTRIBUTING.md's clean-room note - no vendor software was used.Addresses the remaining SRM/PRM scope of #25.
Test plan
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspace(26 unit tests including 5 new ones for the SRM helpers, 1 conformance test, 10 roundtrip tests; cache-gated ones skip cleanly since/corpus/isn't present here, matching existing CI behavior)Contributed by @Nabejo.