Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

David@mixture #44

Merged
merged 7 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions imspy/imspy/dda.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import numpy as np
import pandas as pd

import imspy_connector as pims

from imspy.spectrum import IndexedMzSpectrum


class FragmentDDA:
def __init__(self, frame_id: int, precursor_id: int, selected_fragment: IndexedMzSpectrum):
self._fragment_ptr = pims.PyTimsFragmentDDA(frame_id, precursor_id, selected_fragment.get_spec_ptr())

@classmethod
def from_py_tims_fragment_dda(cls, fragment: pims.PyTimsFragmentDDA):
instance = cls.__new__(cls)
instance._fragment_ptr = fragment
return instance

@property
def frame_id(self) -> int:
return self._fragment_ptr.frame_id

@property
def precursor_id(self) -> int:
return self._fragment_ptr.precursor_id

@property
def selected_fragment(self) -> IndexedMzSpectrum:
return IndexedMzSpectrum.from_py_indexed_mz_spectrum(self._fragment_ptr.selected_fragment)

def __repr__(self):
return f"FragmentDDA(frame_id={self.frame_id}, precursor_id={self.precursor_id}, " \
f"selected_fragment={self.selected_fragment})"

def get_fragment_ptr(self):
return self._fragment_ptr

44 changes: 34 additions & 10 deletions imspy/imspy/handle.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from abc import ABC

from imspy.dda import FragmentDDA
from imspy.frame import TimsFrame
from imspy.slice import TimsSlice

Expand All @@ -21,19 +22,21 @@ def __init__(self, data_path: str):
Args:
data_path (str): Path to the data.
"""
self.__dataset = None
self.binary_path = None

self.data_path = data_path
self.bp: List[str] = obb.get_so_paths()
self.meta_data = self.__load_meta_data()
self.precursor_frames = self.meta_data[self.meta_data["MsMsType"] == 0].Id.values.astype(np.int32)
self.fragment_frames = self.meta_data[self.meta_data["MsMsType"] > 0].Id.values.astype(np.int32)
self.__handle = None
self.__current_index = 1

# Try to load the data with the first binary found
appropriate_found = False
for so_path in self.bp:
for so_path in obb.get_so_paths():
try:
self.__handle = pims.PyTimsDataHandle(self.data_path, so_path)
self.__dataset = pims.PyTimsDataset(self.data_path, so_path)
self.binary_path = so_path
appropriate_found = True
break
except Exception:
Expand All @@ -48,7 +51,7 @@ def acquisition_mode(self) -> str:
Returns:
str: Acquisition mode.
"""
return self.__handle.get_acquisition_mode_as_string()
return self.__dataset.get_acquisition_mode_as_string()

@property
def acquisition_mode_numerical(self) -> int:
Expand All @@ -57,7 +60,7 @@ def acquisition_mode_numerical(self) -> int:
Returns:
int: Acquisition mode as a numerical value.
"""
return self.__handle.get_acquisition_mode()
return self.__dataset.get_acquisition_mode()

@property
def frame_count(self) -> int:
Expand All @@ -66,7 +69,7 @@ def frame_count(self) -> int:
Returns:
int: Number of frames.
"""
return self.__handle.frame_count
return self.__dataset.frame_count

def __load_meta_data(self) -> pd.DataFrame:
"""Get the meta data.
Expand All @@ -85,7 +88,7 @@ def get_tims_frame(self, frame_id: int) -> TimsFrame:
Returns:
TimsFrame: TimsFrame.
"""
return TimsFrame.from_py_tims_frame(self.__handle.get_tims_frame(frame_id))
return TimsFrame.from_py_tims_frame(self.__dataset.get_frame(frame_id))

def get_tims_slice(self, frame_ids: NDArray[np.int32]) -> TimsSlice:
"""Get a TimsFrame.
Expand All @@ -96,14 +99,14 @@ def get_tims_slice(self, frame_ids: NDArray[np.int32]) -> TimsSlice:
Returns:
TimsFrame: TimsFrame.
"""
return TimsSlice.from_py_tims_slice(self.__handle.get_tims_slice(frame_ids))
return TimsSlice.from_py_tims_slice(self.__dataset.get_slice(frame_ids))

def __iter__(self):
return self

