bam_builder/
bam_order.rs

1//! Specification for how to sort BAM records based on [`BamSortOrder`].
2#![warn(missing_docs)]
3use super::DEFAULT_SEED;
4use rand::prelude::*;
5use rust_htslib::bam::record::Record;
6use std::cmp::Ordering;
7/// Sort order options for reads
8#[derive(Debug)]
9pub enum BamSortOrder {
10    /// Sort by `qname`.
11    NameSorted,
12    /// Sort by `tid` and `pos`.
13    CoordSorted,
14    /// Leave records in current order.
15    Unsorted,
16    /// Randomly shuffle records.
17    Random,
18}
19
20impl BamSortOrder {
21    /// Sort `records` based on the [`BamSortOrder`] variant.
22    pub fn sort(&self, records: &mut [Record]) {
23        match self {
24            BamSortOrder::NameSorted => records.sort_by(|a, b| {
25                let name_cmp = a.qname().cmp(b.qname());
26                match name_cmp {
27                    Ordering::Equal => a.flags().cmp(&b.flags()),
28                    _ => name_cmp,
29                }
30            }),
31            BamSortOrder::CoordSorted => records.sort_by(|a, b| {
32                let ref_cmp = a.tid().cmp(&b.tid());
33                match ref_cmp {
34                    Ordering::Equal => {
35                        let pos_cmp = a.pos().cmp(&b.pos());
36                        match pos_cmp {
37                            Ordering::Equal => a.flags().cmp(&b.flags()),
38                            _ => pos_cmp,
39                        }
40                    }
41                    _ => ref_cmp,
42                }
43            }),
44            BamSortOrder::Unsorted => {} // do nothing
45            BamSortOrder::Random => {
46                let mut rng = StdRng::seed_from_u64(DEFAULT_SEED as u64);
47                records.shuffle(&mut rng);
48            }
49        }
50    }
51}
52
53impl Default for BamSortOrder {
54    /// Default for [`BamSortOrder`] is [`BamSortOrder::Unsorted`].
55    fn default() -> Self {
56        Self::Unsorted
57    }
58}