#[derive(Debug, Clone, Copy)]
pub struct FilterParams {
pub mz_half_width: u32,
pub min_feature_length: usize,
pub max_internal_gap: usize,
pub min_window_intensity: u64,
pub min_feature_intensity: u64,
pub num_iterations: usize,
}
impl Default for FilterParams {
fn default() -> Self {
Self {
mz_half_width: 3,
min_feature_length: 5,
max_internal_gap: 2,
min_window_intensity: 0,
min_feature_intensity: 0,
num_iterations: 2,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct HaloParams {
pub peak_fraction: f64,
pub mz_idx_half_width: u32,
pub scan_half_width: usize,
}
impl Default for HaloParams {
fn default() -> Self {
Self {
peak_fraction: 0.15,
mz_idx_half_width: 80,
scan_half_width: 2,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct SmoothParams {
pub mz_idx_half_width: u32,
pub scan_half_width: usize,
pub iterations: usize,
}
impl Default for SmoothParams {
fn default() -> Self {
Self {
mz_idx_half_width: 2,
scan_half_width: 3,
iterations: 1,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct WatershedParams {
pub box_scan: u32,
pub box_mz_idx: u32,
pub min_seed_intensity: u64,
pub min_centroid_total: u64,
pub max_tof_offset: u32,
}
impl Default for WatershedParams {
fn default() -> Self {
Self {
box_scan: 10,
box_mz_idx: 3,
min_seed_intensity: 0,
min_centroid_total: 0,
max_tof_offset: 10,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct BoxCentroidParams {
pub mz_idx_half_width: u32,
pub scan_half_width: u32,
pub min_centroid_total: u64,
}
impl Default for BoxCentroidParams {
fn default() -> Self {
Self {
mz_idx_half_width: 2,
scan_half_width: 2,
min_centroid_total: 0,
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct DiaWindowParams {
pub scan_pad: u32,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct DdaWindowParams {
pub scan_pad: u32,
}
#[derive(Debug, Clone, Copy)]
pub struct DiaMs1WindowParams {
pub mz_pad: f64,
pub im_pad: f64,
}
impl Default for DiaMs1WindowParams {
fn default() -> Self {
Self {
mz_pad: 5.0,
im_pad: 0.05,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Ms1PolygonParams {
pub mz_pad: f64,
pub im_pad: f64,
}
impl Default for Ms1PolygonParams {
fn default() -> Self {
Self {
mz_pad: 5.0,
im_pad: 0.05,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct MsmsFilterParams {
pub mz_half_width: u32,
pub min_feature_length: usize,
pub max_internal_gap: usize,
pub min_window_intensity: u64,
pub min_feature_intensity: u64,
pub num_iterations: usize,
}
impl Default for MsmsFilterParams {
fn default() -> Self {
Self {
mz_half_width: 3,
min_feature_length: 3,
max_internal_gap: 8,
min_window_intensity: 0,
min_feature_intensity: 0,
num_iterations: 1,
}
}
}
impl MsmsFilterParams {
pub fn as_filter_params(&self) -> FilterParams {
FilterParams {
mz_half_width: self.mz_half_width,
min_feature_length: self.min_feature_length,
max_internal_gap: self.max_internal_gap,
min_window_intensity: self.min_window_intensity,
min_feature_intensity: self.min_feature_intensity,
num_iterations: self.num_iterations,
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct CropParams {
pub mz_min: Option<f64>,
pub mz_max: Option<f64>,
pub im_min: Option<f64>,
pub im_max: Option<f64>,
pub rt_min: Option<f64>,
pub rt_max: Option<f64>,
pub min_intensity: Option<u32>,
pub max_intensity: Option<u32>,
}
impl CropParams {
pub fn is_empty(&self) -> bool {
*self == CropParams::default()
}
pub fn has_rt(&self) -> bool {
self.rt_min.is_some() || self.rt_max.is_some()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn filter_defaults_match_tuned_benchmark() {
let p = FilterParams::default();
assert_eq!(p.mz_half_width, 3);
assert_eq!(p.min_feature_length, 5);
assert_eq!(p.max_internal_gap, 2);
assert_eq!(p.min_window_intensity, 0);
assert_eq!(p.min_feature_intensity, 0);
assert_eq!(p.num_iterations, 2);
}
#[test]
fn halo_smooth_watershed_defaults() {
let h = HaloParams::default();
assert_eq!(h.peak_fraction, 0.15);
assert_eq!(h.mz_idx_half_width, 80);
assert_eq!(h.scan_half_width, 2);
let s = SmoothParams::default();
assert_eq!(s.mz_idx_half_width, 2);
assert_eq!(s.scan_half_width, 3);
assert_eq!(s.iterations, 1);
let w = WatershedParams::default();
assert_eq!(w.box_scan, 10);
assert_eq!(w.box_mz_idx, 3);
assert_eq!(w.max_tof_offset, 10);
}
#[test]
fn dia_ms1_defaults_are_physical_pads() {
let d = DiaMs1WindowParams::default();
assert_eq!(d.mz_pad, 5.0);
assert_eq!(d.im_pad, 0.05);
}
#[test]
fn polygon_pad_defaults_match_dia_ms1() {
let p = Ms1PolygonParams::default();
let d = DiaMs1WindowParams::default();
assert_eq!(p.mz_pad, d.mz_pad);
assert_eq!(p.im_pad, d.im_pad);
}
#[test]
fn msms_defaults_use_a_shorter_feature_length_than_ms1() {
let m = MsmsFilterParams::default();
assert_eq!(m.min_feature_length, 3);
assert_eq!(m.max_internal_gap, 8);
assert_eq!(m.num_iterations, 1);
assert!(m.min_feature_length < FilterParams::default().min_feature_length);
}
#[test]
fn msms_as_filter_params_preserves_every_knob() {
let m = MsmsFilterParams {
mz_half_width: 7,
min_feature_length: 4,
max_internal_gap: 9,
min_window_intensity: 11,
min_feature_intensity: 13,
num_iterations: 3,
};
let f = m.as_filter_params();
assert_eq!(f.mz_half_width, m.mz_half_width);
assert_eq!(f.min_feature_length, m.min_feature_length);
assert_eq!(f.max_internal_gap, m.max_internal_gap);
assert_eq!(f.min_window_intensity, m.min_window_intensity);
assert_eq!(f.min_feature_intensity, m.min_feature_intensity);
assert_eq!(f.num_iterations, m.num_iterations);
}
#[test]
fn crop_default_is_empty_with_no_rt() {
let c = CropParams::default();
assert!(c.is_empty());
assert!(!c.has_rt());
}
#[test]
fn crop_with_a_non_rt_bound_is_not_empty_but_has_no_rt() {
let c = CropParams {
mz_min: Some(400.0),
..CropParams::default()
};
assert!(!c.is_empty());
assert!(!c.has_rt());
}
#[test]
fn crop_has_rt_detects_either_bound() {
assert!(
CropParams {
rt_min: Some(1.0),
..Default::default()
}
.has_rt()
);
let hi = CropParams {
rt_max: Some(9.0),
..Default::default()
};
assert!(hi.has_rt());
assert!(!hi.is_empty());
}
#[test]
fn stages_default_is_every_stage_off() {
let s = Stages::default();
assert!(!s.filter_all_frames);
assert_eq!(s.frame_half_width, 0);
assert!(s.halo.is_none());
assert!(s.denoise_msms.is_none());
assert!(s.smooth.is_none());
assert!(s.watershed.is_none());
assert!(s.box_centroid.is_none());
assert!(s.dia_window.is_none());
assert!(s.dda_window.is_none());
assert!(!s.dia_per_window);
assert!(s.dia_ms1.is_none());
assert!(s.ms1_polygon.is_none());
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct Stages<'a> {
pub filter_all_frames: bool,
pub frame_half_width: usize,
pub halo: Option<&'a HaloParams>,
pub denoise_msms: Option<&'a MsmsFilterParams>,
pub smooth: Option<&'a SmoothParams>,
pub watershed: Option<&'a WatershedParams>,
pub box_centroid: Option<&'a BoxCentroidParams>,
pub dia_window: Option<&'a DiaWindowParams>,
pub dda_window: Option<&'a DdaWindowParams>,
pub dia_per_window: bool,
pub dia_ms1: Option<&'a DiaMs1WindowParams>,
pub ms1_polygon: Option<&'a Ms1PolygonParams>,
}