rustdf 0.3.3

A Rust library for interacting with Bruker TDF formatted Raw Data.
use mscore::data::peptide::PeptideSequence;
use mscore::data::spectrum::{MsType, MzSpectrum};
use rand::distributions::{Distribution, Uniform};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SignalDistribution {
    pub mean: f32,
    pub variance: f32,
    pub error: f32,
    pub occurrence: Vec<u32>,
    pub abundance: Vec<f32>,
}

impl SignalDistribution {
    pub fn new(
        mean: f32,
        variance: f32,
        error: f32,
        occurrence: Vec<u32>,
        abundance: Vec<f32>,
    ) -> Self {
        SignalDistribution {
            mean,
            variance,
            error,
            occurrence,
            abundance,
        }
    }

    pub fn add_noise(&self, noise_level: f32) -> Vec<f32> {
        let mut rng = rand::thread_rng();
        let noise_dist = Uniform::new(0.0, noise_level);

        let noise: Vec<f32> = self
            .abundance
            .iter()
            .map(|_| noise_dist.sample(&mut rng))
            .collect();
        let noise_relative: Vec<f32> = self
            .abundance
            .iter()
            .zip(noise.iter())
            .map(|(&abu, &noise)| abu * noise)
            .collect();
        let noised_signal: Vec<f32> = self
            .abundance
            .iter()
            .zip(noise_relative.iter())
            .map(|(&abu, &noise_rel)| abu + noise_rel)
            .collect();

        let sum_noised_signal: f32 = noised_signal.iter().sum();
        let sum_rt_abu: f32 = self.abundance.iter().sum();

        noised_signal
            .iter()
            .map(|&x| (x / sum_noised_signal) * sum_rt_abu)
            .collect()
    }
}

#[derive(Debug, Clone)]
pub struct PeptidesSim {
    pub protein_id: u32,
    pub peptide_id: u32,
    pub sequence: PeptideSequence,
    pub proteins: String,
    pub decoy: bool,
    pub missed_cleavages: i8,
    pub n_term: Option<bool>,
    pub c_term: Option<bool>,
    pub mono_isotopic_mass: f32,
    pub retention_time: f32,
    pub events: f32,
    pub frame_start: u32,
    pub frame_end: u32,
    pub frame_distribution: SignalDistribution,
}

impl PeptidesSim {
    pub fn new(
        protein_id: u32,
        peptide_id: u32,
        sequence: String,
        proteins: String,
        decoy: bool,
        missed_cleavages: i8,
        n_term: Option<bool>,
        c_term: Option<bool>,
        mono_isotopic_mass: f32,
        retention_time: f32,
        events: f32,
        frame_start: u32,
        frame_end: u32,
        frame_occurrence: Vec<u32>,
        frame_abundance: Vec<f32>,
    ) -> Self {
        PeptidesSim {
            protein_id,
            peptide_id,
            sequence: PeptideSequence::new(sequence, Some(peptide_id as i32)),
            proteins,
            decoy,
            missed_cleavages,
            n_term,
            c_term,
            mono_isotopic_mass,
            retention_time,
            events,
            frame_start,
            frame_end,
            frame_distribution: SignalDistribution::new(
                0.0,
                0.0,
                0.0,
                frame_occurrence,
                frame_abundance,
            ),
        }
    }
}

#[derive(Debug, Clone)]
pub struct WindowGroupSettingsSim {
    pub window_group: u32,
    pub scan_start: u32,
    pub scan_end: u32,
    pub isolation_mz: f32,
    pub isolation_width: f32,
    pub collision_energy: f32,
}

impl WindowGroupSettingsSim {
    pub fn new(
        window_group: u32,
        scan_start: u32,
        scan_end: u32,
        isolation_mz: f32,
        isolation_width: f32,
        collision_energy: f32,
    ) -> Self {
        WindowGroupSettingsSim {
            window_group,
            scan_start,
            scan_end,
            isolation_mz,
            isolation_width,
            collision_energy,
        }
    }
}

#[derive(Debug, Clone)]
pub struct FrameToWindowGroupSim {
    pub frame_id: u32,
    pub window_group: u32,
}

impl FrameToWindowGroupSim {
    pub fn new(frame_id: u32, window_group: u32) -> Self {
        FrameToWindowGroupSim {
            frame_id,
            window_group,
        }
    }
}

#[derive(Debug, Clone)]
pub struct IonSim {
    pub ion_id: u32,
    pub peptide_id: u32,
    pub sequence: String,
    pub charge: i8,
    pub relative_abundance: f32,
    pub mobility: f32,
    pub simulated_spectrum: MzSpectrum,
    pub scan_distribution: SignalDistribution,
}

impl IonSim {
    pub fn new(
        ion_id: u32,
        peptide_id: u32,
        sequence: String,
        charge: i8,
        relative_abundance: f32,
        mobility: f32,
        simulated_spectrum: MzSpectrum,
        scan_occurrence: Vec<u32>,
        scan_abundance: Vec<f32>,
    ) -> Self {
        IonSim {
            ion_id,
            peptide_id,
            sequence,
            charge,
            relative_abundance,
            mobility,
            simulated_spectrum,
            scan_distribution: SignalDistribution::new(
                0.0,
                0.0,
                0.0,
                scan_occurrence,
                scan_abundance,
            ),
        }
    }
}

#[derive(Debug, Clone)]
pub struct ScansSim {
    pub scan: u32,
    pub mobility: f32,
}

impl ScansSim {
    pub fn new(scan: u32, mobility: f32) -> Self {
        ScansSim { scan, mobility }
    }
}

#[derive(Debug, Clone)]
pub struct FramesSim {
    pub frame_id: u32,
    pub time: f32,
    pub ms_type: i64,
}

impl FramesSim {
    pub fn new(frame_id: u32, time: f32, ms_type: i64) -> Self {
        FramesSim {
            frame_id,
            time,
            ms_type,
        }
    }
    pub fn parse_ms_type(&self) -> MsType {
        match self.ms_type {
            0 => MsType::Precursor,
            8 => MsType::FragmentDda,
            9 => MsType::FragmentDia,
            _ => MsType::Unknown,
        }
    }
}

pub struct FragmentIonSim {
    pub peptide_id: u32,
    pub ion_id: u32,
    pub collision_energy: f64,
    pub charge: i8,
    pub indices: Vec<u32>,
    pub values: Vec<f64>,
}

impl FragmentIonSim {
    pub fn new(
        peptide_id: u32,
        ion_id: u32,
        collision_energy: f64,
        charge: i8,
        indices: Vec<u32>,
        values: Vec<f64>,
    ) -> Self {
        FragmentIonSim {
            peptide_id,
            ion_id,
            charge,
            collision_energy,
            indices,
            values,
        }
    }

    pub fn to_dense(&self, length: usize) -> Vec<f64> {
        let mut dense = vec![0.0; length];
        for (i, &idx) in self.indices.iter().enumerate() {
            dense[idx as usize] = self.values[i];
        }
        dense
    }
}