lfq_permutation_audit/support/
lfq_matrices.rs1use koth_ms::lfq::IntensityMatrix;
2use std::path::Path;
3
4pub fn matrices(m: &IntensityMatrix, folder: &Path) -> anyhow::Result<()> {
5 let meta = [
6 "massCalib",
7 "mz",
8 "charge",
9 "rtApex",
10 "im",
11 "combined_score",
12 "seed_run",
13 "n_contributing_runs",
14 ];
15 for (kind, name) in [
16 "consensus_features.tsv",
17 "intensity_matrix.tsv",
18 "qvalue_matrix.tsv",
19 "decoy_intensity_matrix.tsv",
20 ]
21 .iter()
22 .enumerate()
23 {
24 let mut out = csv::WriterBuilder::new()
25 .delimiter(b'\t')
26 .from_path(folder.join(name))?;
27 let mut header: Vec<String> = meta.iter().map(|s| s.to_string()).collect();
28 if kind == 0 {
29 header.extend(["n_runs_detected", "group_score", "group_qvalue"].map(String::from));
30 } else {
31 header.extend(m.run_names.clone());
32 }
33 out.write_record(header)?;
34 for (i, g) in m.consensus.iter().enumerate() {
35 let mut row = vec![
36 format!("{:.6}", g.neutral_mass),
37 format!("{:.6}", g.ref_mz),
38 g.charge.to_string(),
39 format!("{:.6}", g.ref_rt),
40 if g.ref_im == 0.0 {
41 String::new()
42 } else {
43 format!("{:.6}", g.ref_im)
44 },
45 format!("{:.6}", g.seed_combined_score),
46 m.run_names[g.seed_run_idx].clone(),
47 g.n_contributing_runs.to_string(),
48 ];
49 if kind == 0 {
50 row.extend([
51 (0..m.n_runs)
52 .filter(|&r| m.intensity(i, r) > 0.0)
53 .count()
54 .to_string(),
55 format!("{:.6}", g.group_score),
56 format!("{:.6}", g.group_qvalue),
57 ]);
58 } else {
59 for r in 0..m.n_runs {
60 let v = match kind {
61 1 => m.intensity(i, r),
62 2 => m.q_value(i, r),
63 _ => m.decoy_intensity(i, r),
64 };
65 row.push(if kind == 2 {
66 format!("{v:.4}")
67 } else if v > 0.0 {
68 format!("{v:.5e}")
69 } else {
70 "0".into()
71 });
72 }
73 }
74 out.write_record(row)?;
75 }
76 out.flush()?;
77 }
78 let mut audit = csv::WriterBuilder::new()
79 .delimiter(b'\t')
80 .from_path(folder.join("ownership.tsv"))?;
81 audit.write_record([
82 "feature_idx",
83 "run_idx",
84 "is_decoy",
85 "intensity",
86 "ownership_status",
87 "owned_samples",
88 "excluded_samples",
89 "competing_feature",
90 "apex_rt",
91 "bhattacharyya",
92 "coelution",
93 "preceding_signal_fraction",
94 ])?;
95 for e in &m.entries {
96 audit.write_record([
97 e.feature_idx.to_string(),
98 e.run_idx.to_string(),
99 e.is_decoy.to_string(),
100 e.intensity.to_string(),
101 e.ownership_status.to_string(),
102 e.owned_samples.to_string(),
103 e.excluded_samples.to_string(),
104 e.competing_feature
105 .map(|i| i.to_string())
106 .unwrap_or_default(),
107 e.apex_rt.to_string(),
108 e.spectral_bhattacharyya.to_string(),
109 e.coelution.to_string(),
110 e.preceding_signal_fraction.to_string(),
111 ])?;
112 }
113 audit.flush()?;
114 Ok(())
115}