def __next__(self):
if self.__current_index <= self.frame_count:
frame_ptr = self.__handle.get_tims_frame(self.__current_index)
frame_ptr = self.__dataset.get_frame(self.__current_index)
self.__current_index += 1
if frame_ptr is not None:
return TimsFrame.from_py_tims_frame(frame_ptr)
Expand All @@ -120,6 +123,11 @@ def __getitem__(self, index):


class TimsDatasetDDA(TimsDataset):

def __init__(self, data_path: str):
super().__init__(data_path=data_path)
self.__dataset = pims.PyTimsDatasetDDA(self.data_path, self.binary_path)

@property
def selected_precursors(self):
"""Get precursors selected for fragmentation.
Expand All @@ -139,8 +147,24 @@ def pasef_meta_data(self):
return pd.read_sql_query("SELECT * from PasefFrameMsMsInfo",
sqlite3.connect(self.data_path + "/analysis.tdf"))

def get_pasef_fragments(self):
"""Get PASEF fragments.

Args:
num_threads (int, optional): Number of threads. Defaults to 4.

Returns:
List[FragmentDDA]: List of PASEF fragments.
"""
pasef_fragments = self.__dataset.get_pasef_fragments(1)
return [FragmentDDA.from_py_tims_fragment_dda(fragment) for fragment in pasef_fragments]


class TimsDatasetDIA(TimsDataset):
def __init__(self, data_path: str):
super().__init__(data_path=data_path)
self.__dataset = pims.PyTimsDatasetDIA(self.data_path, self.binary_path)

@property
def pasef_meta_data(self):
"""Get PASEF meta data for DIA.
Expand Down
8 changes: 8 additions & 0 deletions imspy/imspy/spectrum.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ def df(self) -> pd.DataFrame:

return pd.DataFrame({'index': self.index, 'mz': self.mz, 'intensity': self.intensity})

def get_spec_ptr(self) -> pims.PyIndexedMzSpectrum:
"""Get the spec_ptr.

Returns:
pims.PyIndexedMzSpectrum: spec_ptr.
"""
return self.__spec_ptr

def __repr__(self):
return f"IndexedMzSpectrum(num_peaks={len(self.index)})"

Expand Down
12 changes: 8 additions & 4 deletions imspy_connector/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
mod py_handle;
mod py_dataset;
mod py_mz_spectrum;
mod py_tims_frame;
mod py_tims_slice;
mod py_timstof_dda;
mod py_dda;
mod py_dia;

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

