Skip to main content

timsrust_tdf/
precursor_reader.rs

1mod dda;
2mod dia;
3
4use std::sync::Arc;
5
6use dda::{DDATDFPrecursorReader, DDATDFPrecursorReaderError};
7use dia::{DIATDFPrecursorReader, DIATDFPrecursorReaderError};
8use timsrust_core::utils::reader::Reader;
9use timsrust_core::{
10    AcquisitionType, Im, InvertibleConverter, Precursor, ScanIndex,
11};
12
13use crate::{
14    FrameWindowSplittingConfiguration, TDFPathLike,
15    file_readers::sql_reader::{
16        ReadableSqlTable, SqlReader, SqlReaderError, frames::SqlFrame,
17    },
18};
19
20use super::{TDFPath, TDFPathError};
21
22pub(crate) struct PrecursorReaderBuilder<ImC> {
23    path: Option<TDFPath>,
24    config: FrameWindowSplittingConfiguration<ImC>,
25    im_converter: Option<Arc<ImC>>,
26}
27
28impl<ImC> Default for PrecursorReaderBuilder<ImC> {
29    fn default() -> Self {
30        Self {
31            path: None,
32            config: FrameWindowSplittingConfiguration::default(),
33            im_converter: None,
34        }
35    }
36}
37
38impl<ImC> Clone for PrecursorReaderBuilder<ImC> {
39    fn clone(&self) -> Self {
40        Self {
41            path: self.path.clone(),
42            config: self.config.clone(),
43            im_converter: self.im_converter.clone(),
44        }
45    }
46}
47
48impl<ImC> PrecursorReaderBuilder<ImC> {
49    pub(crate) fn with_path(&self, path: impl TDFPathLike) -> Self {
50        let path = Some(path.to_timstof_path().unwrap());
51        Self {
52            path,
53            ..self.clone()
54        }
55    }
56
57    pub(crate) fn with_config(
58        &self,
59        config: FrameWindowSplittingConfiguration<ImC>,
60    ) -> Self {
61        Self {
62            config,
63            ..self.clone()
64        }
65    }
66
67    pub(crate) fn with_im_converter(&self, im_converter: Arc<ImC>) -> Self {
68        Self {
69            im_converter: Some(im_converter),
70            ..self.clone()
71        }
72    }
73}
74
75impl<ImC: InvertibleConverter<ScanIndex, Im> + Send + Sync + std::fmt::Debug>
76    PrecursorReaderBuilder<ImC>
77{
78    pub(crate) fn finalize(
79        self,
80    ) -> Result<TDFPrecursorReader<ImC>, TDFPrecursorReaderError> {
81        let path = match self.path {
82            None => return Err(TDFPrecursorReaderError::NoPath),
83            Some(path) => path,
84        };
85        let im_converter = match self.im_converter {
86            None => return Err(TDFPrecursorReaderError::NoImConverter),
87            Some(c) => c,
88        };
89        TDFPrecursorReader::new(path, self.config, im_converter)
90    }
91}
92
93#[derive(Debug)]
94#[allow(clippy::upper_case_acronyms)]
95enum InnerPrecursorReader<ImC> {
96    DDAPASEF(DDATDFPrecursorReader<ImC>),
97    DIAPASEF(DIATDFPrecursorReader<ImC>),
98}
99
100impl<ImC: InvertibleConverter<ScanIndex, Im>> InnerPrecursorReader<ImC> {
101    fn len(&self) -> usize {
102        match self {
103            InnerPrecursorReader::DDAPASEF(reader) => reader.len(),
104            InnerPrecursorReader::DIAPASEF(reader) => reader.len(),
105        }
106    }
107}
108
109#[derive(Debug)]
110pub struct TDFPrecursorReader<ImC> {
111    precursor_reader: InnerPrecursorReader<ImC>,
112}
113
114impl<ImC: InvertibleConverter<ScanIndex, Im> + Send + Sync + std::fmt::Debug>
115    TDFPrecursorReader<ImC>
116{
117    pub(crate) fn build() -> PrecursorReaderBuilder<ImC> {
118        PrecursorReaderBuilder::default()
119    }
120
121    pub fn len(&self) -> usize {
122        self.precursor_reader.len()
123    }
124
125    pub fn is_empty(&self) -> bool {
126        self.len() == 0
127    }
128
129    pub fn new(
130        path: impl TDFPathLike,
131        splitting_strategy: FrameWindowSplittingConfiguration<ImC>,
132        im_converter: Arc<ImC>,
133    ) -> Result<Self, TDFPrecursorReaderError> {
134        let tdf_sql_reader = SqlReader::open(&path)?;
135        let sql_frames = SqlFrame::from_sql_reader(&tdf_sql_reader)?;
136        let acquisition_type = if sql_frames.iter().any(|f| f.scan_mode == 8) {
137            AcquisitionType::DDAPASEF
138        } else if sql_frames.iter().any(|f| f.scan_mode == 9) {
139            AcquisitionType::DIAPASEF
140        } else {
141            AcquisitionType::Unknown
142        };
143        let precursor_reader = match acquisition_type {
144            AcquisitionType::DDAPASEF => InnerPrecursorReader::DDAPASEF(
145                DDATDFPrecursorReader::new(&path, im_converter)?,
146            ),
147            AcquisitionType::DIAPASEF => {
148                InnerPrecursorReader::DIAPASEF(DIATDFPrecursorReader::new(
149                    path,
150                    splitting_strategy,
151                    im_converter,
152                )?)
153            },
154            acquisition_type => {
155                return Err(TDFPrecursorReaderError::UnsupportedAcquisition(
156                    format!("{:?}", acquisition_type),
157                ));
158            },
159        };
160        Ok(Self { precursor_reader })
161    }
162}
163
164impl<ImC: InvertibleConverter<ScanIndex, Im>> Reader<Precursor>
165    for TDFPrecursorReader<ImC>
166{
167    type Error = TDFPrecursorReaderError;
168    fn get(&self, index: usize) -> Result<Precursor, Self::Error> {
169        match self.precursor_reader {
170            InnerPrecursorReader::DDAPASEF(ref reader) => {
171                Ok(reader.get(index)?)
172            },
173            InnerPrecursorReader::DIAPASEF(ref reader) => {
174                Ok(reader.get(index)?)
175            },
176        }
177    }
178}
179
180#[allow(private_interfaces)]
181#[derive(Debug, thiserror::Error)]
182pub enum TDFPrecursorReaderError {
183    #[error("{0}")]
184    SqlReaderError(#[from] SqlReaderError),
185    #[error("{0}")]
186    DDATDFPrecursorReaderError(#[from] DDATDFPrecursorReaderError),
187    #[error("{0}")]
188    DIATDFPrecursorReaderError(#[from] DIATDFPrecursorReaderError),
189    #[error("Invalid acquistion type for precursor reader: {0}")]
190    UnsupportedAcquisition(String),
191    #[error("{0}")]
192    TDFPathError(#[from] TDFPathError),
193    #[error("No path provided for precursor reader")]
194    NoPath,
195    #[error("No im_converter provided for precursor reader")]
196    NoImConverter,
197}