Skip to main content

timsrust_centroid/
spectrum_reader.rs

1pub mod narrow_spectrum_reader;
2pub mod wide_spectrum_reader;
3
4use std::sync::Arc;
5
6use rayon::prelude::*;
7use timsrust_core::{
8    Converter, FrameInfo, FrameIons, FrameReader, Im, InvertibleConverter, Mz,
9    ScanIndex, Spectrum, TofIndex,
10};
11
12pub use narrow_spectrum_reader::NarrowSpectrumReader;
13use timsrust_core::utils::reader::{IndexedReader, ParIterableReader};
14pub use wide_spectrum_reader::WideSpectrumReader;
15
16use crate::{PeakReader, error::TimsResult};
17
18/// Reads and extracts spectra from frames.
19pub enum SpectrumReader<
20    IonReader,
21    InfoReader,
22    IM: InvertibleConverter<ScanIndex, Im>,
23    MZ: Converter<TofIndex, Mz>,
24> {
25    Narrow(NarrowSpectrumReader<IonReader, InfoReader, IM, MZ>),
26    Wide(WideSpectrumReader<IonReader, InfoReader, IM>),
27}
28
29impl<IonReader, InfoReader, IM, MZ>
30    SpectrumReader<IonReader, InfoReader, IM, MZ>
31where
32    IonReader: timsrust_core::utils::reader::Reader<FrameIons> + Sync + Send,
33    InfoReader: timsrust_core::utils::reader::Reader<FrameInfo>
34        + IndexedReader<FrameInfo>
35        + Sync
36        + Send,
37    IM: InvertibleConverter<ScanIndex, Im> + Sync + Send,
38    MZ: Converter<TofIndex, Mz> + Sync + Send,
39{
40    /// Create a new [`SpectrumReader`] from a [`FrameReader`] and processing parameters.
41    ///
42    /// # Errors
43    /// Returns an error if kernel extraction fails.
44    pub fn new(
45        frame_reader: FrameReader<IonReader, InfoReader>,
46        min_ms1_ion_count: f64,
47        min_ms2_ion_count: f64,
48        min_spectrum_size: usize,
49        use_precursors: bool,
50        im_converter: IM,
51        mz_converter: MZ,
52    ) -> TimsResult<Self> {
53        let spectrum_reader = if use_precursors {
54            let peak_reader = PeakReader::new(
55                frame_reader,
56                min_ms1_ion_count,
57                min_ms2_ion_count,
58            )?;
59            let reader = NarrowSpectrumReader::new(
60                peak_reader,
61                min_spectrum_size,
62                Arc::new(im_converter),
63                Arc::new(mz_converter),
64            )?;
65            SpectrumReader::Narrow(reader)
66        } else {
67            let peak_reader =
68                PeakReader::new(frame_reader, -1.0, min_ms2_ion_count)?;
69            let reader = WideSpectrumReader::new(
70                peak_reader,
71                min_spectrum_size,
72                Arc::new(im_converter),
73            )?;
74            SpectrumReader::Wide(reader)
75        };
76        Ok(spectrum_reader)
77    }
78
79    /// Returns the number of spectra processed so far.
80    pub fn len(&self) -> usize {
81        match self {
82            SpectrumReader::Narrow(reader) => reader.len(),
83            SpectrumReader::Wide(reader) => reader.len(),
84        }
85    }
86
87    pub fn is_empty(&self) -> bool {
88        self.len() == 0
89    }
90
91    /// Extract all MS2 spectra from a given frame index.
92    pub fn get_spectra_from_frame(&self, frame_index: usize) -> Vec<Spectrum> {
93        match self {
94            SpectrumReader::Narrow(reader) => {
95                reader.get_spectra_from_frame(frame_index)
96            },
97            SpectrumReader::Wide(reader) => {
98                reader.get_spectra_from_frame(frame_index)
99            },
100        }
101    }
102
103    pub fn frame_count(&self) -> usize {
104        match self {
105            SpectrumReader::Narrow(reader) => reader.frame_count(),
106            SpectrumReader::Wide(reader) => reader.frame_count(),
107        }
108    }
109
110    pub fn tof_fwhm(&self) -> usize {
111        match self {
112            SpectrumReader::Narrow(reader) => reader.tof_fwhm(),
113            SpectrumReader::Wide(reader) => reader.tof_fwhm(),
114        }
115    }
116
117    pub fn scan_fwhm(&self) -> usize {
118        match self {
119            SpectrumReader::Narrow(reader) => reader.scan_fwhm(),
120            SpectrumReader::Wide(reader) => reader.scan_fwhm(),
121        }
122    }
123}
124
125impl<'a, IonReader, InfoReader, IM, MZ> ParIterableReader<'a, Spectrum>
126    for SpectrumReader<IonReader, InfoReader, IM, MZ>
127where
128    IonReader: timsrust_core::utils::reader::Reader<FrameIons> + Sync + Send,
129    InfoReader: timsrust_core::utils::reader::Reader<FrameInfo>
130        + IndexedReader<FrameInfo>
131        + Sync
132        + Send,
133    IM: InvertibleConverter<ScanIndex, Im> + Sync + Send,
134    MZ: Converter<TofIndex, Mz> + Sync + Send,
135{
136    type Error = TimsCentroidError;
137
138    fn par_iter(
139        &'a self,
140    ) -> impl ParallelIterator<Item = Result<Spectrum, Self::Error>> {
141        match self {
142            SpectrumReader::Narrow(reader) => A::Narrow(reader),
143            SpectrumReader::Wide(reader) => A::Wide(reader),
144        }
145        .map(Ok)
146    }
147}
148
149enum A<
150    'a,
151    IonReader,
152    InfoReader,
153    IM: InvertibleConverter<ScanIndex, Im>,
154    MZ: Converter<TofIndex, Mz>,
155> {
156    Narrow(&'a NarrowSpectrumReader<IonReader, InfoReader, IM, MZ>),
157    Wide(&'a WideSpectrumReader<IonReader, InfoReader, IM>),
158}
159
160#[derive(Debug, thiserror::Error)]
161#[error("{0}")]
162pub struct TimsCentroidError(String);
163
164impl<
165    'a,
166    IonReader: timsrust_core::utils::reader::Reader<FrameIons> + Sync + Send,
167    InfoReader: timsrust_core::utils::reader::Reader<FrameInfo>
168        + IndexedReader<FrameInfo>
169        + Sync
170        + Send,
171    IM: InvertibleConverter<ScanIndex, Im> + Sync + Send,
172    MZ: Converter<TofIndex, Mz> + Sync + Send,
173> ParallelIterator for A<'a, IonReader, InfoReader, IM, MZ>
174{
175    type Item = timsrust_core::Spectrum;
176
177    fn drive_unindexed<C>(self, consumer: C) -> C::Result
178    where
179        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
180    {
181        match self {
182            Self::Narrow(reader) => {
183                reader._par_iter().drive_unindexed(consumer)
184            },
185            Self::Wide(reader) => reader._par_iter().drive_unindexed(consumer),
186        }
187    }
188}
189
190impl<
191    IonReader: timsrust_core::utils::reader::Reader<FrameIons> + Sync + Send,
192    InfoReader: timsrust_core::utils::reader::Reader<FrameInfo>
193        + IndexedReader<FrameInfo>
194        + Sync
195        + Send,
196    IM: InvertibleConverter<ScanIndex, Im> + Sync + Send,
197    MZ: Converter<TofIndex, Mz> + Sync + Send,
198> ParallelIterator for SpectrumReader<IonReader, InfoReader, IM, MZ>
199{
200    type Item = timsrust_core::Spectrum;
201
202    fn drive_unindexed<C>(self, consumer: C) -> C::Result
203    where
204        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
205    {
206        match self {
207            Self::Narrow(reader) => {
208                reader._par_iter().drive_unindexed(consumer)
209            },
210            Self::Wide(reader) => reader._par_iter().drive_unindexed(consumer),
211        }
212    }
213}