lfq_member_geometry/
lfq_member_geometry.rs1use koth_ms::{
3 alignment::{align_runs, RunInput},
4 config::AlignConfig,
5 input::{check_batch_mobility_scales, discover_runs, read_features},
6};
7use std::{collections::HashSet, path::PathBuf};
8fn main() -> anyhow::Result<()> {
9 let args: Vec<_> = std::env::args().skip(1).collect();
10 anyhow::ensure!(
11 args.len() == 5,
12 "usage: lfq_member_geometry BATCH CONFIG MEMBERS_TSV OUT_TSV ID,ID"
13 );
14 let cfg = AlignConfig::from_toml(&PathBuf::from(&args[1]))?;
15 let paths = discover_runs(&PathBuf::from(&args[0]))?;
16 let runs: Vec<_> = paths
17 .iter()
18 .map(|r| {
19 Ok(RunInput {
20 name: r.name.clone(),
21 features: read_features(&r.features_path)?,
22 hills: Vec::new(),
23 scan_times: Vec::new(),
24 rt_bounds: None,
25 })
26 })
27 .collect::<anyhow::Result<_>>()?;
28 check_batch_mobility_scales(
29 paths
30 .iter()
31 .zip(&runs)
32 .map(|(p, r)| (p, r.features.as_slice())),
33 )?;
34 let alignment = align_runs(&runs, &cfg.alignment);
35 let ids: HashSet<usize> = args[4]
36 .split(',')
37 .map(str::parse)
38 .collect::<Result<_, _>>()?;
39 let mut input = csv::ReaderBuilder::new()
40 .delimiter(b'\t')
41 .from_path(&args[2])?;
42 let mut output = csv::WriterBuilder::new()
43 .delimiter(b'\t')
44 .from_path(&args[3])?;
45 output.write_record([
46 "candidate_id",
47 "run_id",
48 "feature_idx",
49 "mass",
50 "rt",
51 "im",
52 "quality",
53 "is_primary",
54 "neutron_offset",
55 ])?;
56 for row in input.records() {
57 let row = row?;
58 let id: usize = row[0].parse()?;
59 if !ids.contains(&id) {
60 continue;
61 }
62 let r: usize = row[1].parse()?;
63 let f: usize = row[2].parse()?;
64 let feat = &runs[r].features[f];
65 let mz = feat.monoisotopic_mz();
66 let rt = feat.feature.rt_apex();
67 let im = feat.feature.im_apex();
68 let (mz, rt, im) = if r == alignment.reference_idx {
69 (mz, rt, im)
70 } else {
71 let a = &alignment.alignments[&runs[r].name];
72 (a.correct_mz(mz, rt), a.warp_rt(rt), a.correct_im(im, rt))
73 };
74 let mass = (mz - 1.007276466621) * feat.feature.charge as f64;
75 output.write_record([
76 id.to_string(),
77 r.to_string(),
78 f.to_string(),
79 mass.to_string(),
80 rt.to_string(),
81 im.to_string(),
82 feat.combined_score.to_string(),
83 row[3].to_string(),
84 feat.neutron_offset.to_string(),
85 ])?;
86 }
87 output.flush()?;
88 Ok(())
89}