Skip to content

Merge frame splitting into sw dev #23

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

Merged
merged 29 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a3b254a
(wip) added span-run and nsplit strategies
jspaezp Jul 12, 2024
f5fb8d9
propagated configs (untested)
jspaezp Jul 17, 2024
903ed34
FIX: typo in tdfblob reader
sander-willems-bruker Jul 17, 2024
c6f96de
CHORE: rename unsuoppreted acquistion for precrsor reader
sander-willems-bruker Jul 17, 2024
ea8be45
FEAT: implemented error propagation for spectrum readers
sander-willems-bruker Jul 17, 2024
0b7f4b8
FEAT: added error propagation macro
sander-willems-bruker Jul 17, 2024
fdad79c
merge
jspaezp Jul 17, 2024
2adb685
CHORE(wip): Partial addition of tests and removal of debug prints
jspaezp Jul 18, 2024
1261967
CHORE: More work towards testing splitting methods
jspaezp Jul 18, 2024
cfa0574
CHORE: resolve merge conflicts
sander-willems-bruker Jul 25, 2024
a5fd90d
FIX: resolve test and bench conflicts
sander-willems-bruker Jul 25, 2024
db6a217
CHORE: compartmentalize how to build a spectrumreader
sander-willems-bruker Jul 25, 2024
c0039d8
FEAT: simplified frame reader creation
sander-willems-bruker Jul 25, 2024
e5a69f1
FIX: rebuild bench tests
sander-willems-bruker Jul 25, 2024
e53b958
FEAT: implemented domain inverters
sander-willems-bruker Jul 26, 2024
b5879eb
DOCS: add future plans to readme
sander-willems-bruker Jul 26, 2024
64f1cad
FEAT: MAde spectrum reader more user friendly to create and set prope…
sander-willems-bruker Jul 26, 2024
1f95023
FEAT: simplified spectrumreader new and build
sander-willems-bruker Jul 26, 2024
9c75d2a
FEAT: cleaned up precursorreader
sander-willems-bruker Jul 26, 2024
5f7a3de
CHORE: simplify precursor reader
sander-willems-bruker Jul 26, 2024
a404bcd
FEAT: propagating spectrum reader errrors (pt1)
sander-willems-bruker Jul 26, 2024
7f4ab57
FIX: More error propagation for spectrumreaders
sander-willems-bruker Jul 26, 2024
ed57539
FIX: More error propagation for SpectrumReaders
sander-willems-bruker Jul 29, 2024
bea23c2
CHORE: flagged todo items for error propagation
sander-willems-bruker Jul 29, 2024
3fbfca3
FEAT: added calibration option to spectrumreaderconfig
sander-willems-bruker Jul 29, 2024
b4dc3ba
FEAT: improved error options
sander-willems-bruker Jul 29, 2024
d9e98c1
FEAT: moved tdf_utils to quadrupole_reader and cleaned up
sander-willems-bruker Jul 29, 2024
6bcd632
FEATL reverted spectrum reader get all to vec of result instead of re…
sander-willems-bruker Jul 31, 2024
23f43cb
DOCS: readme update
sander-willems-bruker Jul 31, 2024
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,11 @@ Two file formats are supported:
## Python bindings

