Skip to content

dda: drop hardcoded scan 0..1000 in extract_precursor_ms1_signals#399

Merged
theGreatHerrLebert merged 1 commit into
mainfrom
fix/dda-scan-range-cap
May 20, 2026
Merged

dda: drop hardcoded scan 0..1000 in extract_precursor_ms1_signals#399
theGreatHerrLebert merged 1 commit into
mainfrom
fix/dda-scan-range-cap

Conversation

@theGreatHerrLebert
Copy link
Copy Markdown
Owner

Problem

extract_precursor_ms1_signals (rustdf/src/data/dda.rs) builds its XIC /
mobilogram filter with a hardcoded scan range 0..1000:

let xic_filtered = frame.filter_ranged(
    xic_mz_min, xic_mz_max,
    0, 1000,                  // <-- hardcoded
    im_min, im_max,
    ...
);

The inv_mobility window (im_min/im_max) was already doing the actual
mobility selection — the scan cap added nothing except silent signal loss for
any acquisition with more than 1000 scans per frame. That's common for
high-mobility-resolution methods, particularly HLA immunopeptidomics setups.

Symptom

On affected datasets, sample precursors whose target mobility maps to
scan indices >= 1000 extract to all-zero MS1: isotope_intensity = [0,0,0,0,0],
rt_r2 = 0, im_r2 = 0 — even when m/z calibration is correct.

Confirmed on two real datasets (with the SDK-derived m/z fix from #396
already in place, so this is not the m/z bug):

Dataset nonzero / sampled
PXD026463 (HLA immunopeptidomics) 0 / 10 — entire dataset hidden
PXD020509 (HLA immunopeptidomics) 5 / 10 — per-precursor binary on/off depending on mobility

The per-precursor binary pattern on PXD020509 (clean envelopes when mobility
falls in scans 0–1000; zero when it falls in scans ≥1000) is the giveaway.

Fix

One-line change: replace 0, 1000 with 0, i32::MAX. The inv_mobility
filter still selects the requested mobility band.

Compatibility

No API change. No new arguments. The only observable difference is that
acquisitions with >1000 scans per frame stop dropping signal in the XIC /
mobilogram path.

Note

dda.rs has a few other filter_ranged call sites that hardcode
scan 0..2000 (lines 355, 670, 787, 875). Those are different code paths
(fragment extraction, top-N peak filtering) and are out of scope for this
fix — the 2000 cap is unlikely to bite in practice. Worth a follow-up audit
if a similar symptom ever appears on the fragment side.

The MS1 XIC/mobilogram filter in extract_precursor_ms1_signals hardcoded the
scan range to 0..1000. The inv_mobility window (im_min/im_max) was already
doing the actual mobility selection, so the scan cap only served to silently
truncate signal on acquisitions that use more than 1000 scans per frame
(high mobility-resolution / wide IM range methods — common in HLA
immunopeptidomics).

Symptom: for affected datasets, sample precursors whose target mobility
maps to scan indices >= 1000 extract to all-zero MS1 (iso = [0,0,0,0,0],
rt_r2 = 0, im_r2 = 0) even when the m/z calibration is correct. Confirmed
on PXD026463 (10/10 precursors zero) and PXD020509 (5/10 zero, 5/10 fine)
with the SDK-derived m/z fix applied — the latter's per-precursor binary
on/off pattern is the giveaway.

Fix: change the scan range to 0..i32::MAX. The inv_mobility filter still
constrains to the requested mobility window.
@theGreatHerrLebert theGreatHerrLebert merged commit 8789a1a into main May 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant