pub mod mzml;
pub mod prefetch;
pub mod tims_calibration;
#[cfg(feature = "tdf")]
pub mod bruker;
#[cfg(feature = "thermo")]
pub mod thermo;
use std::path::Path;
use crate::config::FileConfig;
use crate::error::KothError;
use crate::models::Spectrum;
pub type SpectrumStream = Box<dyn Iterator<Item = Result<Spectrum, KothError>> + Send>;
pub fn stream_spectra(path: &Path, file: &FileConfig) -> Result<SpectrumStream, KothError> {
match detect_format(path) {
InputFormat::Mzml | InputFormat::MzmlGz => mzml::stream_mzml_results(path),
#[cfg(feature = "tdf")]
InputFormat::BrukerD => Ok(Box::new(bruker::stream_bruker(path, file))),
#[cfg(feature = "thermo")]
InputFormat::ThermoRaw => thermo::stream_thermo(path),
_ => read_spectra(path, file)
.map(|spectra| Box::new(spectra.into_iter().map(Ok)) as SpectrumStream),
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InputFormat {
Mzml,
MzmlGz,
BrukerD,
ThermoRaw,
Unsupported,
}
pub fn detect_format(path: &Path) -> InputFormat {
let name = path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("")
.to_lowercase();
if name.ends_with(".mzml.gz") {
InputFormat::MzmlGz
} else if name.ends_with(".mzml") {
InputFormat::Mzml
} else if name.ends_with(".d") && path.is_dir() {
InputFormat::BrukerD
} else if name.ends_with(".raw") {
InputFormat::ThermoRaw
} else {
InputFormat::Unsupported
}
}
pub fn read_spectra(path: &Path, file: &FileConfig) -> Result<Vec<Spectrum>, KothError> {
match detect_format(path) {
InputFormat::Mzml | InputFormat::MzmlGz => mzml::read_mzml(path),
InputFormat::BrukerD => read_bruker_inner(path, file),
InputFormat::ThermoRaw => read_thermo_inner(path),
InputFormat::Unsupported => Err(KothError::UnsupportedFormat(format!(
"'{}' is not a supported input format. Use .mzML, a Bruker .d directory, or a Thermo .raw file.",
path.display()
))),
}
}
#[cfg(feature = "thermo")]
fn read_thermo_inner(path: &Path) -> Result<Vec<Spectrum>, KothError> {
thermo::read_thermo(path)
}
#[cfg(not(feature = "thermo"))]
fn read_thermo_inner(_path: &Path) -> Result<Vec<Spectrum>, KothError> {
Err(KothError::UnsupportedFormat(
"Thermo .raw support requires the 'thermo' feature flag. Rebuild with the default features (or --features thermo)."
.into(),
))
}
#[cfg(feature = "tdf")]
fn read_bruker_inner(path: &Path, file: &FileConfig) -> Result<Vec<Spectrum>, KothError> {
bruker::read_bruker(path, file)
}
#[cfg(not(feature = "tdf"))]
fn read_bruker_inner(_path: &Path, _file: &FileConfig) -> Result<Vec<Spectrum>, KothError> {
Err(KothError::UnsupportedFormat(
"Bruker .d support requires the 'tdf' feature flag. Rebuild with --features tdf.".into(),
))
}