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}