pub struct ScoredFeature {
pub feature: Feature,
pub neutron_offset: i8,
pub isotope_score: f64,
pub cosine_score: f64,
pub combined_score: f64,
pub theoretical_pattern: Vec<f64>,
}Expand description
Feature with isotope pattern scoring applied.
Carries three distinct quality scores so downstream stages (alignment,
consensus grouping, LFQ filters) can filter on whichever makes sense for
their purpose. All three are bounded [0, 1]; higher = better.
Fields§
§feature: Feature§neutron_offset: i8Neutron offset applied: -1, 0, or 1. Non-zero means the observed monoisotopic peak is actually M+|offset|.
isotope_score: f64Isotope-pattern score: Bhattacharyya coefficient between the observed apex-scan isotope intensities and the theoretical averagine template. Measures “does the isotope envelope look like a peptide?”.
cosine_score: f64Chromatographic cosine score: mirror of feature.cosine_score —
the mean cosine similarity (in time domain) between adjacent isotope
hills. Measures “do the isotope hills co-elute?”.
combined_score: f64Combined score: isotope_score × cosine_score. The default
quality knob used by alignment, consensus grouping, and feature
retention. High requires both a good pattern match AND tight co-elution.
theoretical_pattern: Vec<f64>Theoretical averagine isotope pattern (normalized to sum=1)
Implementations§
Source§impl ScoredFeature
impl ScoredFeature
Sourcepub fn monoisotopic_mz(&self) -> f64
pub fn monoisotopic_mz(&self) -> f64
Corrected monoisotopic m/z (adjusted by neutron_offset).
Examples found in repository?
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}Sourcepub fn monoisotopic_neutral_mass(&self, polarity: Polarity) -> Option<f64>
pub fn monoisotopic_neutral_mass(&self, polarity: Polarity) -> Option<f64>
Corrected neutral monoisotopic mass.
Examples found in repository?
30fn uno_style(path: &std::path::Path, config: &KothConfig) {
31 // One call, everything owned in memory. No files touched.
32 let out = run_pipeline(path, config, &PipelineOptions::default()).expect("pipeline");
33
34 // uno searches MS1 features by neutral mass + charge + RT.
35 let searchable: Vec<&ScoredFeature> = out
36 .features
37 .iter()
38 .filter(|f| f.feature.charge > 0) // same set the features file would hold
39 .collect();
40
41 println!(
42 "[uno] {} hills, {} charged features available for MS1 search",
43 out.hills.len(),
44 searchable.len()
45 );
46 if let Some(top) = searchable.iter().max_by(|a, b| {
47 a.feature
48 .total_intensity()
49 .partial_cmp(&b.feature.total_intensity())
50 .unwrap()
51 }) {
52 println!(
53 "[uno] most intense: mass {:?} z{} score {:.3}",
54 top.monoisotopic_neutral_mass(koth_ms::Polarity::Positive),
55 top.feature.charge,
56 top.combined_score
57 );
58 }
59}Trait Implementations§
Source§impl Clone for ScoredFeature
impl Clone for ScoredFeature
Source§fn clone(&self) -> ScoredFeature
fn clone(&self) -> ScoredFeature
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for ScoredFeature
impl RefUnwindSafe for ScoredFeature
impl Send for ScoredFeature
impl Sync for ScoredFeature
impl Unpin for ScoredFeature
impl UnsafeUnpin for ScoredFeature
impl UnwindSafe for ScoredFeature
Blanket Implementations§
impl<T> Allocation for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.