mzdeisotope_map/
iter.rs

1use mzpeaks::{
2    feature::{Feature, TimeInterval},
3    prelude::*,
4    CentroidPeak, MZ,
5};
6
7#[derive(Debug)]
8pub struct FeatureSetIter<'a, Y> {
9    features: &'a [Option<&'a Feature<MZ, Y>>],
10    pub start_time: f64,
11    pub end_time: f64,
12    pub last_time_seen: f64,
13    index_list: Vec<usize>,
14    has_more: bool,
15}
16
17impl<Y> Iterator for FeatureSetIter<'_, Y> {
18    type Item = (f64, Vec<Option<CentroidPeak>>);
19
20    fn next(&mut self) -> Option<Self::Item> {
21        self.get_next_value()
22    }
23}
24
25impl<'a, Y> FeatureSetIter<'a, Y> {
26    pub fn new_with_time_interval(
27        features: &'a [Option<&'a Feature<MZ, Y>>],
28        start_time: f64,
29        end_time: f64,
30    ) -> Self {
31        let n = features.len();
32        let index_list = (0..n).map(|_| 0).collect();
33
34        let mut this = Self {
35            features,
36            start_time,
37            end_time,
38            index_list,
39            last_time_seen: f64::NEG_INFINITY,
40            has_more: true,
41        };
42        this.initialize_indices();
43        this.has_more = this.has_more();
44        this
45    }
46
47    pub fn new(features: &'a [Option<&'a Feature<MZ, Y>>]) -> Self {
48        let mut start_time: f64 = 0.0;
49        let mut end_time: f64 = f64::INFINITY;
50
51        for f in features.iter().flatten() {
52            {
53                if let Some(t) = f.start_time() {
54                    if start_time < t {
55                        start_time = t;
56                    }
57                }
58                if let Some(t) = f.end_time() {
59                    if end_time > t {
60                        end_time = t;
61                    }
62                }
63            }
64        }
65
66        if end_time < start_time {
67            std::mem::swap(&mut start_time, &mut end_time);
68        }
69
70        Self::new_with_time_interval(features, start_time, end_time)
71    }
72
73    fn get_next_time(&self) -> Option<f64> {
74        let mut time = f64::INFINITY;
75
76        for (f, ix) in self.features.iter().zip(self.index_list.iter().copied()) {
77            if let Some(f) = f {
78                if let Some(ix_time) = f.time_view().get(ix).copied() {
79                    if ix_time < time
80                        && (ix_time <= self.end_time || ix_time.is_close(&self.end_time))
81                        && ix_time > self.last_time_seen
82                    {
83                        time = ix_time;
84                    }
85                }
86            }
87        }
88
89        if time.is_infinite() {
90            return None;
91        }
92        Some(time)
93    }
94
95    fn has_more(&self) -> bool {
96        let mut j = 0;
97        let n = self.features.len();
98
99        for (f, ix) in self.features.iter().zip(self.index_list.iter().copied()) {
100            if let Some(f) = f {
101                let done = ix >= f.len();
102                let done = if !done {
103                    let time_at = f.time_view()[ix];
104                    time_at > self.end_time
105                } else {
106                    true
107                };
108                j += done as usize;
109            } else {
110                j += 1;
111            }
112        }
113        j != n
114    }
115
116    fn initialize_indices(&mut self) {
117        self.features.iter().enumerate().for_each(|(i, f)| {
118            if let Some(f) = f {
119                let (ix, _) = f.find_time(self.start_time);
120                self.index_list[i] = ix.unwrap();
121            } else {
122                self.index_list[i] = 0;
123            }
124        })
125    }
126
127    fn get_peaks_for_next_time(&mut self, time: f64) -> Vec<Option<CentroidPeak>> {
128        let mut peaks = Vec::new();
129        for (f, i) in self.features.iter().zip(&mut self.index_list) {
130            if let Some(f) = f {
131                if *i >= f.len() {
132                    peaks.push(None);
133                    continue;
134                }
135                let (mz, time_at, intensity) = f.at(*i).unwrap();
136                let time_err = time_at - time;
137                if time_err.abs() > 1e-3 {
138                    peaks.push(None);
139                } else {
140                    peaks.push(Some(CentroidPeak::new(mz, intensity, *i as u32)));
141                    *i += 1;
142                }
143            } else {
144                peaks.push(None);
145            }
146        }
147        peaks
148    }
149
150    fn get_next_value(&mut self) -> Option<(f64, Vec<Option<CentroidPeak>>)> {
151        if !self.has_more {
152            return None;
153        }
154        let time = self.get_next_time();
155        if let Some(time) = time {
156            let peaks = self.get_peaks_for_next_time(time);
157            self.last_time_seen = time;
158            Some((time, peaks))
159        } else {
160            self.has_more = false;
161            None
162        }
163    }
164}