Skip to content

Commit

Permalink
Merge pull request #43 from theGreatHerrLebert/david@mixture
Browse files Browse the repository at this point in the history
David@mixture
  • Loading branch information
theGreatHerrLebert authored Nov 9, 2023
2 parents d4a4a2e + 54d7f65 commit 7157adb
Show file tree
Hide file tree
Showing 16 changed files with 424 additions and 35 deletions.
16 changes: 16 additions & 0 deletions imspy/imspy/spectrum.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,22 @@ def intensity(self) -> NDArray[np.float64]:
"""
return self.__spec_ptr.intensity

def filter(self, mz_min: float = 0.0, mz_max: float = 2000.0, intensity_min: float = 0.0,
intensity_max: float = 1e9) -> 'IndexedMzSpectrum':
"""Filter the spectrum for a given m/z range and intensity range.
Args:
mz_min (float): Minimum m/z value.
mz_max (float): Maximum m/z value.
intensity_min (float, optional): Minimum intensity value. Defaults to 0.0.
intensity_max (float, optional): Maximum intensity value. Defaults to 1e9.
Returns:
IndexedMzSpectrum: Filtered spectrum.
"""
return IndexedMzSpectrum.from_py_indexed_mz_spectrum(
self.__spec_ptr.filter_ranged(mz_min, mz_max, intensity_min, intensity_max))

@property
def df(self) -> pd.DataFrame:
"""Data.
Expand Down
4 changes: 2 additions & 2 deletions imspy/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "imspy"
version = "0.2.2"
version = "0.2.5"
description = ""
authors = ["theGreatHerrLebert <[email protected]>"]
readme = "README.md"
Expand All @@ -11,7 +11,7 @@ pandas = ">=2.1"
numpy = ">=1.21"
tensorflow = ">=2.14"
tensorflow-probability = ">=0.22.1"
imspy-connector = ">=0.2.0"
imspy-connector = ">=0.2.5"

[build-system]
requires = ["poetry-core"]
Expand Down
4 changes: 2 additions & 2 deletions imspy_connector/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "imspy_connector"
version = "0.2.2"
name = "imspy-connector"
version = "0.2.5"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
4 changes: 3 additions & 1 deletion imspy_connector/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ mod py_handle;
mod py_mz_spectrum;
mod py_tims_frame;
mod py_tims_slice;
mod py_timstof_dda;

use pyo3::prelude::*;
use crate::py_handle::PyTimsDataHandle;
use crate::py_mz_spectrum::{PyMzSpectrum, PyIndexedMzSpectrum, PyTimsSpectrum, PyMzSpectrumVectorized};
use crate::py_tims_frame::{PyTimsFrame, PyTimsFrameVectorized};
use crate::py_tims_frame::{PyTimsFrame, PyTimsFrameVectorized, PyRawTimsFrame};
use crate::py_tims_slice::{PyTimsPlane, PyTimsSlice, PyTimsSliceVectorized};

