use openmassspec_core::conformance::assert_source_invariants;
use openmassspec_core::SpectrumSource;
use openszraw::reader::Reader;
use std::path::{Path, PathBuf};
fn qgd_profile_fixture() -> PathBuf {
PathBuf::from("/workspaces/Projects/Data/SZRaw/PXD019638/L-B2-Br0-1.qgd")
}
fn qgd_mrm_fixture() -> PathBuf {
PathBuf::from("/workspaces/Projects/Data/SZRaw/PXD034978/49_27a__8122021_11.qgd")
}
fn qtfl_fixture() -> PathBuf {
PathBuf::from("/workspaces/Projects/Data/SZRaw/MSV000084197/20190607_NM16.lcd")
}
fn ttfl_fixture() -> PathBuf {
PathBuf::from("/workspaces/Projects/Data/SZRaw/PXD020792/UY02-01-01p400.LCD")
}
fn ttfl_partial_block_fixture() -> PathBuf {
PathBuf::from("/workspaces/Projects/Data/SZRaw/PXD025121/17.lcd")
}
fn open_or_skip(path: &Path) -> Option<Reader> {
if !path.exists() {
eprintln!("skip: corpus not present at {}", path.display());
return None;
}
Some(Reader::open(path).unwrap_or_else(|e| panic!("Reader::open({path:?}) failed: {e}")))
}
#[test]
fn qgd_profile_conformance() {
let Some(mut reader) = open_or_skip(&qgd_profile_fixture()) else {
return;
};
let n = assert_source_invariants(&mut reader).expect("conformance invariants failed");
assert!(n > 0, "expected at least one spectrum");
println!("qgd profile: {n} spectra");
}
#[test]
fn qgd_profile_peaks_are_plausible() {
let Some(mut reader) = open_or_skip(&qgd_profile_fixture()) else {
return;
};
let spectra: Vec<_> = reader.iter_spectra().collect();
assert!(!spectra.is_empty());
assert!(spectra.iter().all(|s| s.ms_level == 1));
let with_peaks: Vec<_> = spectra.iter().filter(|s| !s.mz.is_empty()).collect();
assert!(
!with_peaks.is_empty(),
"expected at least one spectrum with peaks"
);
for s in &with_peaks {
for &mz in &s.mz {
assert!(
(1.0..=2000.0).contains(&mz),
"implausible GC-MS m/z {mz} in spectrum {}",
s.native_id
);
}
}
let mut last_rt = f64::MIN;
for s in &spectra {
assert!(
s.retention_time_sec + 1e-6 >= last_rt,
"RT regressed: {} -> {}",
last_rt,
s.retention_time_sec
);
last_rt = s.retention_time_sec;
}
}
#[test]
fn qgd_mrm_conformance() {
let Some(mut reader) = open_or_skip(&qgd_mrm_fixture()) else {
return;
};
let n = assert_source_invariants(&mut reader).expect("conformance invariants failed");
assert!(n > 0, "expected at least one spectrum");
println!("qgd mrm: {n} spectra");
}
#[test]
fn qgd_mrm_transitions_are_plausible() {
let Some(mut reader) = open_or_skip(&qgd_mrm_fixture()) else {
return;
};
let spectra: Vec<_> = reader.iter_spectra().collect();
assert!(!spectra.is_empty());
assert!(spectra.iter().all(|s| s.ms_level == 2));
assert!(spectra
.iter()
.all(|s| s.mz.len() == 1 && s.intensity.len() == 1));
for s in &spectra {
let precursor = s
.precursor
.as_ref()
.unwrap_or_else(|| panic!("MRM spectrum {} missing precursor", s.native_id));
let precursor_mz = precursor.selected_mz.expect("selected_mz set for MRM");
assert!(
(1.0..=2000.0).contains(&precursor_mz),
"implausible precursor m/z {precursor_mz}"
);
let product_mz = s.mz[0];
assert!(
(1.0..=2000.0).contains(&product_mz),
"implausible product m/z {product_mz}"
);
}
}
#[test]
fn qtfl_conformance() {
let Some(mut reader) = open_or_skip(&qtfl_fixture()) else {
return;
};
let n = assert_source_invariants(&mut reader).expect("conformance invariants failed");
assert!(n > 0, "expected at least one spectrum");
println!("qtfl: {n} spectra");
}
#[test]
fn qtfl_centroid_mz_is_plausible_and_has_ms2() {
let Some(mut reader) = open_or_skip(&qtfl_fixture()) else {
return;
};
let spectra: Vec<_> = reader.iter_spectra().collect();
assert!(!spectra.is_empty());
let has_ms1 = spectra.iter().any(|s| s.ms_level == 1);
let has_ms2 = spectra.iter().any(|s| s.ms_level == 2);
assert!(has_ms1, "expected at least one MS1 (event_id==1) scan");
assert!(
has_ms2,
"expected at least one MS2 (event_id>1) scan - see docs/format/05 addendum"
);
let with_peaks: Vec<_> = spectra.iter().filter(|s| !s.mz.is_empty()).collect();
assert!(!with_peaks.is_empty());
for s in &with_peaks {
for &mz in &s.mz {
assert!(
(50.0..=5000.0).contains(&mz),
"implausible QTOF m/z {mz} in spectrum {}",
s.native_id
);
}
}
for s in spectra.iter().filter(|s| s.ms_level == 2) {
assert!(
s.precursor
.as_ref()
.is_some_and(|p| p.precursor_native_id.is_some()),
"MS2 spectrum {} missing precursor_native_id",
s.native_id
);
}
}
#[test]
fn ttfl_conformance() {
let Some(mut reader) = open_or_skip(&ttfl_fixture()) else {
return;
};
let n = assert_source_invariants(&mut reader).expect("conformance invariants failed");
assert!(n > 0, "expected at least one spectrum");
println!("ttfl: {n} spectra");
}
#[test]
fn ttfl_partial_block_conformance() {
let Some(mut reader) = open_or_skip(&ttfl_partial_block_fixture()) else {
return;
};
let n = assert_source_invariants(&mut reader).expect("conformance invariants failed");
assert!(n > 0, "expected at least one spectrum");
println!("ttfl (2-channel, partial trailing block): {n} spectra");
}
#[test]
fn ttfl_mz_is_calibrated_finite_and_nonnegative() {
let Some(mut reader) = open_or_skip(&ttfl_fixture()) else {
return;
};
let spectra: Vec<_> = reader.iter_spectra().collect();
assert!(!spectra.is_empty());
assert!(spectra.iter().all(|s| s.ms_level == 1));
let with_peaks: Vec<_> = spectra.iter().filter(|s| !s.mz.is_empty()).collect();
assert!(!with_peaks.is_empty());
for s in &with_peaks {
for &mz in &s.mz {
assert!(mz.is_finite(), "non-finite calibrated m/z {mz}");
assert!(mz >= 0.0, "negative calibrated m/z {mz}");
}
}
}
#[test]
fn ttfl_base_peak_mz_is_plausible_for_most_scans() {
let Some(mut reader) = open_or_skip(&ttfl_fixture()) else {
return;
};
let spectra: Vec<_> = reader.iter_spectra().collect();
let base_peaks: Vec<f64> = spectra
.iter()
.filter_map(|s| {
s.intensity
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| a.total_cmp(b))
.map(|(i, _)| s.mz[i])
})
.collect();
assert!(!base_peaks.is_empty());
let plausible = base_peaks.iter().filter(|&&mz| mz < 20_000.0).count();
let fraction = plausible as f64 / base_peaks.len() as f64;
assert!(
fraction > 0.8,
"only {:.1}% of base peaks fell under 20,000 Da ({} of {})",
fraction * 100.0,
plausible,
base_peaks.len()
);
}