1extern crate rusqlite;
2
3use rusqlite::{Connection, Result};
4use std::path::Path;
5
6#[derive(Debug, Clone)]
7pub struct DiaMsMisInfo {
8 pub frame_id: u32,
9 pub window_group: u32,
10}
11
12#[derive(Debug, Clone)]
13pub struct DiaMsMsWindow {
14 pub window_group: u32,
15 pub scan_num_begin: u32,
16 pub scan_num_end: u32,
17 pub isolation_mz: f64,
18 pub isolation_width: f64,
19 pub collision_energy: f64,
20}
21
22#[derive(Debug, Clone)]
23pub struct PasefMsMsMeta {
24 pub frame_id: i64,
25 pub scan_num_begin: i64,
26 pub scan_num_end: i64,
27 pub isolation_mz: f64,
28 pub isolation_width: f64,
29 pub collision_energy: f64,
30 pub precursor_id: i64,
31}
32
33#[derive(Debug, Clone)]
34pub struct DDAPrecursorMeta {
35 pub precursor_id: i64,
36 pub precursor_mz_highest_intensity: f64,
37 pub precursor_mz_average: f64,
38 pub precursor_mz_monoisotopic: Option<f64>,
39 pub precursor_charge: Option<i64>,
40 pub precursor_average_scan_number: f64,
41 pub precursor_total_intensity: f64,
42 pub precursor_frame_id: i64,
43}
44
45#[derive(Debug, Clone)]
46pub struct DDAPrecursor {
47 pub frame_id: i64,
48 pub precursor_id: i64,
49 pub mono_mz: Option<f64>,
50 pub highest_intensity_mz: f64,
51 pub average_mz: f64,
52 pub charge: Option<i64>,
53 pub inverse_ion_mobility: f64,
54 pub collision_energy: f64,
55 pub precuror_total_intensity: f64,
56 pub isolation_mz: f64,
57 pub isolation_width: f64,
58}
59
60#[derive(Debug, Clone)]
61pub struct DDAFragmentInfo {
62 pub frame_id: i64,
63 pub scan_begin: i64,
64 pub scan_end: i64,
65 pub isolation_mz: f64,
66 pub isolation_width: f64,
67 pub collision_energy: f64,
68 pub precursor_id: i64,
69}
70
71pub struct DIAFragmentFrameInfo {}
72
73pub struct DIAWindowGroupInfo {}
74
75#[derive(Debug)]
76pub struct GlobalMetaData {
77 pub schema_type: String,
78 pub schema_version_major: i64,
79 pub schema_version_minor: i64,
80 pub acquisition_software_vendor: String,
81 pub instrument_vendor: String,
82 pub closed_property: i64,
83 pub tims_compression_type: i64,
84 pub max_num_peaks_per_scan: i64,
85 pub mz_acquisition_range_lower: f64,
86 pub mz_acquisition_range_upper: f64,
87 pub one_over_k0_range_lower: f64,
88 pub one_over_k0_range_upper: f64,
89 pub tof_max_index: u32,
90}
91
92#[derive(Debug)]
93pub struct FrameMeta {
94 pub id: i64,
95 pub time: f64,
96 pub polarity: String,
97 pub scan_mode: i64,
98 pub ms_ms_type: i64,
99 pub tims_id: i64,
100 pub max_intensity: f64,
101 pub sum_intensity: f64,
102 pub num_scans: i64,
103 pub num_peaks: i64,
104 pub mz_calibration: i64,
105 pub t_1: f64,
106 pub t_2: f64,
107 pub tims_calibration: i64,
108 pub property_group: i64,
109 pub accumulation_time: f64,
110 pub ramp_time: f64,
111}
112
113struct GlobalMetaInternal {
114 key: String,
115 value: String,
116}
117
118pub fn read_dda_precursor_meta(
119 bruker_d_folder_name: &str,
120) -> Result<Vec<DDAPrecursorMeta>, Box<dyn std::error::Error>> {
121 let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
123 let conn = Connection::open(db_path)?;
124
125 let rows: Vec<&str> = vec![
127 "Id",
128 "LargestPeakMz",
129 "AverageMz",
130 "MonoisotopicMz",
131 "Charge",
132 "ScanNumber",
133 "Intensity",
134 "Parent",
135 ];
136 let query = format!("SELECT {} FROM Precursors", rows.join(", "));
137
138 let frames_rows: Result<Vec<DDAPrecursorMeta>, _> = conn
140 .prepare(&query)?
141 .query_map([], |row| {
142 Ok(DDAPrecursorMeta {
143 precursor_id: row.get(0)?,
144 precursor_mz_highest_intensity: row.get(1)?,
145 precursor_mz_average: row.get(2)?,
146 precursor_mz_monoisotopic: row.get(3)?, precursor_charge: row.get(4)?, precursor_average_scan_number: row.get(5)?,
149 precursor_total_intensity: row.get(6)?,
150 precursor_frame_id: row.get(7)?,
151 })
152 })?
153 .collect();
154
155 Ok(frames_rows?)
157}
158
159pub fn read_pasef_frame_ms_ms_info(
160 bruker_d_folder_name: &str,
161) -> Result<Vec<PasefMsMsMeta>, Box<dyn std::error::Error>> {
162 let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
164 let conn = Connection::open(db_path)?;
165
166 let rows: Vec<&str> = vec![
168 "Frame",
169 "ScanNumBegin",
170 "ScanNumEnd",
171 "IsolationMz",
172 "IsolationWidth",
173 "CollisionEnergy",
174 "Precursor",
175 ];
176 let query = format!("SELECT {} FROM PasefFrameMsMsInfo", rows.join(", "));
177
178 let frames_rows: Result<Vec<PasefMsMsMeta>, _> = conn
180 .prepare(&query)?
181 .query_map([], |row| {
182 Ok(PasefMsMsMeta {
183 frame_id: row.get(0)?,
184 scan_num_begin: row.get(1)?,
185 scan_num_end: row.get(2)?,
186 isolation_mz: row.get(3)?,
187 isolation_width: row.get(4)?,
188 collision_energy: row.get(5)?,
189 precursor_id: row.get(6)?,
190 })
191 })?
192 .collect();
193
194 Ok(frames_rows?)
196}
197
198pub fn read_global_meta_sql(
200 bruker_d_folder_name: &str,
201) -> Result<GlobalMetaData, Box<dyn std::error::Error>> {
202 let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
204 let conn = Connection::open(db_path)?;
205
206 let frames_rows: Result<Vec<GlobalMetaInternal>, _> = conn
208 .prepare("SELECT * FROM GlobalMetadata")?
209 .query_map([], |row| {
210 Ok(GlobalMetaInternal {
211 key: row.get(0)?,
212 value: row.get(1)?,
213 })
214 })?
215 .collect();
216
217 let mut global_meta = GlobalMetaData {
218 schema_type: String::new(),
219 schema_version_major: -1,
220 schema_version_minor: -1,
221 acquisition_software_vendor: String::new(),
222 instrument_vendor: String::new(),
223 closed_property: -1,
224 tims_compression_type: -1,
225 max_num_peaks_per_scan: -1,
226 mz_acquisition_range_lower: -1.0,
227 mz_acquisition_range_upper: -1.0,
228 one_over_k0_range_lower: -1.0,
229 one_over_k0_range_upper: -1.0,
230 tof_max_index: 0,
231 };
232
233 for row in frames_rows? {
235 match row.key.as_str() {
236 "SchemaType" => global_meta.schema_type = row.value,
237 "SchemaVersionMajor" => {
238 global_meta.schema_version_major = row.value.parse::<i64>().unwrap()
239 }
240 "SchemaVersionMinor" => {
241 global_meta.schema_version_minor = row.value.parse::<i64>().unwrap()
242 }
243 "AcquisitionSoftwareVendor" => global_meta.acquisition_software_vendor = row.value,
244 "InstrumentVendor" => global_meta.instrument_vendor = row.value,
245 "ClosedProperly" => global_meta.closed_property = row.value.parse::<i64>().unwrap(),
246 "TimsCompressionType" => {
247 global_meta.tims_compression_type = row.value.parse::<i64>().unwrap()
248 }
249 "MaxNumPeaksPerScan" => {
250 global_meta.max_num_peaks_per_scan = row.value.parse::<i64>().unwrap()
251 }
252 "MzAcqRangeLower" => {
253 global_meta.mz_acquisition_range_lower = row.value.parse::<f64>().unwrap()
254 }
255 "MzAcqRangeUpper" => {
256 global_meta.mz_acquisition_range_upper = row.value.parse::<f64>().unwrap()
257 }
258 "OneOverK0AcqRangeLower" => {
259 global_meta.one_over_k0_range_lower = row.value.parse::<f64>().unwrap()
260 }
261 "OneOverK0AcqRangeUpper" => {
262 global_meta.one_over_k0_range_upper = row.value.parse::<f64>().unwrap()
263 }
264 "DigitizerNumSamples" => {
265 global_meta.tof_max_index = (row.value.parse::<i64>().unwrap() + 1) as u32
266 }
267 _ => (),
268 }
269 }
270 Ok(global_meta)
272}
273
274pub fn read_meta_data_sql(
276 bruker_d_folder_name: &str,
277) -> Result<Vec<FrameMeta>, Box<dyn std::error::Error>> {
278 let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
280 let conn = Connection::open(db_path)?;
281
282 let rows: Vec<&str> = vec![
284 "Id",
285 "Time",
286 "ScanMode",
287 "Polarity",
288 "MsMsType",
289 "TimsId",
290 "MaxIntensity",
291 "SummedIntensities",
292 "NumScans",
293 "NumPeaks",
294 "MzCalibration",
295 "T1",
296 "T2",
297 "TimsCalibration",
298 "PropertyGroup",
299 "AccumulationTime",
300 "RampTime",
301 ];
302 let query = format!("SELECT {} FROM Frames", rows.join(", "));
303
304 let frames_rows: Result<Vec<FrameMeta>, _> = conn
306 .prepare(&query)?
307 .query_map([], |row| {
308 Ok(FrameMeta {
309 id: row.get(0)?,
310 time: row.get(1)?,
311 scan_mode: row.get(2)?,
312 polarity: row.get(3)?,
313 ms_ms_type: row.get(4)?,
314 tims_id: row.get(5)?,
315 max_intensity: row.get(6)?,
316 sum_intensity: row.get(7)?,
317 num_scans: row.get(8)?,
318 num_peaks: row.get(9)?,
319 mz_calibration: row.get(10)?,
320 t_1: row.get(11)?,
321 t_2: row.get(12)?,
322 tims_calibration: row.get(13)?,
323 property_group: row.get(14)?,
324 accumulation_time: row.get(15)?,
325 ramp_time: row.get(16)?,
326 })
327 })?
328 .collect();
329
330 Ok(frames_rows?)
332}
333
334pub fn read_dia_ms_ms_info(
335 bruker_d_folder_name: &str,
336) -> Result<Vec<DiaMsMisInfo>, Box<dyn std::error::Error>> {
337 let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
339 let conn = Connection::open(db_path)?;
340
341 let rows: Vec<&str> = vec!["Frame", "WindowGroup"];
343 let query = format!("SELECT {} FROM DiaFrameMsMsInfo", rows.join(", "));
344
345 let frames_rows: Result<Vec<DiaMsMisInfo>, _> = conn
347 .prepare(&query)?
348 .query_map([], |row| {
349 Ok(DiaMsMisInfo {
350 frame_id: row.get(0)?,
351 window_group: row.get(1)?,
352 })
353 })?
354 .collect();
355
356 Ok(frames_rows?)
358}
359
360pub fn read_dia_ms_ms_windows(
361 bruker_d_folder_name: &str,
362) -> Result<Vec<DiaMsMsWindow>, Box<dyn std::error::Error>> {
363 let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
365 let conn = Connection::open(db_path)?;
366
367 let rows: Vec<&str> = vec![
369 "WindowGroup",
370 "ScanNumBegin",
371 "ScanNumEnd",
372 "IsolationMz",
373 "IsolationWidth",
374 "CollisionEnergy",
375 ];
376 let query = format!("SELECT {} FROM DiaFrameMsMsWindows", rows.join(", "));
377
378 let frames_rows: Result<Vec<DiaMsMsWindow>, _> = conn
380 .prepare(&query)?
381 .query_map([], |row| {
382 Ok(DiaMsMsWindow {
383 window_group: row.get(0)?,
384 scan_num_begin: row.get(1)?,
385 scan_num_end: row.get(2)?,
386 isolation_mz: row.get(3)?,
387 isolation_width: row.get(4)?,
388 collision_energy: row.get(5)?,
389 })
390 })?
391 .collect();
392
393 Ok(frames_rows?)
395}