#[pymodule]
Expand All @@ -17,6 +18,7 @@ fn imspy_connector(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PyIndexedMzSpectrum>()?;
m.add_class::<PyTimsSpectrum>()?;
m.add_class::<PyTimsFrame>()?;
m.add_class::<PyRawTimsFrame>()?;
m.add_class::<PyTimsFrameVectorized>()?;
m.add_class::<PyTimsSlice>()?;
m.add_class::<PyTimsSliceVectorized>()?;
Expand Down
8 changes: 8 additions & 0 deletions imspy_connector/src/py_mz_spectrum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ impl PyIndexedMzSpectrum {
pub fn intensity(&self, py: Python) -> Py<PyArray1<f64>> {
self.inner.mz_spectrum.intensity.clone().into_pyarray(py).to_owned()
}

pub fn filter_ranged(&self, mz_min: f64, mz_max: f64, intensity_min: f64, intensity_max: f64) -> PyResult<PyIndexedMzSpectrum> {
let filtered = self.inner.filter_ranged(mz_min, mz_max, intensity_min, intensity_max);
let py_filtered = PyIndexedMzSpectrum {
inner: filtered,
};
Ok(py_filtered)
}
}

#[pyclass]
Expand Down
64 changes: 63 additions & 1 deletion imspy_connector/src/py_tims_frame.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,72 @@
use pyo3::prelude::*;
use numpy::{PyArray1, IntoPyArray};
use mscore::{TimsFrame, ImsFrame, MsType, TimsFrameVectorized, ImsFrameVectorized, ToResolution, Vectorized};
use mscore::{TimsFrame, ImsFrame, MsType, TimsFrameVectorized, ImsFrameVectorized, ToResolution, Vectorized, RawTimsFrame};
use pyo3::types::PyList;

use crate::py_mz_spectrum::{PyIndexedMzSpectrum, PyMzSpectrum, PyTimsSpectrum};

#[pyclass]
#[derive(Clone)]
pub struct PyRawTimsFrame {
pub inner: RawTimsFrame,
}

#[pymethods]
impl PyRawTimsFrame {
#[new]
pub unsafe fn new(frame_id: i32,
ms_type: i32,
retention_time: f64,
scan: &PyArray1<i32>,
tof: &PyArray1<i32>,
intensity: &PyArray1<f64>) -> PyResult<Self> {
Ok(PyRawTimsFrame {
inner: RawTimsFrame {
frame_id,
retention_time,
ms_type: MsType::new(ms_type),
scan: scan.as_slice()?.to_vec(),
tof: tof.as_slice()?.to_vec(),
intensity: intensity.as_slice()?.to_vec(),
},
})
}

#[getter]
pub fn intensity(&self, py: Python) -> Py<PyArray1<f64>> {
self.inner.intensity.clone().into_pyarray(py).to_owned()
}
#[getter]
pub fn scan(&self, py: Python) -> Py<PyArray1<i32>> {
self.inner.scan.clone().into_pyarray(py).to_owned()
}

#[getter]
pub fn tof(&self, py: Python) -> Py<PyArray1<i32>> {
self.inner.tof.clone().into_pyarray(py).to_owned()
}

#[getter]
pub fn frame_id(&self) -> i32 {
self.inner.frame_id
}

#[getter]
pub fn ms_type_numeric(&self) -> i32 {
self.inner.ms_type.ms_type_numeric()
}

#[getter]
pub fn ms_type(&self) -> String {
self.inner.ms_type.to_string()
}

#[getter]
pub fn retention_time(&self) -> f64 {
self.inner.retention_time
}
}

#[pyclass]
#[derive(Clone)]
pub struct PyTimsFrame {
Expand Down
61 changes: 61 additions & 0 deletions imspy_connector/src/py_timstof_dda.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use pyo3::prelude::*;
use mscore::{ TimsDDAPrecursor };

#[pyclass]
#[derive(Clone)]
pub struct PyTimsDDAPrecursor {
pub inner: TimsDDAPrecursor,
}

#[pymethods]
impl PyTimsDDAPrecursor {
#[new]
pub fn new(
_py: Python,
id: u32,
parent_id: u32,
scan_num: u32,
mz_average: f32,
mz_most_intense: f32,
intensity: f32,
mz_mono_isotopic: Option<f32>,
charge: Option<u32>,
) -> PyResult<Self> {
let tims_dda_precursor = TimsDDAPrecursor {
id,
parent_id,
scan_num,
mz_average,
mz_most_intense,
intensity,
mz_mono_isotopic,
charge,
};

Ok(PyTimsDDAPrecursor { inner: tims_dda_precursor })
}

#[getter]
pub fn id(&self) -> u32 { self.inner.id }

#[getter]
pub fn parent_id(&self) -> u32 { self.inner.parent_id }

#[getter]
pub fn scan_num(&self) -> u32 { self.inner.scan_num }

#[getter]
pub fn mz_average(&self) -> f32 { self.inner.mz_average }

#[getter]
pub fn mz_most_intense(&self) -> f32 { self.inner.mz_most_intense }

#[getter]
pub fn intensity(&self) -> f32 { self.inner.intensity }

#[getter]
pub fn mz_mono_isotopic(&self) -> Option<f32> { self.inner.mz_mono_isotopic }

#[getter]
pub fn charge(&self) -> Option<u32> { self.inner.charge }
}
72 changes: 72 additions & 0 deletions mscore/src/chemistry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/// convert 1 over reduced ion mobility (1/k0) to CCS
///
/// Arguments:
///
/// * `one_over_k0` - 1 over reduced ion mobility (1/k0)
/// * `charge` - charge state of the ion
/// * `mz` - mass-over-charge of the ion
/// * `mass_gas` - mass of drift gas (N2)
/// * `temp` - temperature of the drift gas in C°
/// * `t_diff` - factor to translate from C° to K
///
/// Returns:
///
/// * `ccs` - collision cross-section
///
/// # Examples
///
/// ```
/// use mscore::one_over_reduced_mobility_to_ccs;
///
/// let ccs = one_over_reduced_mobility_to_ccs(0.5, 1000.0, 2, 28.013, 31.85, 273.15);
/// assert_eq!(ccs, 806.5918693771381);
/// ```
pub fn one_over_reduced_mobility_to_ccs(
one_over_k0: f64,
mz: f64,
charge: u32,
mass_gas: f64,
temp: f64,
t_diff: f64,
) -> f64 {
let summary_constant = 18509.8632163405;
let reduced_mass = (mz * charge as f64 * mass_gas) / (mz * charge as f64 + mass_gas);
summary_constant * charge as f64 / (reduced_mass * (temp + t_diff)).sqrt() / one_over_k0
}


/// convert CCS to 1 over reduced ion mobility (1/k0)
///
/// Arguments:
///
/// * `ccs` - collision cross-section
/// * `charge` - charge state of the ion
/// * `mz` - mass-over-charge of the ion
/// * `mass_gas` - mass of drift gas (N2)
/// * `temp` - temperature of the drift gas in C°
/// * `t_diff` - factor to translate from C° to K
///
/// Returns:
///
/// * `one_over_k0` - 1 over reduced ion mobility (1/k0)
///
/// # Examples
///
/// ```
/// use mscore::ccs_to_reduced_mobility;
///
/// let k0 = ccs_to_reduced_mobility(806.5918693771381, 1000.0, 2, 28.013, 31.85, 273.15);
/// assert_eq!(1.0 / k0, 0.5);
/// ```
pub fn ccs_to_reduced_mobility(
ccs: f64,
mz: f64,
charge: u32,
mass_gas: f64,
temp: f64,
t_diff: f64,
) -> f64 {
let summary_constant = 18509.8632163405;
let reduced_mass = (mz * charge as f64 * mass_gas) / (mz * charge as f64 + mass_gas);
((reduced_mass * (temp + t_diff)).sqrt() * ccs) / (summary_constant * charge as f64)
}
9 changes: 9 additions & 0 deletions mscore/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
pub mod mz_spectrum;
mod tims_frame;
mod tims_slice;
mod timstof_dda;
mod chemistry;

pub use {

chemistry::one_over_reduced_mobility_to_ccs,
chemistry::ccs_to_reduced_mobility,

mz_spectrum::MsType,

mz_spectrum::MzSpectrum,
Expand All @@ -17,6 +23,7 @@ pub use {
tims_frame::ImsFrame,
tims_frame::ImsFrameVectorized,

tims_frame::RawTimsFrame,
tims_frame::TimsFrame,
tims_frame::TimsFrameVectorized,
tims_frame::ToResolution,
Expand All @@ -28,4 +35,6 @@ pub use {
tims_slice::TimsSliceFlat,

tims_slice::TimsPlane,

timstof_dda::TimsDDAPrecursor,
};
15 changes: 15 additions & 0 deletions mscore/src/mz_spectrum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,21 @@ impl IndexedMzSpectrum {
}
}
}

pub fn filter_ranged(&self, mz_min: f64, mz_max: f64, intensity_min:f64, intensity_max: f64) -> Self {
let mut mz_vec: Vec<f64> = Vec::new();
let mut intensity_vec: Vec<f64> = Vec::new();
let mut index_vec: Vec<i32> = Vec::new();

for ((&mz, &intensity), &index) in self.mz_spectrum.mz.iter().zip(self.mz_spectrum.intensity.iter()).zip(self.index.iter()) {
if mz_min <= mz && mz <= mz_max && intensity >= intensity_min && intensity <= intensity_max {
mz_vec.push(mz);
intensity_vec.push(intensity);
index_vec.push(index);
}
}
IndexedMzSpectrum { index: index_vec, mz_spectrum: MzSpectrum { mz: mz_vec, intensity: intensity_vec } }
}
}

impl Display for IndexedMzSpectrum {
Expand Down
10 changes: 10 additions & 0 deletions mscore/src/tims_frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ pub trait Vectorized<T> {
fn vectorized(&self, resolution: i32) -> T;
}

#[derive(Clone)]
pub struct RawTimsFrame {
pub frame_id: i32,
pub retention_time: f64,
pub ms_type: MsType,
pub scan: Vec<i32>,
pub tof: Vec<i32>,
pub intensity: Vec<f64>,
}

#[derive(Clone)]
pub struct ImsFrame {
pub retention_time: f64,
Expand Down
11 changes: 11 additions & 0 deletions mscore/src/timstof_dda.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[derive(Clone)]
pub struct TimsDDAPrecursor {
pub id: u32,
pub parent_id: u32,
pub scan_num: u32,
pub mz_average: f32,
pub mz_most_intense: f32,
pub intensity: f32,
pub mz_mono_isotopic: Option<f32>,
pub charge: Option<u32>,
}
4 changes: 2 additions & 2 deletions rustdf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ path = "src/lib.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
libloading = "0.8"
libloading = "0.8.1"
rusqlite = "0.29.0"
lzf = "1.0.0"
zstd = "0.12.4"
zstd = "0.13.0"
byteorder = "1.4.3"
anyhow = "1.0.75"
mscore = {path = "../mscore"}
Loading

0 comments on commit 7157adb

Please sign in to comment.