rustdf/data/
meta.rs

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    // Connect to the database
122    let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
123    let conn = Connection::open(db_path)?;
124
125    // prepare the query
126    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    // execute the query
139    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)?, // Now using Option<f64>
147                precursor_charge: row.get(4)?,          // Now using Option<i64>
148                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    // return the frames
156    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    // Connect to the database
163    let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
164    let conn = Connection::open(db_path)?;
165
166    // prepare the query
167    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    // execute the query
179    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    // return the frames
195    Ok(frames_rows?)
196}
197
198// Read the global meta data from the analysis.tdf file
199pub fn read_global_meta_sql(
200    bruker_d_folder_name: &str,
201) -> Result<GlobalMetaData, Box<dyn std::error::Error>> {
202    // Connect to the database
203    let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
204    let conn = Connection::open(db_path)?;
205
206    // execute the query
207    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    // go over the keys and parse values for the global meta data
234    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    // return global_meta
271    Ok(global_meta)
272}
273
274// Read the frame meta data from the analysis.tdf file
275pub fn read_meta_data_sql(
276    bruker_d_folder_name: &str,
277) -> Result<Vec<FrameMeta>, Box<dyn std::error::Error>> {
278    // Connect to the database
279    let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
280    let conn = Connection::open(db_path)?;
281
282    // prepare the query
283    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    // execute the query
305    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    // return the frames
331    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    // Connect to the database
338    let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
339    let conn = Connection::open(db_path)?;
340
341    // prepare the query
342    let rows: Vec<&str> = vec!["Frame", "WindowGroup"];
343    let query = format!("SELECT {} FROM DiaFrameMsMsInfo", rows.join(", "));
344
345    // execute the query
346    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    // return the frames
357    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    // Connect to the database
364    let db_path = Path::new(bruker_d_folder_name).join("analysis.tdf");
365    let conn = Connection::open(db_path)?;
366
367    // prepare the query
368    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    // execute the query
379    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    // return the frames
394    Ok(frames_rows?)
395}