The [timsrust_pyo3](https://github.com/jspaezp/timsrust_pyo3) package is an example of how the performance of TimsRust can be utilized in Python

## Planned changes for future versions
TODO
* Improve docs
* Improve tests
* Pase CompressionType1
* Make Path of TimsTOF data into special type
* ...
11 changes: 5 additions & 6 deletions benches/speed_performance.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rayon::iter::ParallelIterator;
use timsrust::{
io::readers::{FrameReader, SpectrumReader},
ms_data::Frame,
use timsrust::io::readers::{
FrameReader, SpectrumReader, SpectrumReaderConfig,
};

const DDA_TEST: &str =
Expand Down Expand Up @@ -34,7 +33,7 @@ fn criterion_benchmark_dda(c: &mut Criterion) {
group.significance_level(0.001).sample_size(10);
let d_folder_name: &str = DDA_TEST;
let frame_reader = FrameReader::new(d_folder_name).unwrap();
let spectrum_reader = SpectrumReader::new(d_folder_name);
let spectrum_reader = SpectrumReader::new(d_folder_name).unwrap();
group.bench_function("DDA read_all_frames 6m", |b| {
b.iter(|| read_all_frames(black_box(&frame_reader)))
});
Expand All @@ -56,7 +55,7 @@ fn criterion_benchmark_dia(c: &mut Criterion) {
group.significance_level(0.001).sample_size(10);
let d_folder_name: &str = DIA_TEST;
let frame_reader = FrameReader::new(d_folder_name).unwrap();
let spectrum_reader = SpectrumReader::new(d_folder_name);
let spectrum_reader = SpectrumReader::new(d_folder_name).unwrap();
group.bench_function("DIA read_all_frames 6m", |b| {
b.iter(|| read_all_frames(black_box(&frame_reader)))
});
Expand All @@ -75,7 +74,7 @@ fn criterion_benchmark_syp(c: &mut Criterion) {
group.significance_level(0.001).sample_size(10);
let d_folder_name: &str = SYP_TEST;
let frame_reader = FrameReader::new(d_folder_name).unwrap();
let spectrum_reader = SpectrumReader::new(d_folder_name);
let spectrum_reader = SpectrumReader::new(d_folder_name).unwrap();
group.bench_function("SYP read_all_frames 6m", |b| {
b.iter(|| read_all_frames(black_box(&frame_reader)))
});
Expand Down
2 changes: 2 additions & 0 deletions src/domain_converters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ pub use tof_to_mz::Tof2MzConverter;
/// Convert from one domain (e.g. Time of Flight) to another (m/z).
pub trait ConvertableDomain {
fn convert<T: Into<f64> + Copy>(&self, value: T) -> f64;

fn invert<T: Into<f64> + Copy>(&self, value: T) -> f64;
}
16 changes: 16 additions & 0 deletions src/domain_converters/frame_to_rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,20 @@ impl super::ConvertableDomain for Frame2RtConverter {
let upper_value: f64 = self.rt_values[value.into().ceil() as usize];
(lower_value + upper_value) / 2.
}
fn invert<T: Into<f64> + Copy>(&self, value: T) -> f64 {
let rt_value = value.into();
match self.rt_values.binary_search_by(|probe| {
probe.partial_cmp(&rt_value).expect("Cannot handle NaNs")
}) {
Ok(index) => index as f64,
Err(index) => match index {
_ if (index > 0) && (index < self.rt_values.len()) => {
let start = self.rt_values[index - 1];
let end = self.rt_values[index];
index as f64 + (rt_value - start) / (end - start)
},
_ => index as f64,
},
}
}
}
9 changes: 7 additions & 2 deletions src/domain_converters/scan_to_im.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ impl Scan2ImConverter {

impl super::ConvertableDomain for Scan2ImConverter {
fn convert<T: Into<f64> + Copy>(&self, value: T) -> f64 {
let scan_index_f64: f64 = value.into();
self.scan_intercept + self.scan_slope * scan_index_f64
let scan_index: f64 = value.into();
self.scan_intercept + self.scan_slope * scan_index
}

fn invert<T: Into<f64> + Copy>(&self, value: T) -> f64 {
let im_value: f64 = value.into();
(im_value - self.scan_intercept) / self.scan_slope
}
}
8 changes: 6 additions & 2 deletions src/domain_converters/tof_to_mz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ impl Tof2MzConverter {

impl super::ConvertableDomain for Tof2MzConverter {
fn convert<T: Into<f64> + Copy>(&self, value: T) -> f64 {
let tof_index_f64: f64 = value.into();
(self.tof_intercept + self.tof_slope * tof_index_f64).powi(2)
let tof_index: f64 = value.into();
(self.tof_intercept + self.tof_slope * tof_index).powi(2)
}
fn invert<T: Into<f64> + Copy>(&self, value: T) -> f64 {
let mz_value: f64 = value.into();
(mz_value.sqrt() - self.tof_intercept) / self.tof_slope
}
}
32 changes: 14 additions & 18 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
#[derive(thiserror::Error, Debug)]
pub enum FileFormatError {
#[error("DirectoryDoesNotExist")]
DirectoryDoesNotExist,
#[error("NoParentWithBrukerExtension")]
NoParentWithBrukerExtension,
#[error("BinaryFilesAreMissing")]
BinaryFilesAreMissing,
#[error("MetadataFilesAreMissing")]
MetadataFilesAreMissing,
}
use crate::io::readers::{
FrameReaderError, MetadataReaderError, PrecursorReaderError,
QuadrupoleSettingsReaderError, SpectrumReaderError,
};

/// An error that is produced by timsrust (uses [thiserror]).
#[derive(thiserror::Error, Debug)]
pub enum Error {
/// An error to indicate a path is not a Bruker File Format.
#[error("FileFormatError: {0}")]
FileFormatError(#[from] FileFormatError),
// #[error("SqlError: {0}")]
// SqlError(#[from] SqlError),
// #[error("BinError: {0}")]
// BinError(#[from] TdfBlobError),
#[error("{0}")]
FrameReaderError(#[from] FrameReaderError),
#[error("{0}")]
SpectrumReaderError(#[from] SpectrumReaderError),
#[error("{0}")]
MetadataReaderError(#[from] MetadataReaderError),
#[error("{0}")]
PrecursorReaderError(#[from] PrecursorReaderError),
#[error("{0}")]
QuadrupoleSettingsReaderError(#[from] QuadrupoleSettingsReaderError),
}
2 changes: 1 addition & 1 deletion src/io/readers/file_readers/tdf_blob_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl IndexedTdfBlobReader {
pub fn new(
file_name: impl AsRef<Path>,
binary_offsets: Vec<usize>,
) -> Result<Self, TdfBlobReaderError> {
) -> Result<Self, IndexedTdfBlobReaderError> {
let blob_reader = TdfBlobReader::new(file_name)?;
let reader = Self {
binary_offsets,
Expand Down
61 changes: 52 additions & 9 deletions src/io/readers/precursor_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ mod minitdf;
mod tdf;

use core::fmt;
use std::path::Path;
use std::path::{Path, PathBuf};

use minitdf::{MiniTDFPrecursorReader, MiniTDFPrecursorReaderError};
use tdf::{TDFPrecursorReader, TDFPrecursorReaderError};

use crate::ms_data::Precursor;

use super::quad_settings_reader::FrameWindowSplittingStrategy;

pub struct PrecursorReader {
precursor_reader: Box<dyn PrecursorReaderTrait>,
}
Expand All @@ -20,15 +22,12 @@ impl fmt::Debug for PrecursorReader {
}

impl PrecursorReader {
pub fn build() -> PrecursorReaderBuilder {
PrecursorReaderBuilder::default()
}

pub fn new(path: impl AsRef<Path>) -> Result<Self, PrecursorReaderError> {
let precursor_reader: Box<dyn PrecursorReaderTrait> =
match path.as_ref().extension().and_then(|e| e.to_str()) {
Some("parquet") => Box::new(MiniTDFPrecursorReader::new(path)?),
Some("tdf") => Box::new(TDFPrecursorReader::new(path)?),
_ => panic!(),
};
let reader = Self { precursor_reader };
Ok(reader)
Self::build().with_path(path).finalize()
}

pub fn get(&self, index: usize) -> Option<Precursor> {
Expand All @@ -40,6 +39,48 @@ impl PrecursorReader {
}
}

#[derive(Debug, Default, Clone)]
pub struct PrecursorReaderBuilder {
path: PathBuf,
config: FrameWindowSplittingStrategy,
}

impl PrecursorReaderBuilder {
pub fn with_path(&self, path: impl AsRef<Path>) -> Self {
Self {
path: path.as_ref().to_path_buf(),
..self.clone()
}
}

pub fn with_config(&self, config: FrameWindowSplittingStrategy) -> Self {
Self {
config: config,
..self.clone()
}
}

pub fn finalize(&self) -> Result<PrecursorReader, PrecursorReaderError> {
let precursor_reader: Box<dyn PrecursorReaderTrait> =
match self.path.extension().and_then(|e| e.to_str()) {
Some("parquet") => {
Box::new(MiniTDFPrecursorReader::new(self.path.clone())?)
},
Some("tdf") => Box::new(TDFPrecursorReader::new(
self.path.clone(),
self.config.clone(),
)?),
_ => {
return Err(PrecursorReaderError::PrecursorReaderFileError(
self.path.clone(),
))
},
};
let reader = PrecursorReader { precursor_reader };
Ok(reader)
}
}

trait PrecursorReaderTrait: Sync {
fn get(&self, index: usize) -> Option<Precursor>;
fn len(&self) -> usize;
Expand All @@ -51,4 +92,6 @@ pub enum PrecursorReaderError {
MiniTDFPrecursorReaderError(#[from] MiniTDFPrecursorReaderError),
#[error("{0}")]
TDFPrecursorReaderError(#[from] TDFPrecursorReaderError),
#[error("File {0} not valid")]
PrecursorReaderFileError(PathBuf),
}
22 changes: 14 additions & 8 deletions src/io/readers/precursor_reader/tdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use dda::{DDATDFPrecursorReader, DDATDFPrecursorReaderError};
use dia::{DIATDFPrecursorReader, DIATDFPrecursorReaderError};

use crate::{
io::readers::file_readers::sql_reader::{SqlError, SqlReader},
io::readers::{
file_readers::sql_reader::{SqlError, SqlReader},
quad_settings_reader::FrameWindowSplittingStrategy,
},
ms_data::{AcquisitionType, Precursor},
};

Expand All @@ -20,6 +23,7 @@ pub struct TDFPrecursorReader {
impl TDFPrecursorReader {
pub fn new(
path: impl AsRef<Path>,
splitting_strategy: FrameWindowSplittingStrategy,
) -> Result<Self, TDFPrecursorReaderError> {
let sql_path = path.as_ref();
let tdf_sql_reader = SqlReader::open(sql_path)?;
Expand All @@ -37,13 +41,15 @@ impl TDFPrecursorReader {
AcquisitionType::DDAPASEF => {
Box::new(DDATDFPrecursorReader::new(path)?)
},
AcquisitionType::DIAPASEF => {
Box::new(DIATDFPrecursorReader::new(path)?)
},
AcquisitionType::DIAPASEF => Box::new(
DIATDFPrecursorReader::new(path, splitting_strategy)?,
),
acquisition_type => {
return Err(TDFPrecursorReaderError::UnknownPrecursorType(
format!("{:?}", acquisition_type),
))
return Err(
TDFPrecursorReaderError::UnsupportedAcquisition(
format!("{:?}", acquisition_type),
),
)
},
};
let reader = Self { precursor_reader };
Expand All @@ -70,5 +76,5 @@ pub enum TDFPrecursorReaderError {
#[error("{0}")]
DIATDFPrecursorReaderError(#[from] DIATDFPrecursorReaderError),
#[error("Invalid acquistion type for precursor reader: {0}")]
UnknownPrecursorType(String),
UnsupportedAcquisition(String),
}
31 changes: 8 additions & 23 deletions src/io/readers/precursor_reader/tdf/dia.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use std::path::Path;

use crate::io::readers::quad_settings_reader::FrameWindowSplittingStrategy;
use crate::{
domain_converters::{
ConvertableDomain, Frame2RtConverter, Scan2ImConverter,
},
io::readers::{
file_readers::sql_reader::{
frame_groups::SqlWindowGroup, ReadableSqlTable, SqlError, SqlReader,
},
file_readers::sql_reader::{SqlError, SqlReader},
MetadataReader, MetadataReaderError, QuadrupoleSettingsReader,
QuadrupoleSettingsReaderError,
},
Expand All @@ -26,32 +25,18 @@ pub struct DIATDFPrecursorReader {
impl DIATDFPrecursorReader {
pub fn new(
path: impl AsRef<Path>,
splitting_strategy: FrameWindowSplittingStrategy,
) -> Result<Self, DIATDFPrecursorReaderError> {
let sql_path = path.as_ref();
let tdf_sql_reader = SqlReader::open(sql_path)?;
let metadata = MetadataReader::new(&path)?;
let rt_converter: Frame2RtConverter = metadata.rt_converter;
let im_converter: Scan2ImConverter = metadata.im_converter;
let window_groups = SqlWindowGroup::from_sql_reader(&tdf_sql_reader)?;
let quadrupole_settings =
QuadrupoleSettingsReader::new(tdf_sql_reader.get_path())?;
let mut expanded_quadrupole_settings: Vec<QuadrupoleSettings> = vec![];
for window_group in window_groups {
let window = window_group.window_group;
let frame = window_group.frame;
let group = &quadrupole_settings[window as usize - 1];
for sub_window in 0..group.isolation_mz.len() {
let sub_quad_settings = QuadrupoleSettings {
index: frame,
scan_starts: vec![group.scan_starts[sub_window]],
scan_ends: vec![group.scan_ends[sub_window]],
isolation_mz: vec![group.isolation_mz[sub_window]],
isolation_width: vec![group.isolation_width[sub_window]],
collision_energy: vec![group.collision_energy[sub_window]],
};
expanded_quadrupole_settings.push(sub_quad_settings)
}
}
let expanded_quadrupole_settings =
QuadrupoleSettingsReader::from_splitting(
tdf_sql_reader.get_path(),
splitting_strategy,
)?;
let reader = Self {
expanded_quadrupole_settings,
rt_converter,
Expand Down
Loading
Loading