1use std::{collections::HashSet, convert::TryInto, mem};
2
3use mzpeaks::{
4 prelude::*,
5 feature::{ChargedFeature, Feature},
6 CentroidLike, CentroidPeak, CoordinateLike, DeconvolutedPeak, DeconvolutedPeakSet,
7 IonMobility,MZPeakSetType, Mass, PeakSet,
8 MZ,
9};
10
11use mzdata_param::Unit;
12
13use crate::{utils::{mass_charge_ratio, neutral_mass}};
14
15use super::{
16 array::DataArray,
17 encodings::{ArrayRetrievalError, ArrayType, BinaryCompressionType, BinaryDataArrayType},
18 map::BinaryArrayMap,
19 BinaryArrayMap3D, ByteArrayView,
20};
21
22impl From<&PeakSet> for BinaryArrayMap {
23 fn from(peaks: &PeakSet) -> BinaryArrayMap {
24 let mut arrays = BinaryArrayMap::new();
25
26 let mut mz_array = DataArray::from_name_type_size(
27 &ArrayType::MZArray,
28 BinaryDataArrayType::Float64,
29 peaks.len() * BinaryDataArrayType::Float64.size_of(),
30 );
31
32 let mut intensity_array = DataArray::from_name_type_size(
33 &ArrayType::IntensityArray,
34 BinaryDataArrayType::Float32,
35 peaks.len() * BinaryDataArrayType::Float32.size_of(),
36 );
37
38 mz_array.compression = BinaryCompressionType::Decoded;
39 intensity_array.compression = BinaryCompressionType::Decoded;
40
41 for p in peaks.iter() {
42 let mz: f64 = p.coordinate();
43 let inten: f32 = p.intensity();
44
45 let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
46 mz_array.data.extend(raw_bytes);
47
48 let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
49 intensity_array.data.extend(raw_bytes);
50 }
51
52 arrays.add(mz_array);
53 arrays.add(intensity_array);
54 arrays
55 }
56}
57
58impl<C: CentroidLike + From<CentroidPeak>> From<BinaryArrayMap> for MZPeakSetType<C> {
59 fn from(arrays: BinaryArrayMap) -> MZPeakSetType<C> {
60 (&arrays).into()
61 }
62}
63
64impl<C: CentroidLike + From<CentroidPeak>> From<&BinaryArrayMap> for MZPeakSetType<C> {
65 fn from(arrays: &BinaryArrayMap) -> MZPeakSetType<C> {
66 let mz_array = arrays.mzs().unwrap();
67 let intensity_array = arrays.intensities().unwrap();
68 let mut peaks = Vec::with_capacity(mz_array.len());
69
70 for (i, (mz, intensity)) in mz_array.iter().zip(intensity_array.iter()).enumerate() {
71 peaks.push(
72 CentroidPeak {
73 mz: *mz,
74 intensity: *intensity,
75 index: i as u32,
76 }
77 .into(),
78 )
79 }
80 MZPeakSetType::<C>::new(peaks)
81 }
82}
83
84impl From<&BinaryArrayMap> for DeconvolutedPeakSet {
85 fn from(arrays: &BinaryArrayMap) -> DeconvolutedPeakSet {
86 let mz_array = arrays.mzs().unwrap();
87 let intensity_array = arrays.intensities().unwrap();
88 let charge_array = arrays
89 .charges()
90 .expect("Charge state array is required for deconvoluted peaks");
91 let mut peaks = Vec::with_capacity(mz_array.len());
92 for (i, ((mz, intensity), charge)) in mz_array
93 .iter()
94 .zip(intensity_array.iter())
95 .zip(charge_array.iter())
96 .enumerate()
97 {
98 peaks.push(DeconvolutedPeak {
99 neutral_mass: neutral_mass(*mz, *charge),
100 intensity: *intensity,
101 charge: *charge,
102 index: i as u32,
103 })
104 }
105
106 DeconvolutedPeakSet::new(peaks)
107 }
108}
109
110impl From<&DeconvolutedPeakSet> for BinaryArrayMap {
111 fn from(peaks: &DeconvolutedPeakSet) -> BinaryArrayMap {
112 let mut arrays = BinaryArrayMap::new();
113
114 let mut mz_array = DataArray::from_name_type_size(
115 &ArrayType::MZArray,
116 BinaryDataArrayType::Float64,
117 peaks.len() * BinaryDataArrayType::Float64.size_of(),
118 );
119
120 let mut intensity_array = DataArray::from_name_type_size(
121 &ArrayType::IntensityArray,
122 BinaryDataArrayType::Float32,
123 peaks.len() * BinaryDataArrayType::Float32.size_of(),
124 );
125
126 let mut charge_array = DataArray::from_name_type_size(
127 &ArrayType::ChargeArray,
128 BinaryDataArrayType::Int32,
129 peaks.len() * BinaryDataArrayType::Int32.size_of(),
130 );
131
132 mz_array.compression = BinaryCompressionType::Decoded;
133 intensity_array.compression = BinaryCompressionType::Decoded;
134 charge_array.compression = BinaryCompressionType::Decoded;
135
136 for p in peaks.iter() {
137 let mz: f64 = p.mz();
138 let inten: f32 = p.intensity();
139 let charge = p.charge();
140
141 let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
142 mz_array.data.extend_from_slice(&raw_bytes);
143
144 let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
145 intensity_array.data.extend_from_slice(&raw_bytes);
146
147 let raw_bytes: [u8; mem::size_of::<i32>()] = charge.to_le_bytes();
148 charge_array.data.extend_from_slice(&raw_bytes);
149 }
150
151 arrays.add(mz_array);
152 arrays.add(intensity_array);
153 arrays.add(charge_array);
154 arrays
155 }
156}
157
158#[derive(Debug, Clone)]
159pub enum ArraysAvailable {
160 Unknown,
161 Ok,
162 MissingArrays(Vec<ArrayType>),
163}
164
165pub trait BuildFromArrayMap: Sized {
166 fn arrays_required() -> Option<Vec<ArrayType>> {
167 None
168 }
169
170 fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError>;
171
172 fn from_arrays(arrays: &BinaryArrayMap) -> Vec<Self> {
173 Self::try_from_arrays(arrays).unwrap()
174 }
175
176 fn has_arrays_for(arrays: &BinaryArrayMap) -> ArraysAvailable {
178 if let Some(arrays_required) = Self::arrays_required() {
179 let missing: Vec<_> = arrays_required
180 .into_iter()
181 .filter(|array_type| !arrays.has_array(array_type))
182 .collect();
183 if !missing.is_empty() {
184 ArraysAvailable::MissingArrays(missing)
185 } else {
186 ArraysAvailable::Ok
187 }
188 } else {
189 ArraysAvailable::Unknown
190 }
191 }
192}
193
194pub trait BuildArrayMapFrom: Sized {
195 fn arrays_included(&self) -> Option<Vec<ArrayType>> {
196 None
197 }
198
199 fn as_arrays(source: &[Self]) -> BinaryArrayMap;
200}
201
202pub trait BuildArrayMap3DFrom: BuildArrayMapFrom {
203 fn as_arrays_3d(source: &[Self]) -> BinaryArrayMap3D {
204 BuildArrayMapFrom::as_arrays(source).try_into().unwrap()
205 }
206}
207
208pub trait BuildFromArrayMap3D: BuildFromArrayMap {
209 fn try_from_arrays_3d(arrays: &BinaryArrayMap3D) -> Result<Vec<Self>, ArrayRetrievalError> {
210 BuildFromArrayMap::try_from_arrays(&arrays.unstack()?)
211 }
212
213 fn from_arrays_3d(arrays: &BinaryArrayMap3D) -> Vec<Self> {
214 Self::try_from_arrays_3d(arrays).unwrap()
215 }
216
217 fn has_arrays_3d_for(arrays: &BinaryArrayMap3D) -> ArraysAvailable {
218 if let Some(arrays_required) = Self::arrays_required() {
219 let arrays_required: Vec<_> = arrays_required
220 .into_iter()
221 .filter(|a| !a.is_ion_mobility())
222 .collect();
223 let mut arrays_not_seen: HashSet<_> = arrays_required.iter().cloned().collect();
224 let mut missing = Vec::new();
225 for (_, arr) in arrays.iter() {
226 if arr.is_empty() {
227 continue;
228 }
229 missing.clear();
230 for array_type in arrays_required.iter() {
231 if arr.has_array(array_type) {
232 arrays_not_seen.remove(array_type);
233 } else {
234 missing.push(array_type);
235 }
236 }
237 if missing.is_empty() {
238 return ArraysAvailable::Ok;
239 }
240 }
241 if arrays_not_seen.is_empty() {
242 ArraysAvailable::Unknown
243 } else {
244 ArraysAvailable::MissingArrays(arrays_not_seen.into_iter().collect())
245 }
246 } else {
247 ArraysAvailable::Unknown
248 }
249 }
250}
251
252impl BuildArrayMapFrom for CentroidPeak {
255 fn arrays_included(&self) -> Option<Vec<ArrayType>> {
256 Some(vec![ArrayType::MZArray, ArrayType::IntensityArray])
257 }
258
259 fn as_arrays(source: &[Self]) -> BinaryArrayMap {
260 let mut arrays = BinaryArrayMap::new();
261
262 let mut mz_array = DataArray::from_name_type_size(
263 &ArrayType::MZArray,
264 BinaryDataArrayType::Float64,
265 source.len() * BinaryDataArrayType::Float64.size_of(),
266 );
267 mz_array.unit = Unit::MZ;
268
269 let mut intensity_array = DataArray::from_name_type_size(
270 &ArrayType::IntensityArray,
271 BinaryDataArrayType::Float32,
272 source.len() * BinaryDataArrayType::Float32.size_of(),
273 );
274 intensity_array.unit = Unit::DetectorCounts;
275
276 mz_array.compression = BinaryCompressionType::Decoded;
277 intensity_array.compression = BinaryCompressionType::Decoded;
278
279 for p in source.iter() {
280 let mz: f64 = p.coordinate();
281 let inten: f32 = p.intensity();
282
283 let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
284 mz_array.data.extend_from_slice(&raw_bytes);
285
286 let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
287 intensity_array.data.extend_from_slice(&raw_bytes);
288 }
289
290 arrays.add(mz_array);
291 arrays.add(intensity_array);
292 arrays
293 }
294}
295
296impl BuildFromArrayMap for CentroidPeak {
297 fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
298 let mz_array = arrays.mzs()?;
299 let intensity_array = arrays.intensities()?;
300 let mut peaks = Vec::with_capacity(mz_array.len());
301
302 for (i, (mz, intensity)) in mz_array.iter().zip(intensity_array.iter()).enumerate() {
303 peaks.push(CentroidPeak {
304 mz: *mz,
305 intensity: *intensity,
306 index: i as u32,
307 })
308 }
309 Ok(peaks)
310 }
311
312 fn arrays_required() -> Option<Vec<ArrayType>> {
313 Some(vec![ArrayType::MZArray, ArrayType::IntensityArray])
314 }
315}
316
317impl BuildArrayMapFrom for DeconvolutedPeak {
318 fn as_arrays(source: &[Self]) -> BinaryArrayMap {
319 let mut arrays = BinaryArrayMap::new();
320
321 let mut mz_array = DataArray::from_name_type_size(
322 &ArrayType::MZArray,
323 BinaryDataArrayType::Float64,
324 source.len() * BinaryDataArrayType::Float64.size_of(),
325 );
326 mz_array.unit = Unit::MZ;
327
328 let mut intensity_array = DataArray::from_name_type_size(
329 &ArrayType::IntensityArray,
330 BinaryDataArrayType::Float32,
331 source.len() * BinaryDataArrayType::Float32.size_of(),
332 );
333 intensity_array.unit = Unit::DetectorCounts;
334
335 let mut charge_array = DataArray::from_name_type_size(
336 &ArrayType::ChargeArray,
337 BinaryDataArrayType::Int32,
338 source.len() * BinaryDataArrayType::Int32.size_of(),
339 );
340
341 mz_array.compression = BinaryCompressionType::Decoded;
342 intensity_array.compression = BinaryCompressionType::Decoded;
343 charge_array.compression = BinaryCompressionType::Decoded;
344
345 for p in source.iter() {
346 let mz: f64 = p.mz();
347 let inten: f32 = p.intensity();
348 let charge = p.charge();
349
350 let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
351 mz_array.data.extend_from_slice(&raw_bytes);
352
353 let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
354 intensity_array.data.extend_from_slice(&raw_bytes);
355
356 let raw_bytes: [u8; mem::size_of::<i32>()] = charge.to_le_bytes();
357 charge_array.data.extend_from_slice(&raw_bytes);
358 }
359
360 arrays.add(mz_array);
361 arrays.add(intensity_array);
362 arrays.add(charge_array);
363 arrays
364 }
365
366 fn arrays_included(&self) -> Option<Vec<ArrayType>> {
367 Some(vec![
368 ArrayType::MZArray,
369 ArrayType::IntensityArray,
370 ArrayType::ChargeArray,
371 ])
372 }
373}
374
375impl BuildFromArrayMap for DeconvolutedPeak {
376 fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
377 let mz_array = arrays.mzs()?;
378 let intensity_array = arrays.intensities()?;
379 let charge_array = arrays.charges()?;
380 let mut peaks = Vec::with_capacity(mz_array.len());
381 for (i, ((mz, intensity), charge)) in mz_array
382 .iter()
383 .zip(intensity_array.iter())
384 .zip(charge_array.iter())
385 .enumerate()
386 {
387 peaks.push(DeconvolutedPeak {
388 neutral_mass: neutral_mass(*mz, *charge),
389 intensity: *intensity,
390 charge: *charge,
391 index: i as u32,
392 })
393 }
394
395 Ok(peaks)
396 }
397}
398
399impl BuildArrayMapFrom for Feature<MZ, IonMobility> {
402 fn arrays_included(&self) -> Option<Vec<ArrayType>> {
403 Some(vec![
404 ArrayType::MZArray,
405 ArrayType::IntensityArray,
406 ArrayType::RawIonMobilityArray,
407 ArrayType::nonstandard("feature identifier array"),
408 ])
409 }
410
411 fn as_arrays(source: &[Self]) -> BinaryArrayMap {
412 let mut arrays = BinaryArrayMap::new();
413 let n: usize = source.iter().map(|f| f.len()).sum();
414
415 let mut mz_array = DataArray::from_name_type_size(
416 &ArrayType::MZArray,
417 BinaryDataArrayType::Float64,
418 n * BinaryDataArrayType::Float64.size_of(),
419 );
420 mz_array.unit = Unit::MZ;
421
422 let mut intensity_array = DataArray::from_name_type_size(
423 &ArrayType::IntensityArray,
424 BinaryDataArrayType::Float32,
425 n * BinaryDataArrayType::Float32.size_of(),
426 );
427 intensity_array.unit = Unit::DetectorCounts;
428
429 let mut ion_mobility_array = DataArray::from_name_type_size(
430 &ArrayType::RawIonMobilityArray,
431 BinaryDataArrayType::Float64,
432 n * BinaryDataArrayType::Float64.size_of(),
433 );
434
435 let mut marker_array = DataArray::from_name_type_size(
436 &ArrayType::nonstandard("feature identifier array"),
437 BinaryDataArrayType::Int32,
438 n * BinaryDataArrayType::Int32.size_of(),
439 );
440
441 mz_array.compression = BinaryCompressionType::Decoded;
442 intensity_array.compression = BinaryCompressionType::Decoded;
443 ion_mobility_array.compression = BinaryCompressionType::Decoded;
444 marker_array.compression = BinaryCompressionType::Decoded;
445
446 let mut acc = Vec::with_capacity(n);
447 source.iter().enumerate().for_each(|(i, f)| {
448 f.iter()
449 .for_each(|(mz, im, inten)| acc.push((mz, im, inten, i)))
450 });
451 acc.sort_by(|(mz_a, im_a, _, key_a), (mz_b, im_b, _, key_b)| {
452 mz_a.total_cmp(mz_b)
453 .then(im_a.total_cmp(im_b))
454 .then(key_a.cmp(key_b))
455 });
456
457 for (mz, im, inten, key) in acc.iter() {
458 mz_array.data.extend_from_slice(&mz.to_le_bytes());
459 intensity_array.data.extend_from_slice(&inten.to_le_bytes());
460 ion_mobility_array.data.extend_from_slice(&im.to_le_bytes());
461 marker_array
462 .data
463 .extend_from_slice(&(*key as i32).to_le_bytes());
464 }
465
466 arrays.add(mz_array);
467 arrays.add(intensity_array);
468 arrays.add(ion_mobility_array);
469 arrays.add(marker_array);
470 arrays
471 }
472}
473
474impl BuildFromArrayMap for Feature<MZ, IonMobility> {
475 fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
476 let mz_array = arrays.mzs()?;
477 let intensity_array = arrays.intensities()?;
478 let im_array = arrays
479 .get(&ArrayType::RawIonMobilityArray)
480 .ok_or(ArrayRetrievalError::NotFound(
481 ArrayType::RawIonMobilityArray,
482 ))?
483 .to_f64()?;
484
485 let array_key = ArrayType::nonstandard("feature identifier array");
486 let marker_array = arrays
487 .get(&array_key)
488 .ok_or(ArrayRetrievalError::NotFound(array_key))?
489 .to_i32()?;
490
491 let n = marker_array.iter().map(|i| *i as usize).max();
492
493 let mut features = if let Some(n) = n {
494 let mut features = Vec::with_capacity(n);
495 features.resize(n, Feature::default());
496 features
497 } else {
498 return Ok(Vec::new());
499 };
500
501 mz_array
502 .iter()
503 .zip(intensity_array.iter())
504 .zip(im_array.iter())
505 .zip(marker_array.iter())
506 .for_each(|(((mz, inten), im), key)| {
507 features[(*key) as usize].push_raw(*mz, *im, *inten);
508 });
509
510 Ok(features)
511 }
512}
513
514impl BuildArrayMapFrom for ChargedFeature<Mass, IonMobility> {
515 fn arrays_included(&self) -> Option<Vec<ArrayType>> {
516 Some(vec![
517 ArrayType::MZArray,
518 ArrayType::IntensityArray,
519 ArrayType::RawIonMobilityArray,
520 ArrayType::ChargeArray,
521 ArrayType::nonstandard("feature identifier array"),
522 ])
523 }
524
525 fn as_arrays(source: &[Self]) -> BinaryArrayMap {
526 let mut arrays = BinaryArrayMap::new();
527 let n: usize = source.iter().map(|f| f.len()).sum();
528
529 let mut mz_array = DataArray::from_name_type_size(
530 &ArrayType::MZArray,
531 BinaryDataArrayType::Float64,
532 n * BinaryDataArrayType::Float64.size_of(),
533 );
534 mz_array.unit = Unit::MZ;
535
536 let mut intensity_array = DataArray::from_name_type_size(
537 &ArrayType::IntensityArray,
538 BinaryDataArrayType::Float32,
539 n * BinaryDataArrayType::Float32.size_of(),
540 );
541 intensity_array.unit = Unit::DetectorCounts;
542
543 let mut charge_array = DataArray::from_name_type_size(
544 &ArrayType::ChargeArray,
545 BinaryDataArrayType::Int32,
546 n * BinaryDataArrayType::Int32.size_of(),
547 );
548
549 let mut ion_mobility_array = DataArray::from_name_type_size(
550 &ArrayType::RawIonMobilityArray,
551 BinaryDataArrayType::Float64,
552 n * BinaryDataArrayType::Float64.size_of(),
553 );
554
555 let mut marker_array = DataArray::from_name_type_size(
556 &ArrayType::nonstandard("feature identifier array"),
557 BinaryDataArrayType::Int32,
558 n * BinaryDataArrayType::Int32.size_of(),
559 );
560
561 mz_array.compression = BinaryCompressionType::Decoded;
562 intensity_array.compression = BinaryCompressionType::Decoded;
563 ion_mobility_array.compression = BinaryCompressionType::Decoded;
564 marker_array.compression = BinaryCompressionType::Decoded;
565
566 let mut acc = Vec::with_capacity(n);
567 source.iter().enumerate().for_each(|(i, f)| {
568 f.iter().for_each(|(mass, im, inten)| {
569 acc.push((mass_charge_ratio(mass, f.charge), im, inten, f.charge, i))
570 })
571 });
572 acc.sort_by(|(mz_a, im_a, _, _, key_a), (mz_b, im_b, _, _, key_b)| {
573 mz_a.total_cmp(mz_b)
574 .then(im_a.total_cmp(im_b))
575 .then(key_a.cmp(key_b))
576 });
577
578 for (mz, im, inten, charge, key) in acc.iter() {
579 mz_array.data.extend(mz.to_le_bytes());
580 intensity_array.data.extend(inten.to_le_bytes());
581 ion_mobility_array.data.extend(im.to_le_bytes());
582 charge_array.data.extend(charge.to_le_bytes());
583 marker_array.data.extend((*key as i32).to_le_bytes());
584 }
585
586 arrays.add(mz_array);
587 arrays.add(intensity_array);
588 arrays.add(ion_mobility_array);
589 arrays.add(charge_array);
590 arrays.add(marker_array);
591 arrays
592 }
593}
594
595impl BuildFromArrayMap for ChargedFeature<Mass, IonMobility> {
596 fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
597 let mz_array = arrays.mzs()?;
598 let intensity_array = arrays.intensities()?;
599 let im_array = arrays
600 .get(&ArrayType::RawIonMobilityArray)
601 .ok_or(ArrayRetrievalError::NotFound(
602 ArrayType::RawIonMobilityArray,
603 ))?
604 .to_f64()?;
605
606 let charge_array = arrays
607 .get(&ArrayType::ChargeArray)
608 .ok_or(ArrayRetrievalError::NotFound(ArrayType::ChargeArray))?
609 .to_i32()?;
610
611 let array_key = ArrayType::nonstandard("feature identifier array");
612 let marker_array = arrays
613 .get(&array_key)
614 .ok_or(ArrayRetrievalError::NotFound(array_key))?
615 .to_i32()?;
616
617 let n = marker_array.iter().map(|i| *i as usize).max();
618
619 let mut features = if let Some(n) = n {
620 let mut features = Vec::with_capacity(n);
621 features.resize(n, ChargedFeature::default());
622 features
623 } else {
624 return Ok(Vec::new());
625 };
626
627 mz_array
628 .iter()
629 .zip(intensity_array.iter())
630 .zip(im_array.iter().zip(charge_array.iter()))
631 .zip(marker_array.iter())
632 .for_each(|(((mz, inten), (im, charge)), key)| {
633 let f = &mut features[(*key) as usize];
634 if f.is_empty() {
635 f.charge = *charge;
636 }
637 f.push_raw(neutral_mass(*mz, *charge), *im, *inten);
638 });
639
640 Ok(features)
641 }
642}
643
644impl BuildArrayMap3DFrom for Feature<MZ, IonMobility> {}
645
646impl BuildFromArrayMap3D for Feature<MZ, IonMobility> {
647 fn try_from_arrays_3d(arrays: &BinaryArrayMap3D) -> Result<Vec<Self>, ArrayRetrievalError> {
648 let key = ArrayType::nonstandard("feature identifier array");
649 let mut n: usize = 0;
650 for (_, arr) in arrays.iter() {
651 if arr.is_empty() {
652 continue;
653 }
654 if let Some(arr) = arr.get(&key) {
655 if let Some(i) = arr.iter_i32()?.map(|i| i as usize).max() {
656 n = n.max(i);
657 }
658 }
659 }
660
661 if n == 0 {
662 return Ok(Vec::new());
663 }
664 n += 1;
665 let mut index = Vec::with_capacity(n);
666 index.resize(n, Feature::default());
667
668 for (im, arr) in arrays.iter() {
669 if arr.is_empty() {
670 continue;
671 }
672
673 let mz_array = arr.mzs()?;
674 let intensity_array = arr.intensities()?;
675 let marker_array = arr
676 .get(&key)
677 .ok_or_else(|| ArrayRetrievalError::NotFound(key.clone()))?
678 .to_i32()?;
679
680 for ((mz, inten), key_i) in mz_array
681 .iter()
682 .zip(intensity_array.iter())
683 .zip(marker_array.iter())
684 {
685 index[(*key_i) as usize].push_raw(*mz, im, *inten);
686 }
687 }
688
689 Ok(index)
690 }
691}
692
693impl BuildArrayMap3DFrom for ChargedFeature<Mass, IonMobility> {}
694
695impl BuildFromArrayMap3D for ChargedFeature<Mass, IonMobility> {
696 fn try_from_arrays_3d(arrays: &BinaryArrayMap3D) -> Result<Vec<Self>, ArrayRetrievalError> {
697 let key = ArrayType::nonstandard("feature identifier array");
698 let mut n: usize = 0;
699 for (_, arr) in arrays.iter() {
700 if arr.is_empty() {
701 continue;
702 }
703 if let Some(arr) = arr.get(&key) {
704 if let Some(i) = arr.iter_i32()?.map(|i| i as usize).max() {
705 n = n.max(i);
706 }
707 }
708 }
709
710 if n == 0 {
711 return Ok(Vec::new());
712 }
713 n += 1;
714 let mut index = Vec::with_capacity(n);
715 index.resize(n, ChargedFeature::default());
716
717 for (im, arr) in arrays.iter() {
718 if arr.is_empty() {
719 continue;
720 }
721
722 let mz_array = arr.mzs()?;
723 let intensity_array = arr.intensities()?;
724 let marker_array = arr
725 .get(&key)
726 .ok_or_else(|| ArrayRetrievalError::NotFound(key.clone()))?
727 .to_i32()?;
728 let charge_array = arr.charges()?;
729
730 for ((mz, inten), (charge, key_i)) in mz_array
731 .iter()
732 .zip(intensity_array.iter())
733 .zip(charge_array.iter().zip(marker_array.iter()))
734 {
735 let f = &mut index[(*key_i) as usize];
736 f.push_raw(*mz, im, *inten);
737 f.charge = *charge;
738 }
739 }
740
741 Ok(index)
742 }
743}
744
745impl BuildArrayMapFrom for mzpeaks::peak::IonMobilityAwareCentroidPeak {
748 fn arrays_included(&self) -> Option<Vec<ArrayType>> {
749 Some(vec![
750 ArrayType::MZArray,
751 ArrayType::IntensityArray,
752 ArrayType::IonMobilityArray,
753 ])
754 }
755
756 fn as_arrays(source: &[Self]) -> BinaryArrayMap {
757 let mut arrays = BinaryArrayMap::new();
758
759 let mut mz_array = DataArray::from_name_type_size(
760 &ArrayType::MZArray,
761 BinaryDataArrayType::Float64,
762 source.len() * BinaryDataArrayType::Float64.size_of(),
763 );
764 mz_array.unit = Unit::MZ;
765
766 let mut intensity_array = DataArray::from_name_type_size(
767 &ArrayType::IntensityArray,
768 BinaryDataArrayType::Float32,
769 source.len() * BinaryDataArrayType::Float32.size_of(),
770 );
771 intensity_array.unit = Unit::DetectorCounts;
772
773 let mut im_array = DataArray::from_name_type_size(
774 &ArrayType::IonMobilityArray,
775 BinaryDataArrayType::Float64,
776 source.len() * BinaryDataArrayType::Float64.size_of(),
777 );
778
779 mz_array.compression = BinaryCompressionType::Decoded;
780 intensity_array.compression = BinaryCompressionType::Decoded;
781 im_array.compression = BinaryCompressionType::Decoded;
782
783 for p in source.iter() {
784 let mz: f64 = p.mz();
785 let inten: f32 = p.intensity();
786 let im = p.ion_mobility();
787
788 let raw_bytes: [u8; mem::size_of::<f64>()] = mz.to_le_bytes();
789 mz_array.data.extend_from_slice(&raw_bytes);
790
791 let raw_bytes: [u8; mem::size_of::<f32>()] = inten.to_le_bytes();
792 intensity_array.data.extend_from_slice(&raw_bytes);
793
794 let raw_bytes: [u8; mem::size_of::<f64>()] = im.to_le_bytes();
795 im_array.data.extend_from_slice(&raw_bytes);
796 }
797
798 arrays.add(mz_array);
799 arrays.add(intensity_array);
800 arrays.add(im_array);
801 arrays
802 }
803}
804
805impl BuildFromArrayMap for mzpeaks::peak::IonMobilityAwareCentroidPeak {
806 fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
807 let mz_array = arrays.mzs()?;
808 let intensity_array = arrays.intensities()?;
809 let (im_array, _) = arrays.ion_mobility()?;
810 let mut peaks = Vec::with_capacity(mz_array.len());
811
812 for (i, (mz, (intensity, ion_mobility))) in mz_array
813 .iter()
814 .zip(intensity_array.iter().zip(im_array.iter()))
815 .enumerate()
816 {
817 peaks.push(mzpeaks::peak::IonMobilityAwareCentroidPeak {
818 mz: *mz,
819 intensity: *intensity,
820 index: i as u32,
821 ion_mobility: *ion_mobility,
822 })
823 }
824 Ok(peaks)
825 }
826
827 fn arrays_required() -> Option<Vec<ArrayType>> {
828 Some(vec![
829 ArrayType::MZArray,
830 ArrayType::IntensityArray,
831 ArrayType::IonMobilityArray,
832 ])
833 }
834}
835
836impl BuildArrayMapFrom for mzpeaks::peak::IonMobilityAwareDeconvolutedPeak {
837 fn arrays_included(&self) -> Option<Vec<ArrayType>> {
838 Some(vec![
839 ArrayType::MZArray,
840 ArrayType::IntensityArray,
841 ArrayType::ChargeArray,
842 ArrayType::IonMobilityArray,
843 ])
844 }
845
846 fn as_arrays(source: &[Self]) -> BinaryArrayMap {
847 let mut arrays = BinaryArrayMap::new();
848
849 let mut mz_array = DataArray::from_name_type_size(
850 &ArrayType::MZArray,
851 BinaryDataArrayType::Float64,
852 source.len() * BinaryDataArrayType::Float64.size_of(),
853 );
854 mz_array.unit = Unit::MZ;
855
856 let mut intensity_array = DataArray::from_name_type_size(
857 &ArrayType::IntensityArray,
858 BinaryDataArrayType::Float32,
859 source.len() * BinaryDataArrayType::Float32.size_of(),
860 );
861 intensity_array.unit = Unit::DetectorCounts;
862
863 let mut charge_array = DataArray::from_name_type_size(
864 &ArrayType::ChargeArray,
865 BinaryDataArrayType::Int32,
866 source.len() * BinaryDataArrayType::Int32.size_of(),
867 );
868
869 let mut im_array = DataArray::from_name_type_size(
870 &ArrayType::IonMobilityArray,
871 BinaryDataArrayType::Float64,
872 source.len() * BinaryDataArrayType::Float64.size_of(),
873 );
874
875 mz_array.compression = BinaryCompressionType::Decoded;
876 intensity_array.compression = BinaryCompressionType::Decoded;
877 im_array.compression = BinaryCompressionType::Decoded;
878 charge_array.compression = BinaryCompressionType::Decoded;
879
880 for p in source.iter() {
881 let mz: f64 = p.mz();
882 let inten: f32 = p.intensity();
883 let im = p.ion_mobility();
884
885 mz_array.data.extend_from_slice(&mz.to_le_bytes());
886 intensity_array.data.extend_from_slice(&inten.to_le_bytes());
887 im_array.data.extend_from_slice(&im.to_le_bytes());
888 charge_array
889 .data
890 .extend_from_slice(&p.charge().to_le_bytes());
891 }
892
893 arrays.add(mz_array);
894 arrays.add(intensity_array);
895 arrays.add(im_array);
896 arrays.add(charge_array);
897 arrays
898 }
899}
900
901impl BuildFromArrayMap for mzpeaks::peak::IonMobilityAwareDeconvolutedPeak {
902 fn try_from_arrays(arrays: &BinaryArrayMap) -> Result<Vec<Self>, ArrayRetrievalError> {
903 let mz_array = arrays.mzs()?;
904 let intensity_array = arrays.intensities()?;
905 let charge_array = arrays.charges()?;
906 let (im_array, _) = arrays.ion_mobility()?;
907 let mut peaks = Vec::with_capacity(mz_array.len());
908
909 for (i, (mz, (intensity, (ion_mobility, charge)))) in mz_array
910 .iter()
911 .zip(
912 intensity_array
913 .iter()
914 .zip(im_array.iter().zip(charge_array.iter())),
915 )
916 .enumerate()
917 {
918 let mass = neutral_mass(*mz, *charge);
919 peaks.push(mzpeaks::peak::IonMobilityAwareDeconvolutedPeak {
920 neutral_mass: mass,
921 intensity: *intensity,
922 index: i as u32,
923 ion_mobility: *ion_mobility,
924 charge: *charge,
925 })
926 }
927 Ok(peaks)
928 }
929
930 fn arrays_required() -> Option<Vec<ArrayType>> {
931 Some(vec![
932 ArrayType::MZArray,
933 ArrayType::IntensityArray,
934 ArrayType::ChargeArray,
935 ArrayType::IonMobilityArray,
936 ])
937 }
938}