Skip to main content

timsrust_core/
spectra.rs

1use timsrust_utils::vec::get_top_n;
2
3use super::Precursor;
4use crate::{IsolationWindow, Mz, TofIndex, coordinates::Converter};
5
6/// An MS2 spectrum with centroided mz values and summed intensities.
7#[derive(Debug, PartialEq, Default, Clone)]
8pub struct Spectrum<C = TofIndex> {
9    intensities: Vec<f64>,
10    precursor: Option<Precursor>,
11    index: usize,
12    coordinates: Vec<C>,
13    isolation_window: IsolationWindow,
14}
15
16impl<C> Spectrum<C> {
17    pub fn new(
18        intensities: Vec<f64>,
19        index: usize,
20        precursor: Option<Precursor>,
21        coordinates: Vec<C>,
22        isolation_window: IsolationWindow,
23    ) -> Self {
24        assert!(
25            intensities.len() == coordinates.len(),
26            "Intensities and coordinates must have the same length"
27        );
28        Spectrum {
29            intensities,
30            precursor,
31            index,
32            coordinates,
33            isolation_window,
34        }
35    }
36
37    pub fn intensities(&self) -> &Vec<f64> {
38        &self.intensities
39    }
40
41    pub fn precursor(&self) -> &Option<Precursor> {
42        &self.precursor
43    }
44
45    pub fn index(&self) -> usize {
46        self.index
47    }
48
49    pub fn isolation_window(&self) -> &IsolationWindow {
50        &self.isolation_window
51    }
52
53    pub fn len(&self) -> usize {
54        self.intensities.len()
55    }
56
57    pub fn is_empty(&self) -> bool {
58        self.len() == 0
59    }
60
61    pub fn coordinates(&self) -> &Vec<C> {
62        &self.coordinates
63    }
64
65    pub fn convert_to<X>(self, converter: impl Converter<C, X>) -> Spectrum<X>
66    where
67        C: Copy,
68    {
69        Spectrum {
70            intensities: self.intensities,
71            precursor: self.precursor,
72            index: self.index,
73            coordinates: converter.batch_convert(&self.coordinates),
74            isolation_window: self.isolation_window,
75        }
76    }
77
78    pub fn get_top_n(&self, n: usize) -> Self
79    where
80        C: Clone,
81    {
82        let top_indices = get_top_n(&self.intensities, n);
83        Self {
84            intensities: top_indices
85                .iter()
86                .map(|&index| self.intensities[index])
87                .collect(),
88            precursor: self.precursor.clone(),
89            index: self.index,
90            coordinates: top_indices
91                .iter()
92                .map(|&index| self.coordinates[index].clone())
93                .collect(),
94            isolation_window: self.isolation_window.clone(),
95        }
96    }
97}
98
99impl Spectrum<TofIndex> {
100    pub fn tof_indices(&self) -> &Vec<TofIndex> {
101        &self.coordinates
102    }
103
104    pub fn mz_values(
105        &self,
106        converter: impl Converter<TofIndex, Mz>,
107    ) -> Vec<Mz> {
108        converter.batch_convert(&self.coordinates)
109    }
110
111    pub fn to_mz_spectrum(
112        self,
113        converter: impl Converter<TofIndex, Mz>,
114    ) -> Spectrum<Mz> {
115        self.convert_to(converter)
116    }
117}
118
119impl Spectrum<Mz> {
120    pub fn mz_values(&self) -> &Vec<Mz> {
121        &self.coordinates
122    }
123
124    pub fn to_tof_spectrum(
125        self,
126        converter: impl Converter<Mz, TofIndex>,
127    ) -> Spectrum<TofIndex> {
128        self.convert_to(converter)
129    }
130}