use std::{collections::HashSet, convert::TryInto, mem};
use mzpeaks::{
prelude::*,
feature::{ChargedFeature, Feature},
CentroidLike, CentroidPeak, CoordinateLike, DeconvolutedPeak, DeconvolutedPeakSet,
IonMobility,MZPeakSetType, Mass, PeakSet,
MZ,
};
use crate::{params::Unit, utils::{mass_charge_ratio, neutral_mass}};
use super::{
array::DataArray,
encodings::{ArrayRetrievalError, ArrayType, BinaryCompressionType, BinaryDataArrayType},
map::BinaryArrayMap,
BinaryArrayMap3D, ByteArrayView,
};
impl From<&PeakSet> for BinaryArrayMap {
fn from(peaks: &PeakSet) -> BinaryArrayMap {
let mut arrays = BinaryArrayMap::new();
let mut mz_array = DataArray::from_name_type_size(
&ArrayType::MZArray,
BinaryDataArrayType::Float64,
peaks.len() * BinaryDataArrayType::Float64.size_of(),
);
let mut intensity_array = DataArray::from_name_type_size(
&ArrayType::IntensityArray,
BinaryDataArrayType::Float32,
peaks.len() * BinaryDataArrayType::Float32.size_of(),
);
mz_array.compression = BinaryCompressionType::Decoded;
intensity_array.compression = BinaryCompressionType::Decoded;
for p in peaks.iter() {
let mz: f64 = p.coordinate();
let inten: f32 = p.intensity();
let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
mz_array.data.extend(raw_bytes);
let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
intensity_array.data.extend(raw_bytes);
}
arrays.add(mz_array);
arrays.add(intensity_array);
arrays
}
}
impl<C: CentroidLike + From<CentroidPeak>> From<BinaryArrayMap> for MZPeakSetType<C> {
fn from(arrays: BinaryArrayMap) -> MZPeakSetType<C> {
(&arrays).into()
}
}
impl<C: CentroidLike + From<CentroidPeak>> From<&BinaryArrayMap> for MZPeakSetType<C> {
fn from(arrays: &BinaryArrayMap) -> MZPeakSetType<C> {
let mz_array = arrays.mzs().unwrap();
let intensity_array = arrays.intensities().unwrap();
let mut peaks = Vec::with_capacity(mz_array.len());
for (i, (mz, intensity)) in mz_array.iter().zip(intensity_array.iter()).enumerate() {
peaks.push(
CentroidPeak {
mz: *mz,
intensity: *intensity,
index: i as u32,
}
.into(),
)
}
MZPeakSetType::<C>::new(peaks)
}
}
impl From<&BinaryArrayMap> for DeconvolutedPeakSet {
fn from(arrays: &BinaryArrayMap) -> DeconvolutedPeakSet {
let mz_array = arrays.mzs().unwrap();
let intensity_array = arrays.intensities().unwrap();
let charge_array = arrays
.charges()
.expect("Charge state array is required for deconvoluted peaks");
let mut peaks = Vec::with_capacity(mz_array.len());
for (i, ((mz, intensity), charge)) in mz_array
.iter()
.zip(intensity_array.iter())
.zip(charge_array.iter())
.enumerate()
{
peaks.push(DeconvolutedPeak {
neutral_mass: neutral_mass(*mz, *charge),
intensity: *intensity,
charge: *charge,
index: i as u32,
})
}
DeconvolutedPeakSet::new(peaks)
}
}
impl From<&DeconvolutedPeakSet> for BinaryArrayMap {
fn from(peaks: &DeconvolutedPeakSet) -> BinaryArrayMap {
let mut arrays = BinaryArrayMap::new();
let mut mz_array = DataArray::from_name_type_size(
&ArrayType::MZArray,
BinaryDataArrayType::Float64,
peaks.len() * BinaryDataArrayType::Float64.size_of(),
);
let mut intensity_array = DataArray::from_name_type_size(
&ArrayType::IntensityArray,
BinaryDataArrayType::Float32,
peaks.len() * BinaryDataArrayType::Float32.size_of(),
);
let mut charge_array = DataArray::from_name_type_size(
&ArrayType::ChargeArray,
BinaryDataArrayType::Int32,
peaks.len() * BinaryDataArrayType::Int32.size_of(),
);
mz_array.compression = BinaryCompressionType::Decoded;
intensity_array.compression = BinaryCompressionType::Decoded;
charge_array.compression = BinaryCompressionType::Decoded;
for p in peaks.iter() {
let mz: f64 = p.mz();
let inten: f32 = p.intensity();
let charge = p.charge();
let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
mz_array.data.extend_from_slice(&raw_bytes);
let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
intensity_array.data.extend_from_slice(&raw_bytes);
let raw_bytes: [u8; mem::size_of::<i32>()] = charge.to_le_bytes();
charge_array.data.extend_from_slice(&raw_bytes);
}
arrays.add(mz_array);
arrays.add(intensity_array);
arrays.add(charge_array);
arrays
}
}
#[derive(Debug, Clone)]
pub enum ArraysAvailable {
Unknown,
Ok,
MissingArrays(Vec<ArrayType>),
}
pub trait BuildFromArrayMap: Sized {
fn arrays_required() -> Option<Vec<ArrayType>> {
None
}
fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError>;
fn from_arrays(arrays: &BinaryArrayMap) -> Vec<Self> {
Self::try_from_arrays(arrays).unwrap()
}
fn has_arrays_for(arrays: &BinaryArrayMap) -> ArraysAvailable {
if let Some(arrays_required) = Self::arrays_required() {
let missing: Vec<_> = arrays_required
.into_iter()
.filter(|array_type| !arrays.has_array(array_type))
.collect();
if !missing.is_empty() {
ArraysAvailable::MissingArrays(missing)
} else {
ArraysAvailable::Ok
}
} else {
ArraysAvailable::Unknown
}
}
}
pub trait BuildArrayMap3DFrom: BuildArrayMapFrom {
fn as_arrays_3d(source: &[Self]) -> BinaryArrayMap3D {
BuildArrayMapFrom::as_arrays(source).try_into().unwrap()
}
}
pub trait BuildFromArrayMap3D: BuildFromArrayMap {
fn try_from_arrays_3d(arrays: &BinaryArrayMap3D) -> Result<Vec<Self>, ArrayRetrievalError> {
BuildFromArrayMap::try_from_arrays(&arrays.unstack()?)
}
fn from_arrays_3d(arrays: &BinaryArrayMap3D) -> Vec<Self> {
Self::try_from_arrays_3d(arrays).unwrap()
}
fn has_arrays_3d_for(arrays: &BinaryArrayMap3D) -> ArraysAvailable {
if let Some(arrays_required) = Self::arrays_required() {
let arrays_required: Vec<_> = arrays_required
.into_iter()
.filter(|a| !a.is_ion_mobility())
.collect();
let mut arrays_not_seen: HashSet<_> = arrays_required.iter().cloned().collect();
let mut missing = Vec::new();
for (_, arr) in arrays.iter() {
if arr.is_empty() {
continue;
}
missing.clear();
for array_type in arrays_required.iter() {
if arr.has_array(array_type) {
arrays_not_seen.remove(array_type);
} else {
missing.push(array_type);
}
}
if missing.is_empty() {
return ArraysAvailable::Ok;
}
}
if arrays_not_seen.is_empty() {
ArraysAvailable::Unknown
} else {
ArraysAvailable::MissingArrays(arrays_not_seen.into_iter().collect())
}
} else {
ArraysAvailable::Unknown
}
}
}
pub trait BuildArrayMapFrom: Sized {
fn arrays_included(&self) -> Option<Vec<ArrayType>> {
None
}
fn as_arrays(source: &[Self]) -> BinaryArrayMap;
}
impl BuildArrayMapFrom for CentroidPeak {
fn arrays_included(&self) -> Option<Vec<ArrayType>> {
Some(vec![ArrayType::MZArray, ArrayType::IntensityArray])
}
fn as_arrays(source: &[Self]) -> BinaryArrayMap {
let mut arrays = BinaryArrayMap::new();
let mut mz_array = DataArray::from_name_type_size(
&ArrayType::MZArray,
BinaryDataArrayType::Float64,
source.len() * BinaryDataArrayType::Float64.size_of(),
);
mz_array.unit = Unit::MZ;
let mut intensity_array = DataArray::from_name_type_size(
&ArrayType::IntensityArray,
BinaryDataArrayType::Float32,
source.len() * BinaryDataArrayType::Float32.size_of(),
);
intensity_array.unit = Unit::DetectorCounts;
mz_array.compression = BinaryCompressionType::Decoded;
intensity_array.compression = BinaryCompressionType::Decoded;
for p in source.iter() {
let mz: f64 = p.coordinate();
let inten: f32 = p.intensity();
let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
mz_array.data.extend_from_slice(&raw_bytes);
let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
intensity_array.data.extend_from_slice(&raw_bytes);
}
arrays.add(mz_array);
arrays.add(intensity_array);
arrays
}
}
impl BuildFromArrayMap for CentroidPeak {
fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
let mz_array = arrays.mzs()?;
let intensity_array = arrays.intensities()?;
let mut peaks = Vec::with_capacity(mz_array.len());
for (i, (mz, intensity)) in mz_array.iter().zip(intensity_array.iter()).enumerate() {
peaks.push(CentroidPeak {
mz: *mz,
intensity: *intensity,
index: i as u32,
})
}
Ok(peaks)
}
fn arrays_required() -> Option<Vec<ArrayType>> {
Some(vec![ArrayType::MZArray, ArrayType::IntensityArray])
}
}
impl BuildArrayMapFrom for DeconvolutedPeak {
fn as_arrays(source: &[Self]) -> BinaryArrayMap {
let mut arrays = BinaryArrayMap::new();
let mut mz_array = DataArray::from_name_type_size(
&ArrayType::MZArray,
BinaryDataArrayType::Float64,
source.len() * BinaryDataArrayType::Float64.size_of(),
);
mz_array.unit = Unit::MZ;
let mut intensity_array = DataArray::from_name_type_size(
&ArrayType::IntensityArray,
BinaryDataArrayType::Float32,
source.len() * BinaryDataArrayType::Float32.size_of(),
);
intensity_array.unit = Unit::DetectorCounts;
let mut charge_array = DataArray::from_name_type_size(
&ArrayType::ChargeArray,
BinaryDataArrayType::Int32,
source.len() * BinaryDataArrayType::Int32.size_of(),
);
mz_array.compression = BinaryCompressionType::Decoded;
intensity_array.compression = BinaryCompressionType::Decoded;
charge_array.compression = BinaryCompressionType::Decoded;
for p in source.iter() {
let mz: f64 = p.mz();
let inten: f32 = p.intensity();
let charge = p.charge();
let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
mz_array.data.extend_from_slice(&raw_bytes);
let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
intensity_array.data.extend_from_slice(&raw_bytes);
let raw_bytes: [u8; mem::size_of::<i32>()] = charge.to_le_bytes();
charge_array.data.extend_from_slice(&raw_bytes);
}
arrays.add(mz_array);
arrays.add(intensity_array);
arrays.add(charge_array);
arrays
}
fn arrays_included(&self) -> Option<Vec<ArrayType>> {
Some(vec![
ArrayType::MZArray,
ArrayType::IntensityArray,
ArrayType::ChargeArray,
])
}
}
impl BuildFromArrayMap for DeconvolutedPeak {
fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
let mz_array = arrays.mzs()?;
let intensity_array = arrays.intensities()?;
let charge_array = arrays.charges()?;
let mut peaks = Vec::with_capacity(mz_array.len());
for (i, ((mz, intensity), charge)) in mz_array
.iter()
.zip(intensity_array.iter())
.zip(charge_array.iter())
.enumerate()
{
peaks.push(DeconvolutedPeak {
neutral_mass: neutral_mass(*mz, *charge),
intensity: *intensity,
charge: *charge,
index: i as u32,
})
}
Ok(peaks)
}
}
impl BuildArrayMapFrom for Feature<MZ, IonMobility> {
fn arrays_included(&self) -> Option<Vec<ArrayType>> {
Some(vec![
ArrayType::MZArray,
ArrayType::IntensityArray,
ArrayType::RawIonMobilityArray,
ArrayType::nonstandard("feature identifier array"),
])
}
fn as_arrays(source: &[Self]) -> BinaryArrayMap {
let mut arrays = BinaryArrayMap::new();
let n: usize = source.iter().map(|f| f.len()).sum();
let mut mz_array = DataArray::from_name_type_size(
&ArrayType::MZArray,
BinaryDataArrayType::Float64,
n * BinaryDataArrayType::Float64.size_of(),
);
mz_array.unit = Unit::MZ;
let mut intensity_array = DataArray::from_name_type_size(
&ArrayType::IntensityArray,
BinaryDataArrayType::Float32,
n * BinaryDataArrayType::Float32.size_of(),
);
intensity_array.unit = Unit::DetectorCounts;
let mut ion_mobility_array = DataArray::from_name_type_size(
&ArrayType::RawIonMobilityArray,
BinaryDataArrayType::Float64,
n * BinaryDataArrayType::Float64.size_of(),
);
let mut marker_array = DataArray::from_name_type_size(
&ArrayType::nonstandard("feature identifier array"),
BinaryDataArrayType::Int32,
n * BinaryDataArrayType::Int32.size_of(),
);
mz_array.compression = BinaryCompressionType::Decoded;
intensity_array.compression = BinaryCompressionType::Decoded;
ion_mobility_array.compression = BinaryCompressionType::Decoded;
marker_array.compression = BinaryCompressionType::Decoded;
let mut acc = Vec::with_capacity(n);
source.iter().enumerate().for_each(|(i, f)| {
f.iter()
.for_each(|(mz, im, inten)| acc.push((mz, im, inten, i)))
});
acc.sort_by(|(mz_a, im_a, _, key_a), (mz_b, im_b, _, key_b)| {
mz_a.total_cmp(mz_b)
.then(im_a.total_cmp(im_b))
.then(key_a.cmp(key_b))
});
for (mz, im, inten, key) in acc.iter() {
mz_array.data.extend_from_slice(&mz.to_le_bytes());
intensity_array.data.extend_from_slice(&inten.to_le_bytes());
ion_mobility_array.data.extend_from_slice(&im.to_le_bytes());
marker_array
.data
.extend_from_slice(&(*key as i32).to_le_bytes());
}
arrays.add(mz_array);
arrays.add(intensity_array);
arrays.add(ion_mobility_array);
arrays.add(marker_array);
arrays
}
}
impl BuildFromArrayMap for Feature<MZ, IonMobility> {
fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
let mz_array = arrays.mzs()?;
let intensity_array = arrays.intensities()?;
let im_array = arrays
.get(&ArrayType::RawIonMobilityArray)
.ok_or(ArrayRetrievalError::NotFound(
ArrayType::RawIonMobilityArray,
))?
.to_f64()?;
let array_key = ArrayType::nonstandard("feature identifier array");
let marker_array = arrays
.get(&array_key)
.ok_or(ArrayRetrievalError::NotFound(array_key))?
.to_i32()?;
let n = marker_array.iter().map(|i| *i as usize).max();
let mut features = if let Some(n) = n {
let mut features = Vec::with_capacity(n);
features.resize(n, Feature::default());
features
} else {
return Ok(Vec::new());
};
mz_array
.iter()
.zip(intensity_array.iter())
.zip(im_array.iter())
.zip(marker_array.iter())
.for_each(|(((mz, inten), im), key)| {
features[(*key) as usize].push_raw(*mz, *im, *inten);
});
Ok(features)
}
}
impl BuildArrayMapFrom for ChargedFeature<Mass, IonMobility> {
fn arrays_included(&self) -> Option<Vec<ArrayType>> {
Some(vec![
ArrayType::MZArray,
ArrayType::IntensityArray,
ArrayType::RawIonMobilityArray,
ArrayType::ChargeArray,
ArrayType::nonstandard("feature identifier array"),
])
}
fn as_arrays(source: &[Self]) -> BinaryArrayMap {
let mut arrays = BinaryArrayMap::new();
let n: usize = source.iter().map(|f| f.len()).sum();
let mut mz_array = DataArray::from_name_type_size(
&ArrayType::MZArray,
BinaryDataArrayType::Float64,
n * BinaryDataArrayType::Float64.size_of(),
);
mz_array.unit = Unit::MZ;
let mut intensity_array = DataArray::from_name_type_size(
&ArrayType::IntensityArray,
BinaryDataArrayType::Float32,
n * BinaryDataArrayType::Float32.size_of(),
);
intensity_array.unit = Unit::DetectorCounts;
let mut charge_array = DataArray::from_name_type_size(
&ArrayType::ChargeArray,
BinaryDataArrayType::Int32,
n * BinaryDataArrayType::Int32.size_of(),
);
let mut ion_mobility_array = DataArray::from_name_type_size(
&ArrayType::RawIonMobilityArray,
BinaryDataArrayType::Float64,
n * BinaryDataArrayType::Float64.size_of(),
);
let mut marker_array = DataArray::from_name_type_size(
&ArrayType::nonstandard("feature identifier array"),
BinaryDataArrayType::Int32,
n * BinaryDataArrayType::Int32.size_of(),
);
mz_array.compression = BinaryCompressionType::Decoded;
intensity_array.compression = BinaryCompressionType::Decoded;
ion_mobility_array.compression = BinaryCompressionType::Decoded;
marker_array.compression = BinaryCompressionType::Decoded;
let mut acc = Vec::with_capacity(n);
source.iter().enumerate().for_each(|(i, f)| {
f.iter().for_each(|(mass, im, inten)| {
acc.push((mass_charge_ratio(mass, f.charge), im, inten, f.charge, i))
})
});
acc.sort_by(|(mz_a, im_a, _, _, key_a), (mz_b, im_b, _, _, key_b)| {
mz_a.total_cmp(mz_b)
.then(im_a.total_cmp(im_b))
.then(key_a.cmp(key_b))
});
for (mz, im, inten, charge, key) in acc.iter() {
mz_array.data.extend(mz.to_le_bytes());
intensity_array.data.extend(inten.to_le_bytes());
ion_mobility_array.data.extend(im.to_le_bytes());
charge_array.data.extend(charge.to_le_bytes());
marker_array.data.extend((*key as i32).to_le_bytes());
}
arrays.add(mz_array);
arrays.add(intensity_array);
arrays.add(ion_mobility_array);
arrays.add(charge_array);
arrays.add(marker_array);
arrays
}
}
impl BuildFromArrayMap for ChargedFeature<Mass, IonMobility> {
fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
let mz_array = arrays.mzs()?;
let intensity_array = arrays.intensities()?;
let im_array = arrays
.get(&ArrayType::RawIonMobilityArray)
.ok_or(ArrayRetrievalError::NotFound(
ArrayType::RawIonMobilityArray,
))?
.to_f64()?;
let charge_array = arrays
.get(&ArrayType::ChargeArray)
.ok_or(ArrayRetrievalError::NotFound(ArrayType::ChargeArray))?
.to_i32()?;
let array_key = ArrayType::nonstandard("feature identifier array");
let marker_array = arrays
.get(&array_key)
.ok_or(ArrayRetrievalError::NotFound(array_key))?
.to_i32()?;
let n = marker_array.iter().map(|i| *i as usize).max();
let mut features = if let Some(n) = n {
let mut features = Vec::with_capacity(n);
features.resize(n, ChargedFeature::default());
features
} else {
return Ok(Vec::new());
};
mz_array
.iter()
.zip(intensity_array.iter())
.zip(im_array.iter().zip(charge_array.iter()))
.zip(marker_array.iter())
.for_each(|(((mz, inten), (im, charge)), key)| {
let f = &mut features[(*key) as usize];
if f.is_empty() {
f.charge = *charge;
}
f.push_raw(neutral_mass(*mz, *charge), *im, *inten);
});
Ok(features)
}
}
impl BuildArrayMap3DFrom for Feature<MZ, IonMobility> {}
impl BuildFromArrayMap3D for Feature<MZ, IonMobility> {
fn try_from_arrays_3d(arrays: &BinaryArrayMap3D) -> Result<Vec<Self>, ArrayRetrievalError> {
let key = ArrayType::nonstandard("feature identifier array");
let mut n: usize = 0;
for (_, arr) in arrays.iter() {
if arr.is_empty() {
continue;
}
if let Some(arr) = arr.get(&key) {
if let Some(i) = arr.iter_i32()?.map(|i| i as usize).max() {
n = n.max(i);
}
}
}
if n == 0 {
return Ok(Vec::new());
}
n += 1;
let mut index = Vec::with_capacity(n);
index.resize(n, Feature::default());
for (im, arr) in arrays.iter() {
if arr.is_empty() {
continue;
}
let mz_array = arr.mzs()?;
let intensity_array = arr.intensities()?;
let marker_array = arr
.get(&key)
.ok_or_else(|| ArrayRetrievalError::NotFound(key.clone()))?
.to_i32()?;
for ((mz, inten), key_i) in mz_array
.iter()
.zip(intensity_array.iter())
.zip(marker_array.iter())
{
index[(*key_i) as usize].push_raw(*mz, im, *inten);
}
}
Ok(index)
}
}
impl BuildArrayMap3DFrom for ChargedFeature<Mass, IonMobility> {}
impl BuildFromArrayMap3D for ChargedFeature<Mass, IonMobility> {
fn try_from_arrays_3d(arrays: &BinaryArrayMap3D) -> Result<Vec<Self>, ArrayRetrievalError> {
let key = ArrayType::nonstandard("feature identifier array");
let mut n: usize = 0;
for (_, arr) in arrays.iter() {
if arr.is_empty() {
continue;
}
if let Some(arr) = arr.get(&key) {
if let Some(i) = arr.iter_i32()?.map(|i| i as usize).max() {
n = n.max(i);
}
}
}
if n == 0 {
return Ok(Vec::new());
}
n += 1;
let mut index = Vec::with_capacity(n);
index.resize(n, ChargedFeature::default());
for (im, arr) in arrays.iter() {
if arr.is_empty() {
continue;
}
let mz_array = arr.mzs()?;
let intensity_array = arr.intensities()?;
let marker_array = arr
.get(&key)
.ok_or_else(|| ArrayRetrievalError::NotFound(key.clone()))?
.to_i32()?;
let charge_array = arr.charges()?;
for ((mz, inten), (charge, key_i)) in mz_array
.iter()
.zip(intensity_array.iter())
.zip(charge_array.iter().zip(marker_array.iter()))
{
let f = &mut index[(*key_i) as usize];
f.push_raw(*mz, im, *inten);
f.charge = *charge;
}
}
Ok(index)
}
}
impl BuildArrayMapFrom for mzpeaks::peak::IonMobilityAwareCentroidPeak {
fn arrays_included(&self) -> Option<Vec<ArrayType>> {
Some(vec![
ArrayType::MZArray,
ArrayType::IntensityArray,
ArrayType::IonMobilityArray,
])
}
fn as_arrays(source: &[Self]) -> BinaryArrayMap {
let mut arrays = BinaryArrayMap::new();
let mut mz_array = DataArray::from_name_type_size(
&ArrayType::MZArray,
BinaryDataArrayType::Float64,
source.len() * BinaryDataArrayType::Float64.size_of(),
);
mz_array.unit = Unit::MZ;
let mut intensity_array = DataArray::from_name_type_size(
&ArrayType::IntensityArray,
BinaryDataArrayType::Float32,
source.len() * BinaryDataArrayType::Float32.size_of(),
);
intensity_array.unit = Unit::DetectorCounts;
let mut im_array = DataArray::from_name_type_size(
&ArrayType::IonMobilityArray,
BinaryDataArrayType::Float64,
source.len() * BinaryDataArrayType::Float64.size_of(),
);
mz_array.compression = BinaryCompressionType::Decoded;
intensity_array.compression = BinaryCompressionType::Decoded;
im_array.compression = BinaryCompressionType::Decoded;
for p in source.iter() {
let mz: f64 = p.mz();
let inten: f32 = p.intensity();
let im = p.ion_mobility();
let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
mz_array.data.extend_from_slice(&raw_bytes);
let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
intensity_array.data.extend_from_slice(&raw_bytes);
let raw_bytes: [u8; mem::size_of::<f64>()] = im.to_le_bytes();
im_array.data.extend_from_slice(&raw_bytes);
}
arrays.add(mz_array);
arrays.add(intensity_array);
arrays.add(im_array);
arrays
}
}
impl BuildFromArrayMap for mzpeaks::peak::IonMobilityAwareCentroidPeak {
fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
let mz_array = arrays.mzs()?;
let intensity_array = arrays.intensities()?;
let (im_array, _) = arrays.ion_mobility()?;
let mut peaks = Vec::with_capacity(mz_array.len());
for (i, (mz, (intensity, ion_mobility))) in mz_array
.iter()
.zip(intensity_array.iter().zip(im_array.iter()))
.enumerate()
{
peaks.push(mzpeaks::peak::IonMobilityAwareCentroidPeak {
mz: *mz,
intensity: *intensity,
index: i as u32,
ion_mobility: *ion_mobility,
})
}
Ok(peaks)
}
fn arrays_required() -> Option<Vec<ArrayType>> {
Some(vec![
ArrayType::MZArray,
ArrayType::IntensityArray,
ArrayType::IonMobilityArray,
])
}
}
impl BuildArrayMapFrom for mzpeaks::peak::IonMobilityAwareDeconvolutedPeak {
fn arrays_included(&self) -> Option<Vec<ArrayType>> {
Some(vec![
ArrayType::MZArray,
ArrayType::IntensityArray,
ArrayType::ChargeArray,
ArrayType::IonMobilityArray,
])
}
fn as_arrays(source: &[Self]) -> BinaryArrayMap {
let mut arrays = BinaryArrayMap::new();
let mut mz_array = DataArray::from_name_type_size(
&ArrayType::MZArray,
BinaryDataArrayType::Float64,
source.len() * BinaryDataArrayType::Float64.size_of(),
);
mz_array.unit = Unit::MZ;
let mut intensity_array = DataArray::from_name_type_size(
&ArrayType::IntensityArray,
BinaryDataArrayType::Float32,
source.len() * BinaryDataArrayType::Float32.size_of(),
);
intensity_array.unit = Unit::DetectorCounts;
let mut charge_array = DataArray::from_name_type_size(
&ArrayType::ChargeArray,
BinaryDataArrayType::Int32,
source.len() * BinaryDataArrayType::Int32.size_of(),
);
let mut im_array = DataArray::from_name_type_size(
&ArrayType::IonMobilityArray,
BinaryDataArrayType::Float64,
source.len() * BinaryDataArrayType::Float64.size_of(),
);
mz_array.compression = BinaryCompressionType::Decoded;
intensity_array.compression = BinaryCompressionType::Decoded;
im_array.compression = BinaryCompressionType::Decoded;
charge_array.compression = BinaryCompressionType::Decoded;
for p in source.iter() {
let mz: f64 = p.mz();
let inten: f32 = p.intensity();
let im = p.ion_mobility();
mz_array.data.extend_from_slice(&mz.to_le_bytes());
intensity_array.data.extend_from_slice(&inten.to_le_bytes());
im_array.data.extend_from_slice(&im.to_le_bytes());
charge_array
.data
.extend_from_slice(&p.charge().to_le_bytes());
}
arrays.add(mz_array);
arrays.add(intensity_array);
arrays.add(im_array);
arrays.add(charge_array);
arrays
}
}
impl BuildFromArrayMap for mzpeaks::peak::IonMobilityAwareDeconvolutedPeak {
fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
let mz_array = arrays.mzs()?;
let intensity_array = arrays.intensities()?;
let charge_array = arrays.charges()?;
let (im_array, _) = arrays.ion_mobility()?;
let mut peaks = Vec::with_capacity(mz_array.len());
for (i, (mz, (intensity, (ion_mobility, charge)))) in mz_array
.iter()
.zip(
intensity_array
.iter()
.zip(im_array.iter().zip(charge_array.iter())),
)
.enumerate()
{
let mass = neutral_mass(*mz, *charge);
peaks.push(mzpeaks::peak::IonMobilityAwareDeconvolutedPeak {
neutral_mass: mass,
intensity: *intensity,
index: i as u32,
ion_mobility: *ion_mobility,
charge: *charge,
})
}
Ok(peaks)
}
fn arrays_required() -> Option<Vec<ArrayType>> {
Some(vec![
ArrayType::MZArray,
ArrayType::IntensityArray,
ArrayType::ChargeArray,
ArrayType::IonMobilityArray,
])
}
}