timsrust_tdf/frame_reader/
frame_info_reader.rs1use 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() + 1))
62 } else {
63 None
64 };
65 let (window_group, quad_settings) = if (acquisition
67 == AcquisitionType::DIAPASEF)
68 & (frame_info.ms_level() == MSLevel::MS2)
69 {
70 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 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}