Skip to main content

timsrust_tdf/
spectrum_reader.rs

1mod dda;
2mod dia;
3mod raw_spectra;
4
5use std::sync::Arc;
6
7use raw_spectra::{RawSpectrum, RawSpectrumReader, RawSpectrumReaderError};
8use rayon::iter::{IntoParallelIterator, ParallelIterator};
9use timsrust_core::utils::reader::Reader;
10use timsrust_core::{Im, InvertibleConverter, ScanIndex, Spectrum};
11
12use crate::{
13    FrameReaderError, FrameWindowSplittingConfiguration, MetadataReaderError,
14    TDFPrecursorReader, TDFPrecursorReaderError,
15    file_readers::sql_reader::{SqlReader, SqlReaderError},
16};
17
18use super::TDFPathLike;
19
20use crate::{TDFPath, TdfFrameReader};
21
22#[derive(Debug)]
23pub struct TDFSpectrumReader<ImC> {
24    precursor_reader: TDFPrecursorReader<ImC>,
25    raw_spectrum_reader: RawSpectrumReader,
26    config: SpectrumReaderConfig<ImC>,
27}
28
29impl<ImC: InvertibleConverter<ScanIndex, Im> + Send + Sync + std::fmt::Debug>
30    TDFSpectrumReader<ImC>
31{
32    pub fn new(
33        path: impl TDFPathLike,
34        config: SpectrumReaderConfig<ImC>,
35        im_converter: Arc<ImC>,
36    ) -> Result<Self, TDFSpectrumReaderError> {
37        let frame_reader = TdfFrameReader::new(&path)?;
38        let tdf_sql_reader = SqlReader::open(&path)?;
39        let precursor_reader = TDFPrecursorReader::build()
40            .with_path(&path)
41            .with_config(config.clone().frame_splitting_params)
42            .with_im_converter(im_converter.clone())
43            .finalize()?;
44        let acquisition_type = frame_reader.get_acquisition();
45        let splitting_strategy = config
46            .clone()
47            .frame_splitting_params
48            .finalize(Some(im_converter));
49        let raw_spectrum_reader = RawSpectrumReader::new(
50            &tdf_sql_reader,
51            frame_reader,
52            acquisition_type,
53            splitting_strategy,
54        )?;
55        Ok(Self {
56            precursor_reader,
57            raw_spectrum_reader,
58            config,
59        })
60    }
61
62    fn read_single_raw_spectrum(
63        &self,
64        index: usize,
65    ) -> Result<RawSpectrum, RawSpectrumReaderError> {
66        let raw_spectrum = self
67            .raw_spectrum_reader
68            .get(index)?
69            .smooth(self.config.spectrum_processing_params.smoothing_window)
70            .centroid(
71                self.config.spectrum_processing_params.centroiding_window,
72            );
73        Ok(raw_spectrum)
74    }
75
76    fn _get(&self, index: usize) -> Result<Spectrum, TDFSpectrumReaderError> {
77        let raw_spectrum = self.read_single_raw_spectrum(index)?;
78        let spectrum = raw_spectrum
79            // .finalize(self.precursor_reader.get(index)?, &self.mz_reader);
80            .finalize(self.precursor_reader.get(index)?);
81        Ok(spectrum)
82    }
83
84    pub fn build() -> SpectrumReaderBuilder<ImC> {
85        SpectrumReaderBuilder::default()
86    }
87
88    pub fn get_all(&self) -> Vec<Result<Spectrum, TDFSpectrumReaderError>> {
89        let mut spectra: Vec<Result<Spectrum, TDFSpectrumReaderError>> = (0
90            ..self.len())
91            .into_par_iter()
92            .map(|index| self._get(index))
93            .collect();
94        spectra.sort_by_key(|x| match x {
95            Ok(spectrum) => match &spectrum.precursor() {
96                Some(precursor) => precursor.index(),
97                None => spectrum.index(),
98            },
99            Err(_) => 0,
100        });
101        spectra
102    }
103
104    pub fn len(&self) -> usize {
105        debug_assert_eq!(
106            self.precursor_reader.len(),
107            self.raw_spectrum_reader.len()
108        );
109        self.raw_spectrum_reader.len()
110    }
111
112    pub fn is_empty(&self) -> bool {
113        self.len() == 0
114    }
115
116    pub fn calibrate(&mut self) {}
117}
118
119impl<ImC: InvertibleConverter<ScanIndex, Im> + Send + Sync + std::fmt::Debug>
120    timsrust_core::utils::reader::Reader<Spectrum> for TDFSpectrumReader<ImC>
121{
122    type Error = TDFSpectrumReaderError;
123    fn get(&self, index: usize) -> Result<Spectrum, Self::Error> {
124        self._get(index)
125    }
126}
127
128impl<ImC: InvertibleConverter<ScanIndex, Im> + Send + Sync + std::fmt::Debug>
129    timsrust_core::utils::reader::IndexedReader<Spectrum>
130    for TDFSpectrumReader<ImC>
131{
132    type Iter = std::ops::Range<usize>;
133    fn iter(&self) -> Self::Iter {
134        0..self.len()
135    }
136}
137
138#[allow(private_interfaces)]
139#[derive(Debug, thiserror::Error)]
140pub enum TDFSpectrumReaderError {
141    #[error("{0}")]
142    SqlReaderError(#[from] SqlReaderError),
143    #[error("{0}")]
144    TDFPrecursorReaderError(#[from] TDFPrecursorReaderError),
145    #[error("{0}")]
146    MetadaReaderError(#[from] MetadataReaderError),
147    #[error("{0}")]
148    FrameReaderError(#[from] FrameReaderError),
149    #[error("{0}")]
150    RawSpectrumReaderError(#[from] RawSpectrumReaderError),
151    #[error("{0}")]
152    FileNotFound(String),
153    #[error("No precursor")]
154    NoPrecursor,
155    #[error("No path")]
156    NoPath,
157    #[error("No im_converter provided")]
158    NoImConverter,
159}
160
161pub struct SpectrumReaderBuilder<ImC> {
162    path: Option<TDFPath>,
163    config: SpectrumReaderConfig<ImC>,
164    im_converter: Option<Arc<ImC>>,
165}
166
167impl<ImC> Default for SpectrumReaderBuilder<ImC> {
168    fn default() -> Self {
169        Self {
170            path: None,
171            config: SpectrumReaderConfig::default(),
172            im_converter: None,
173        }
174    }
175}
176
177impl<ImC> Clone for SpectrumReaderBuilder<ImC> {
178    fn clone(&self) -> Self {
179        Self {
180            path: self.path.clone(),
181            config: self.config.clone(),
182            im_converter: self.im_converter.clone(),
183        }
184    }
185}
186
187impl<ImC> SpectrumReaderBuilder<ImC> {
188    pub fn with_path(&self, path: impl TDFPathLike) -> Self {
189        let path = Some(path.to_timstof_path().unwrap());
190        Self {
191            path,
192            ..self.clone()
193        }
194    }
195
196    pub fn with_config(&self, config: SpectrumReaderConfig<ImC>) -> Self {
197        Self {
198            config,
199            ..self.clone()
200        }
201    }
202
203    pub fn with_im_converter(&self, im_converter: Arc<ImC>) -> Self {
204        Self {
205            im_converter: Some(im_converter),
206            ..self.clone()
207        }
208    }
209}
210
211impl<ImC: InvertibleConverter<ScanIndex, Im> + Send + Sync + std::fmt::Debug>
212    SpectrumReaderBuilder<ImC>
213{
214    pub fn finalize(
215        self,
216    ) -> Result<TDFSpectrumReader<ImC>, TDFSpectrumReaderError> {
217        let path = match self.path {
218            None => return Err(TDFSpectrumReaderError::NoPath),
219            Some(path) => path,
220        };
221        let im_converter = match self.im_converter {
222            None => return Err(TDFSpectrumReaderError::NoImConverter),
223            Some(c) => c,
224        };
225        let mut spectrum_reader =
226            TDFSpectrumReader::new(path, self.config.clone(), im_converter)?;
227        if self.config.spectrum_processing_params.calibrate {
228            spectrum_reader.calibrate();
229        }
230        Ok(spectrum_reader)
231    }
232}
233
234#[derive(Debug, Clone, Copy)]
235pub struct SpectrumProcessingParams {
236    pub smoothing_window: u32,
237    pub centroiding_window: u32,
238    pub calibration_tolerance: f64,
239    pub calibrate: bool,
240}
241
242impl Default for SpectrumProcessingParams {
243    fn default() -> Self {
244        Self {
245            smoothing_window: 1,
246            centroiding_window: 1,
247            calibration_tolerance: 0.1,
248            calibrate: false,
249        }
250    }
251}
252
253#[derive(Debug)]
254pub struct SpectrumReaderConfig<ImC> {
255    pub spectrum_processing_params: SpectrumProcessingParams,
256    pub frame_splitting_params: FrameWindowSplittingConfiguration<ImC>,
257}
258
259impl<ImC> Default for SpectrumReaderConfig<ImC> {
260    fn default() -> Self {
261        Self {
262            spectrum_processing_params: SpectrumProcessingParams::default(),
263            frame_splitting_params: FrameWindowSplittingConfiguration::default(
264            ),
265        }
266    }
267}
268
269impl<ImC> Clone for SpectrumReaderConfig<ImC> {
270    fn clone(&self) -> Self {
271        Self {
272            spectrum_processing_params: self.spectrum_processing_params,
273            frame_splitting_params: self.frame_splitting_params.clone(),
274        }
275    }
276}