Skip to content

Commit

Permalink
started implementing python binding
Browse files Browse the repository at this point in the history
  • Loading branch information
theGreatHerrLebert committed Sep 20, 2023
1 parent adb03f7 commit d8b2d19
Show file tree
Hide file tree
Showing 12 changed files with 399 additions and 22 deletions.
41 changes: 35 additions & 6 deletions mscore/src/mz_spectrum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,46 @@ pub struct MzSpectrum {
///
#[derive(Clone)]
pub enum MsType {
PRECURSOR,
FRAGMENT,
UNKNOWN,
Precursor,
FragmentDda,
FragmentDia,
Unknown,
}

impl MsType {
/// Returns the `MsType` enum corresponding to the given integer value.
///
/// # Arguments
///
/// * `ms_type` - An integer value corresponding to the `MsType` enum.
///
pub fn new(ms_type: i32) -> MsType {
match ms_type {
0 => MsType::Precursor,
8 => MsType::FragmentDda,
9 => MsType::FragmentDia,
_ => MsType::Unknown,
}
}

/// Returns the integer value corresponding to the `MsType` enum.
pub fn to_i32(&self) -> i32 {
match self {
MsType::Precursor => 0,
MsType::FragmentDda => 8,
MsType::FragmentDia => 9,
MsType::Unknown => -1,
}
}
}

impl Display for MsType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
MsType::PRECURSOR => write!(f, "PRECURSOR"),
MsType::FRAGMENT => write!(f, "FRAGMENT"),
MsType::UNKNOWN => write!(f, "UNKNOWN"),
MsType::Precursor => write!(f, "Precursor"),
MsType::FragmentDda => write!(f, "FragmentDda"),
MsType::FragmentDia => write!(f, "FragmentDia"),
MsType::Unknown => write!(f, "Unknown"),
}
}
}
Expand Down
120 changes: 120 additions & 0 deletions pyims/.github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# This file is autogenerated by maturin v1.2.3
# To update, run
#
# maturin generate-ci github
#
name: CI

on:
push:
branches:
- main
- master
tags:
- '*'
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
linux:
runs-on: ubuntu-latest
strategy:
matrix:
target: [x86_64, x86, aarch64, armv7, s390x, ppc64le]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist --find-interpreter
sccache: 'true'
manylinux: auto
- name: Upload wheels
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist

windows:
runs-on: windows-latest
strategy:
matrix:
target: [x64, x86]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
architecture: ${{ matrix.target }}
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist --find-interpreter
sccache: 'true'
- name: Upload wheels
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist

macos:
runs-on: macos-latest
strategy:
matrix:
target: [x86_64, aarch64]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist --find-interpreter
sccache: 'true'
- name: Upload wheels
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist

sdist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build sdist
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist
- name: Upload sdist
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist

release:
name: Release
runs-on: ubuntu-latest
if: "startsWith(github.ref, 'refs/tags/')"
needs: [linux, windows, macos, sdist]
steps:
- uses: actions/download-artifact@v3
with:
name: wheels
- name: Publish to PyPI
uses: PyO3/maturin-action@v1
env:
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
with:
command: upload
args: --non-interactive --skip-existing *
72 changes: 72 additions & 0 deletions pyims/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/target

# Byte-compiled / optimized / DLL files
__pycache__/
.pytest_cache/
*.py[cod]

# C extensions
*.so

# Distribution / packaging
.Python
.venv/
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
include/
man/
venv/
*.egg-info/
.installed.cfg
*.egg

# Installer logs
pip-log.txt
pip-delete-this-directory.txt
pip-selfcheck.json

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml

# Translations
*.mo

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

# Rope
.ropeproject

# Django stuff:
*.log
*.pot

.DS_Store

# Sphinx documentation
docs/_build/

# PyCharm
.idea/

# VSCode
.vscode/

# Pyenv
.python-version
15 changes: 15 additions & 0 deletions pyims/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "pyims"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "pyims"
crate-type = ["cdylib"]

[dependencies]
pyo3 = { version = "0.19.2", features = ["extension-module"] }
numpy = "0.19.0"
mscore = {path = "../mscore"}
rustdf = {path = "../rustdf"}
16 changes: 16 additions & 0 deletions pyims/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[build-system]
requires = ["maturin>=1.2,<2.0"]
build-backend = "maturin"

[project]
name = "pyims"
requires-python = ">=3.7"
classifiers = [
"Programming Language :: Rust",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]


[tool.maturin]
features = ["pyo3/extension-module"]
14 changes: 14 additions & 0 deletions pyims/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
mod pyhandle;
mod py_mz_spectrum;

use pyo3::prelude::*;
use crate::pyhandle::PyTimsDataset;
use crate::py_mz_spectrum::PyMzSpectrum;

/// A Python module implemented in Rust.
#[pymodule]
fn pyims(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PyTimsDataset>()?;
m.add_class::<PyMzSpectrum>()?;
Ok(())
}
83 changes: 83 additions & 0 deletions pyims/src/py_mz_spectrum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use pyo3::prelude::*;
use numpy::{PyArray1, IntoPyArray};
use mscore::{MzSpectrum, TimsFrame, MsType};

#[pyclass]
pub struct PyMzSpectrum {
inner: MzSpectrum,
}

#[pymethods]
impl PyMzSpectrum {
#[new]
pub unsafe fn new(mz: &PyArray1<f64>, intensity: &PyArray1<f64>) -> PyResult<Self> {
Ok(PyMzSpectrum {
inner: MzSpectrum {
mz: mz.as_slice()?.to_vec(),
intensity: intensity.as_slice()?.to_vec(),
},
})
}

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

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

#[pyclass]
pub struct PyTimsFrame {
pub inner: TimsFrame,
}

#[pymethods]
impl PyTimsFrame {
#[new]
pub unsafe fn new(frame_id: i32, ms_type: i32, retention_time: f64, scan: &PyArray1<i32>, inv_mobility: &PyArray1<f64>, tof: &PyArray1<i32>, mz: &PyArray1<f64>, intensity: &PyArray1<f64>) -> PyResult<Self> {
Ok(PyTimsFrame {
inner: TimsFrame {
frame_id,
ms_type: MsType::new(ms_type),
retention_time,
scan: scan.as_slice()?.to_vec(),
inv_mobility: inv_mobility.as_slice()?.to_vec(),
tof: tof.as_slice()?.to_vec(),
mz: mz.as_slice()?.to_vec(),
intensity: intensity.as_slice()?.to_vec(),
},
})
}
#[getter]
pub fn mz(&self, py: Python) -> Py<PyArray1<f64>> {
self.inner.mz.clone().into_pyarray(py).to_owned()
}
#[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 inv_mobility(&self, py: Python) -> Py<PyArray1<f64>> {
self.inner.inv_mobility.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(&self) -> i32 {
self.inner.ms_type.to_i32()
}
}
Loading

0 comments on commit d8b2d19

Please sign in to comment.