#[pymodule]
fn imspy_connector(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PyTimsDataHandle>()?;
m.add_class::<PyTimsDataset>()?;
m.add_class::<PyTimsDatasetDDA>()?;
m.add_class::<PyMzSpectrum>()?;
m.add_class::<PyMzSpectrumVectorized>()?;
m.add_class::<PyIndexedMzSpectrum>()?;
Expand All @@ -23,5 +26,6 @@ fn imspy_connector(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PyTimsSlice>()?;
m.add_class::<PyTimsSliceVectorized>()?;
m.add_class::<PyTimsPlane>()?;
m.add_class::<PyTimsFragmentDDA>()?;
Ok(())
}
44 changes: 44 additions & 0 deletions imspy_connector/src/py_dataset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use pyo3::prelude::*;
use rustdf::data::dataset::TimsDataset;
use rustdf::data::handle::TimsData;

use crate::py_tims_frame::{PyTimsFrame};
use crate::py_tims_slice::PyTimsSlice;

#[pyclass]
pub struct PyTimsDataset {
inner: TimsDataset,
}

#[pymethods]
impl PyTimsDataset {
#[new]
pub fn new(data_path: &str, bruker_lib_path: &str) -> Self {
let dataset = TimsDataset::new(bruker_lib_path, data_path);
PyTimsDataset { inner: dataset }
}

pub fn get_frame(&self, frame_id: u32) -> PyTimsFrame {
PyTimsFrame { inner: self.inner.get_frame(frame_id) }
}

pub fn get_slice(&self, frame_ids: Vec<u32>) -> PyTimsSlice {
PyTimsSlice { inner: self.inner.get_slice(frame_ids) }
}

pub fn get_aquisition_mode(&self) -> String {
self.inner.get_aquisition_mode().to_string()
}

pub fn get_frame_count(&self) -> i32 {
self.inner.get_frame_count()
}

pub fn get_data_path(&self) -> &str {
self.inner.get_data_path()
}

pub fn get_bruker_lib_path(&self) -> &str {
self.inner.get_bruker_lib_path()
}
}
78 changes: 78 additions & 0 deletions imspy_connector/src/py_dda.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use pyo3::prelude::*;

use rustdf::data::dda::{PASEFDDAFragment, TimsDatasetDDA};
use rustdf::data::handle::TimsData;
use crate::py_mz_spectrum::PyIndexedMzSpectrum;
use crate::py_tims_frame::PyTimsFrame;
use crate::py_tims_slice::PyTimsSlice;

#[pyclass]
pub struct PyTimsDatasetDDA {
inner: TimsDatasetDDA,
}

#[pymethods]
impl PyTimsDatasetDDA {
#[new]
pub fn new(data_path: &str, bruker_lib_path: &str) -> Self {
let dataset = TimsDatasetDDA::new(bruker_lib_path, data_path);
PyTimsDatasetDDA { inner: dataset }
}
pub fn get_frame(&self, frame_id: u32) -> PyTimsFrame {
PyTimsFrame { inner: self.inner.get_frame(frame_id) }
}

pub fn get_slice(&self, frame_ids: Vec<u32>) -> PyTimsSlice {
PyTimsSlice { inner: self.inner.get_slice(frame_ids) }
}

pub fn get_aquisition_mode(&self) -> String {
self.inner.get_aquisition_mode().to_string()
}

pub fn get_frame_count(&self) -> i32 {
self.inner.get_frame_count()
}

pub fn get_data_path(&self) -> &str {
self.inner.get_data_path()
}

pub fn get_bruker_lib_path(&self) -> &str {
self.inner.get_bruker_lib_path()
}

pub fn get_pasef_fragments(&self, num_threads: usize) -> Vec<PyTimsFragmentDDA> {
let pasef_fragments = self.inner.get_pasef_fragments(num_threads);
pasef_fragments.iter().map(|pasef_fragment| PyTimsFragmentDDA { inner: pasef_fragment.clone() }).collect()
}
}

#[pyclass]
pub struct PyTimsFragmentDDA {
inner: PASEFDDAFragment,
}

#[pymethods]
impl PyTimsFragmentDDA {
#[new]
pub fn new(frame_id: u32, precursor_id: u32, selected_fragment: &PyIndexedMzSpectrum) -> PyResult<Self> {

let pasef_fragment = PASEFDDAFragment {
frame_id,
precursor_id,
selected_fragment: selected_fragment.inner.clone(),
};

Ok(PyTimsFragmentDDA { inner: pasef_fragment })
}

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

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

#[getter]
pub fn selected_fragment(&self) -> PyIndexedMzSpectrum { PyIndexedMzSpectrum { inner: self.inner.selected_fragment.clone() } }
}
43 changes: 43 additions & 0 deletions imspy_connector/src/py_dia.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use pyo3::prelude::*;

use rustdf::data::dia::TimsDatasetDIA;
use rustdf::data::handle::TimsData;
use crate::py_tims_frame::PyTimsFrame;
use crate::py_tims_slice::PyTimsSlice;

#[pyclass]
pub struct PyTimsDatasetDIA {
inner: TimsDatasetDIA,
}

#[pymethods]
impl PyTimsDatasetDIA {
#[new]
pub fn new(data_path: &str, bruker_lib_path: &str) -> Self {
let dataset = TimsDatasetDIA::new(bruker_lib_path, data_path);
PyTimsDatasetDIA { inner: dataset }
}
pub fn get_frame(&self, frame_id: u32) -> PyTimsFrame {
PyTimsFrame { inner: self.inner.get_frame(frame_id) }
}

pub fn get_slice(&self, frame_ids: Vec<u32>) -> PyTimsSlice {
PyTimsSlice { inner: self.inner.get_slice(frame_ids) }
}

pub fn get_aquisition_mode(&self) -> String {
self.inner.get_aquisition_mode().to_string()
}

pub fn get_frame_count(&self) -> i32 {
self.inner.get_frame_count()
}

pub fn get_data_path(&self) -> &str {
self.inner.get_data_path()
}

pub fn get_bruker_lib_path(&self) -> &str {
self.inner.get_bruker_lib_path()
}
}
Loading