Skip to main content

timsrust_tdf/frame_reader/
frame_info_reader.rs

1use std::{collections::HashMap, sync::Arc};
2
3use timsrust_core::{
4    AcquisitionType, FrameInfo, MSLevel, QuadrupoleSettings,
5    utils::reader::{IndexedReader, Reader},
6};
7
8use crate::{
9    QuadrupoleSettingsReader, QuadrupoleSettingsReaderError, TDFPathLike,
10    file_readers::sql_reader::{
11        ReadableSqlTable, SqlReader, SqlReaderError,
12        frame_groups::SqlWindowGroup, frames::SqlFrame,
13    },
14};
15
16#[derive(Debug)]
17pub struct FrameInfoReader {
18    frame_infos: HashMap<usize, FrameInfo>,
19    offsets: HashMap<usize, usize>,
20    acquisition: AcquisitionType,
21}
22
23impl FrameInfoReader {
24    pub fn new(
25        path: impl TDFPathLike,
26    ) -> Result<Self, FrameReaderErrorInternal> {
27        let tdf_sql_reader = SqlReader::open(&path)?;
28        let sql_frames = SqlFrame::from_sql_reader(&tdf_sql_reader)?;
29        let acquisition = if sql_frames.iter().any(|x| x.msms_type == 8) {
30            AcquisitionType::DDAPASEF
31        } else if sql_frames.iter().any(|x| x.msms_type == 9) {
32            AcquisitionType::DIAPASEF
33        } else {
34            AcquisitionType::Unknown
35        };
36        let mut window_groups = vec![0; sql_frames.len()];
37        let quadrupole_settings;
38        if acquisition == AcquisitionType::DIAPASEF {
39            for window_group in
40                SqlWindowGroup::from_sql_reader(&tdf_sql_reader)?
41            {
42                window_groups[window_group.frame - 1] =
43                    window_group.window_group;
44            }
45            quadrupole_settings = QuadrupoleSettingsReader::new(&path)?;
46        } else {
47            quadrupole_settings = vec![];
48        }
49        let quadrupole_settings = quadrupole_settings
50            .into_iter()
51            .map(Arc::new)
52            .collect::<Vec<_>>();
53        let mut offsets = HashMap::new();
54        let frame_infos = sql_frames
55            .into_iter()
56            .enumerate()
57            .map(|(index, sql_frame)| {
58                offsets.insert(sql_frame.id, sql_frame.binary_offset);
59                let mut frame_info = FrameInfo::from(sql_frame);
60                let cycle_index = if acquisition == AcquisitionType::DIAPASEF {
61                    Some(index / quadrupole_settings.len())
62                } else {
63                    None
64                };
65                // dbg!(cycle_index);
66                let (window_group, quad_settings) = if (acquisition
67                    == AcquisitionType::DIAPASEF)
68                    & (frame_info.ms_level() == MSLevel::MS2)
69                {
70                    // TODO should be refactored out to quadrupole reader
71                    let window_group = window_groups[index];
72                    let quad_settings =
73                        quadrupole_settings[window_group as usize - 1].clone();
74                    (window_group as u8, quad_settings)
75                } else {
76                    (
77                        frame_info.window_group(),
78                        frame_info.quadrupole_settings().clone(),
79                    )
80                };
81                frame_info = FrameInfo::new(
82                    quad_settings,
83                    frame_info.index(),
84                    frame_info.rt_in_seconds(),
85                    frame_info.intensity_correction_factor(),
86                    acquisition,
87                    frame_info.ms_level(),
88                    window_group,
89                    cycle_index,
90                );
91                (frame_info.index(), frame_info)
92            })
93            .collect::<HashMap<_, _>>();
94        let reader = Self {
95            frame_infos,
96            offsets,
97            acquisition,
98        };
99        Ok(reader)
100    }
101
102    // pub(crate) fn get_offset(
103    //     &self,
104    //     index: usize,
105    // ) -> Result<usize, FrameReaderErrorInternal> {
106    //     self.offsets
107    //         .get(&index)
108    //         .cloned()
109    //         .ok_or(FrameReaderErrorInternal::IndexOutOfBounds(index))
110    // }
111
112    pub fn get_acquisition(&self) -> AcquisitionType {
113        self.acquisition
114    }
115}
116
117impl From<SqlFrame> for FrameInfo {
118    fn from(sql_frame: SqlFrame) -> Self {
119        FrameInfo::new(
120            Arc::new(QuadrupoleSettings::default()),
121            sql_frame.id,
122            sql_frame.rt,
123            1000.0 / sql_frame.accumulation_time,
124            AcquisitionType::Unknown,
125            MSLevel::read_from_msms_type(sql_frame.msms_type),
126            0,
127            None,
128        )
129    }
130}
131
132impl Reader<FrameInfo> for FrameInfoReader {
133    type Error = FrameReaderErrorInternal;
134
135    fn get(
136        &self,
137        index: usize,
138    ) -> Result<timsrust_core::FrameInfo, Self::Error> {
139        self.frame_infos
140            .get(&index)
141            .cloned()
142            .ok_or(FrameReaderErrorInternal::IndexOutOfBounds(index))
143    }
144}
145
146impl FrameInfoReader {
147    pub(crate) fn offsets_map(
148        &self,
149    ) -> std::collections::HashMap<usize, usize> {
150        self.offsets.clone()
151    }
152}
153
154impl IndexedReader<FrameInfo> for FrameInfoReader {
155    type Iter = std::vec::IntoIter<usize>;
156    fn iter(&self) -> Self::Iter {
157        self.frame_infos
158            .keys()
159            .copied()
160            .collect::<Vec<_>>()
161            .into_iter()
162    }
163}
164
165#[allow(private_interfaces)]
166#[derive(Debug, thiserror::Error)]
167pub enum FrameReaderErrorInternal {
168    #[error("{0}")]
169    FileNotFound(String),
170    #[error("{0}")]
171    SqlReaderError(#[from] SqlReaderError),
172    #[error("Corrupt Frame")]
173    CorruptFrame,
174    #[error("{0}")]
175    QuadrupoleSettingsReaderError(#[from] QuadrupoleSettingsReaderError),
176    #[error("Index out of bounds {0}")]
177    IndexOutOfBounds(usize),
178    #[error("Compression type {0} not understood")]
179    CompressionTypeError(u8),
180}