mzdeisotope-map 0.3.6

A library to deisotope and charge state deconvolve mass spectra
Documentation
use std::collections::{hash_map::{Entry, Iter, IterMut, Keys}, HashMap};

use identity_hash::{BuildIdentityHasher, IdentityHashable};
use mzdeisotope::scorer::ScoreType;

use super::fit::{BuildIdentityHasherFitKey, FitKey};


#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct FeatureKey(pub usize);

impl IdentityHashable for FeatureKey {}

impl std::hash::Hash for FeatureKey {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        state.write_u64(self.0 as u64)
    }
}

impl From<usize> for FeatureKey {
    fn from(value: usize) -> Self {
        FeatureKey(value)
    }
}

#[derive(Debug)]
pub struct FeatureNode {
    pub key: FeatureKey,
    pub links: HashMap<FitKey, ScoreType, BuildIdentityHasherFitKey>,
}


impl FeatureNode {
    pub fn new<T: Into<FeatureKey>>(key: T) -> Self {
        Self {
            key: key.into(),
            links: HashMap::default(),
        }
    }

    pub fn contains(&self, fit: &FitKey) -> bool {
        self.links.contains_key(fit)
    }

    pub fn remove(&mut self, fit: &FitKey) -> Option<f32> {
        self.links.remove(fit)
    }
}

impl PartialEq for FeatureNode {
    fn eq(&self, other: &Self) -> bool {
        self.key == other.key
    }
}

impl Eq for FeatureNode {}
impl std::hash::Hash for FeatureNode {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.key.hash(state);
    }
}

#[derive(Debug, Default)]
pub struct FeatureGraph {
    pub nodes: HashMap<FeatureKey, FeatureNode, BuildIdentityHasher<FeatureKey>>,
}

impl FeatureGraph {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn reset(&mut self) {
        self.nodes.clear();
    }

    pub fn add_feature(&mut self, key: FeatureKey) {
        self.nodes
            .entry(key)
            .or_insert_with(|| FeatureNode::new(key));
    }

    pub fn get(&self, key: &FeatureKey) -> Option<&FeatureNode> {
        self.nodes.get(key)
    }

    pub fn get_mut(&mut self, key: &FeatureKey) -> Option<&mut FeatureNode> {
        self.nodes.get_mut(key)
    }

    pub fn get_or_create_mute(&mut self, key: FeatureKey) -> &mut FeatureNode {
        match self.nodes.entry(key) {
            Entry::Occupied(o) => o.into_mut(),
            Entry::Vacant(v) => v.insert(FeatureNode::new(key)),
        }
    }

    pub fn len(&self) -> usize {
        self.nodes.len()
    }

    pub fn is_empty(&self) -> bool {
        self.nodes.is_empty()
    }

    pub fn keys(&self) -> Keys<'_, FeatureKey, FeatureNode> {
        self.nodes.keys()
    }

    pub fn iter(&self) -> Iter<'_, FeatureKey, FeatureNode> {
        self.nodes.iter()
    }

    pub fn iter_mut(&mut self) -> IterMut<'_, FeatureKey, FeatureNode> {
        self.nodes.iter_mut()
    }

    pub fn drop_fit_dependence<'a, I: Iterator<Item = &'a FeatureKey>>(
        &mut self,
        feat_iter: I,
        fit_key: &FitKey,
    ) {
        for p in feat_iter {
            if let Some(p) = self.nodes.get_mut(p) {
                p.remove(fit_key);
            } else {
                tracing::warn!("Failed to remove {fit_key} for {p:?}");
            }
        }
    }
}