Skip to content

Commit

Permalink
Merge pull request #38 from theGreatHerrLebert/david@mixture
Browse files Browse the repository at this point in the history
David@mixture
  • Loading branch information
theGreatHerrLebert authored Oct 26, 2023
2 parents f9380c2 + 72c9bd3 commit 6906516
Show file tree
Hide file tree
Showing 11 changed files with 433 additions and 86 deletions.
2 changes: 2 additions & 0 deletions mscore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub use {

tims_frame::TimsFrame,
tims_frame::TimsFrameVectorized,
tims_frame::ToResolution,
tims_frame::Vectorized,

tims_slice::TimsSlice,
tims_slice::TimsSliceVectorized,
Expand Down
163 changes: 95 additions & 68 deletions mscore/src/tims_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ use itertools;

use crate::mz_spectrum::{MsType, MzSpectrum, IndexedMzSpectrum, TimsSpectrum};

pub trait ToResolution {
fn to_resolution(&self, resolution: i32) -> Self;
}

pub trait Vectorized<T> {
fn vectorized(&self, resolution: i32) -> T;
}

#[derive(Clone)]
pub struct ImsFrame {
pub retention_time: f64,
Expand Down Expand Up @@ -146,6 +154,7 @@ impl TimsFrame {
/// * `mz_max` - The maximum m/z value.
/// * `scan_min` - The minimum scan value.
/// * `scan_max` - The maximum scan value.
/// *
/// * `intensity_min` - The minimum intensity value.
/// * `intensity_max` - The maximum intensity value.
///
Expand All @@ -155,9 +164,9 @@ impl TimsFrame {
/// use mscore::{TimsFrame, MsType};
///
/// let frame = TimsFrame::new(1, MsType::Precursor, 100.0, vec![1, 2], vec![0.1, 0.2], vec![1000, 2000], vec![100.5, 200.5], vec![50.0, 60.0]);
/// let filtered_frame = frame.filter_ranged(100.0, 200.0, 1, 2, 50.0, 60.0);
/// let filtered_frame = frame.filter_ranged(100.0, 200.0, 1, 2, 0.0, 1.6, 50.0, 60.0);
/// ```
pub fn filter_ranged(&self, mz_min: f64, mz_max: f64, scan_min: i32, scan_max: i32, intensity_min: f64, intensity_max: f64) -> TimsFrame {
pub fn filter_ranged(&self, mz_min: f64, mz_max: f64, scan_min: i32, scan_max: i32, inv_mob_min: f64, inv_mob_max: f64, intensity_min: f64, intensity_max: f64) -> TimsFrame {

let mut scan_vec = Vec::new();
let mut mobility_vec = Vec::new();
Expand All @@ -166,7 +175,7 @@ impl TimsFrame {
let mut intensity_vec = Vec::new();

for (mz, intensity, scan, mobility, tof) in itertools::multizip((&self.ims_frame.mz, &self.ims_frame.intensity, &self.scan, &self.ims_frame.mobility, &self.tof)) {
if mz >= &mz_min && mz <= &mz_max && scan >= &scan_min && scan <= &scan_max && intensity >= &intensity_min && intensity <= &intensity_max {
if mz >= &mz_min && mz <= &mz_max && scan >= &scan_min && scan <= &scan_max && mobility >= &inv_mob_min && mobility <= &inv_mob_max && intensity >= &intensity_min && intensity <= &intensity_max {
scan_vec.push(*scan);
mobility_vec.push(*mobility);
tof_vec.push(*tof);
Expand All @@ -178,23 +187,79 @@ impl TimsFrame {
TimsFrame::new(self.frame_id, self.ms_type.clone(), self.ims_frame.retention_time, scan_vec, mobility_vec, tof_vec, mz_vec, intensity_vec)
}

///
/// Convert a given TimsFrame to a vector of TimsSpectrum.
///
/// # Arguments
///
/// * `resolution` - The resolution to which the m/z values should be rounded.
///
/// # Examples
///
/// ```
/// use mscore::{TimsSpectrum, TimsFrame, MsType};
///
/// let frame = TimsFrame::new(1, MsType::Precursor, 100.0, vec![1, 2], vec![0.1, 0.2], vec![1000, 2000], vec![100.5, 200.5], vec![50.0, 60.0]);
/// let low_res_frame = frame.to_resolution(1);
/// ```
pub fn to_resolution(&self, resolution: i32) -> TimsFrame {
pub fn to_windows(&self, window_length: f64, overlapping: bool, min_peaks: usize, min_intensity: f64) -> Vec<MzSpectrum> {

let spectra = self.to_tims_spectra();

let windows: Vec<_> = spectra.iter().map(|spectrum|
spectrum.spectrum.mz_spectrum.to_windows(window_length, overlapping, min_peaks, min_intensity))
.collect();

let mut result: Vec<MzSpectrum> = Vec::new();

for window in windows {
for (_, spectrum) in window {
result.push(spectrum);
}
}

result
}

}

impl fmt::Display for TimsFrame {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {

let (mz, i) = self.ims_frame.mz.iter()
.zip(&self.ims_frame.intensity)
.max_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal))
.unwrap();

write!(f, "TimsFrame(id: {}, type: {}, rt: {}, data points: {}, max by intensity: (mz: {}, intensity: {}))",
self.frame_id, self.ms_type, self.ims_frame.retention_time, self.scan.len(), format!("{:.3}", mz), i)
}
}

impl Vectorized<TimsFrameVectorized> for TimsFrame {
fn vectorized(&self, resolution: i32) -> TimsFrameVectorized {
let binned_frame = self.to_resolution(resolution);
// Translate the m/z values into integer indices
let indices: Vec<i32> = binned_frame.ims_frame.mz.iter().map(|&mz| (mz * 10f64.powi(resolution)).round() as i32).collect();
// Create a vector of values
return TimsFrameVectorized {
frame_id: self.frame_id,
ms_type: self.ms_type.clone(),
scan: binned_frame.scan,
tof: binned_frame.tof,
ims_frame: ImsFrameVectorized {
retention_time: binned_frame.ims_frame.retention_time,
mobility: binned_frame.ims_frame.mobility,
indices,
values: binned_frame.ims_frame.intensity,
resolution,
},
};
}
}

///
/// Convert a given TimsFrame to a vector of TimsSpectrum.
///
/// # Arguments
///
/// * `resolution` - The resolution to which the m/z values should be rounded.
///
/// # Examples
///
/// ```
/// use mscore::{TimsSpectrum, TimsFrame, MsType, ToResolution};
///
/// let frame = TimsFrame::new(1, MsType::Precursor, 100.0, vec![1, 2], vec![0.1, 0.2], vec![1000, 2000], vec![100.5, 200.5], vec![50.0, 60.0]);
/// let low_res_frame = frame.to_resolution(1);
/// ```
impl ToResolution for TimsFrame {
fn to_resolution(&self, resolution: i32) -> TimsFrame {
let factor = (10.0f64).powi(resolution);

// Using a tuple of (scan, mz_bin) as a key
Expand Down Expand Up @@ -242,64 +307,26 @@ impl TimsFrame {
},
}
}
}

pub fn to_windows(&self, window_length: f64, overlapping: bool, min_peaks: usize, min_intensity: f64) -> Vec<MzSpectrum> {

let spectra = self.to_tims_spectra();

let windows: Vec<_> = spectra.iter().map(|spectrum|
spectrum.spectrum.mz_spectrum.to_windows(window_length, overlapping, min_peaks, min_intensity))
.collect();

let mut result: Vec<MzSpectrum> = Vec::new();

for window in windows {
for (_, spectrum) in window {
result.push(spectrum);
}
}

result
}
pub fn vectorized(&self, resolution: i32) -> TimsFrameVectorized {
let binned_frame = self.to_resolution(resolution);
// Translate the m/z values into integer indices
let indices: Vec<i32> = binned_frame.ims_frame.mz.iter().map(|&mz| (mz * 10f64.powi(resolution)).round() as i32).collect();
// Create a vector of values
return TimsFrameVectorized {
frame_id: self.frame_id,
ms_type: self.ms_type.clone(),
scan: binned_frame.scan,
tof: binned_frame.tof,
ims_frame: ImsFrameVectorized {
retention_time: binned_frame.ims_frame.retention_time,
mobility: binned_frame.ims_frame.mobility,
indices,
values: binned_frame.ims_frame.intensity,
resolution,
},
};
}
#[derive(Clone)]
pub struct TimsFrameVectorized {
pub frame_id: i32,
pub ms_type: MsType,
pub scan: Vec<i32>,
pub tof: Vec<i32>,
pub ims_frame: ImsFrameVectorized,
}

impl fmt::Display for TimsFrame {
impl fmt::Display for TimsFrameVectorized {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {

let (mz, i) = self.ims_frame.mz.iter()
.zip(&self.ims_frame.intensity)
let (mz, i) = self.ims_frame.values.iter()
.zip(&self.ims_frame.values)
.max_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal))
.unwrap();

write!(f, "TimsFrame(id: {}, type: {}, rt: {}, data points: {}, max by intensity: (mz: {}, intensity: {}))",
self.frame_id, self.ms_type, self.ims_frame.retention_time, self.scan.len(), format!("{:.3}", mz), i)
}
}

#[derive(Clone)]
pub struct TimsFrameVectorized {
pub frame_id: i32,
pub ms_type: MsType,
pub scan: Vec<i32>,
pub tof: Vec<i32>,
pub ims_frame: ImsFrameVectorized,
}
8 changes: 4 additions & 4 deletions mscore/src/tims_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use itertools::multizip;
use crate::MsType;

use crate::mz_spectrum::{MzSpectrum};
use crate::tims_frame::{TimsFrame, TimsFrameVectorized};
use crate::tims_frame::{TimsFrame, TimsFrameVectorized, Vectorized, ToResolution};

#[derive(Clone)]
pub struct TimsSlice {
Expand Down Expand Up @@ -58,16 +58,16 @@ impl TimsSlice {
/// use mscore::TimsSlice;
///
/// let slice = TimsSlice::new(vec![]);
/// let filtered_slice = slice.filter_ranged(400.0, 2000.0, 0, 1000, 0.0, 100000.0, 4);
/// let filtered_slice = slice.filter_ranged(400.0, 2000.0, 0, 1000, 0.0, 100000.0, 0.0, 1.6, 4);
/// ```
pub fn filter_ranged(&self, mz_min: f64, mz_max: f64, scan_min: i32, scan_max: i32, intensity_min: f64, intensity_max: f64, num_threads: usize) -> TimsSlice {
pub fn filter_ranged(&self, mz_min: f64, mz_max: f64, scan_min: i32, scan_max: i32, inv_mob_min: f64, inv_mob_max: f64, intensity_min: f64, intensity_max: f64, num_threads: usize) -> TimsSlice {

let pool = ThreadPoolBuilder::new().num_threads(num_threads).build().unwrap(); // Set to the desired number of threads

// Use the thread pool
let filtered_frames = pool.install(|| {
let result: Vec<_> = self.frames.par_iter()
.map(|f| f.filter_ranged(mz_min, mz_max, scan_min, scan_max, intensity_min, intensity_max))
.map(|f| f.filter_ranged(mz_min, mz_max, scan_min, scan_max, inv_mob_min, inv_mob_max, intensity_min, intensity_max))
.collect();
result
});
Expand Down
Loading

0 comments on commit 6906516

Please sign in to comment.