From a0a813e9eb3da24e2e09d892c6fac7bae23f4b14 Mon Sep 17 00:00:00 2001 From: romainlannes Date: Sun, 29 Sep 2024 22:01:20 -0400 Subject: [PATCH 1/7] added SamFlag module --- src/bam/sam_flag.rs | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/bam/sam_flag.rs diff --git a/src/bam/sam_flag.rs b/src/bam/sam_flag.rs new file mode 100644 index 000000000..747743e92 --- /dev/null +++ b/src/bam/sam_flag.rs @@ -0,0 +1,87 @@ + + +//! A module that provides an easier way to work with SAM flags. +//! It achieves this by providing a struct (`SamFlag`) with associated constants representing +//! flags, and the `check_flag()` function that allows testing if specific flags are set or not set. +//! +//! For example, the following code tests if the read flag has the FIRST_IN_PAIR flag set and the MATE_UNMAPPED flag not set: +//! ``` +//! use rust_htslib::bam::{SamFlag, check_flag}; +//! # let read_flag = record.flag(); in general this is the way to obtian a flag. +//! let read_flag = 64; +//! assert_eq!(check_flag(read_flag, SamFlag::FIRST_IN_PAIR, SamFlag::MATE_UNMAPPED), true); +//! ``` + + +/// +/// This structure contains constants representing SAM flag values as u16. +/// Using this structure incurs no runtime cost. +/// +/// ``` +/// use rust_htslib::bam::{SamFlag}; +/// to get the value of a flag representing a read paired, and reversly mapped. +/// let flag = SamFlag::PAIRED + SamFlag::READ_RERVERSE; +/// +/// ``` +pub struct SamFlag; + + +impl SamFlag { + pub const PAIRED: u16 = 1; + pub const PROPERLY_PAIRED: u16 = 2; + pub const READ_UNMAPPED: u16 = 4; + pub const MATE_UNMAPPED: u16 = 8; + pub const READ_RERVERSE: u16 = 16; + pub const MATE_REVERSE: u16 = 32; + pub const FIRST_IN_PAIR: u16 = 64; + pub const SECOND_IN_PAIR: u16 = 128; + pub const NOT_PRIMARY_ALN: u16 = 256; + pub const FAIL_QC: u16 = 512; + pub const DUPLICATE: u16 = 1024; + pub const SUPPLEMENTARY: u16 = 2048; +} + + +pub fn check_flag(flag: u16, in_: u16, not_in: u16) -> bool { + + //! This function uses bitwise operations to test if flags are set or not. + //! + //! # Arguments + //! + //! * `flag`: u16 - The record flag you want to test + //! * `in_`: u16 - The flags you want to check if they are set (use 0 for no test) + //! * `not_in`: u16 - The flags you want to check if they are not set (use 0 for no test) + //! + //! # Usage: + //! example: let test if a flag is both paired and fisrt in pair + //! ``` + //! use rust_htslib::bam::{SamFlag, check_flag}; + //! let read_flag = 18 + //! assert_eq!(check_flag(read_flag, SamFlag::PAIRED +SamFlag::FIRST_IN_PAIR, 0), true); + //! ``` + //! let test that the read is mapped. READ_UNMAPPED + //! ``` + //! use rust_htslib::bam::{SamFlag, check_flag}; + //! let read_flag = 18 + //! assert_eq!(check_flag(read_flag, 0, SamFlag::READ_UNMAPPED), true); + //! ``` + //! + //! Finally let do a more complexe real example test: + //! ``` + //! use rust_htslib::bam::{SamFlag, check_flag}; + //! let read_flag = 19 + //! assert_eq!(check_flag(read_flag, SamFlag::PAIRED + SamFlag::PROPERLY_PAIRED + SamFlag::READ_RERVERSE , SamFlag::READ_UNMAPPED + SamFlag::MATE_UNMAPPED), true); + //! ``` + //! + //binary flag check + //assert that: - in_ is in n + // - not_in is not in n + // bitwise operation + if (not_in & flag) != 0 { + return false; + } + if (in_ & flag) != in_ { + return false; + } + return true; +} From f76747cea92430295ef3679c606ca926e87a0a52 Mon Sep 17 00:00:00 2001 From: RomainL Date: Mon, 30 Sep 2024 08:44:30 -0400 Subject: [PATCH 2/7] Update mod.rs --- src/bam/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bam/mod.rs b/src/bam/mod.rs index ddf1d3221..03c334a78 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -11,6 +11,7 @@ pub mod header; pub mod index; pub mod pileup; pub mod record; +pub mod sam_flag; #[cfg(feature = "serde_feature")] pub mod record_serde; From 82f1e9096081bbcb200ed561f95c34faee074f06 Mon Sep 17 00:00:00 2001 From: rLannes Date: Tue, 12 Nov 2024 13:34:02 -0500 Subject: [PATCH 3/7] refactored the module and struct name, and ran cargo fmt --- src/bam/flags.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ src/bam/mod.rs | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/bam/flags.rs diff --git a/src/bam/flags.rs b/src/bam/flags.rs new file mode 100644 index 000000000..8bb74a165 --- /dev/null +++ b/src/bam/flags.rs @@ -0,0 +1,81 @@ +//! A module that provides an easier way to work with SAM flags. +//! It achieves this by providing a struct (`Flag`) with associated constants representing +//! flags, and the `check_flag()` function that allows testing if specific flags are set or not set. +//! +//! For example, the following code tests if the read flag has the FIRST_IN_PAIR flag set and the MATE_UNMAPPED flag not set: +//! ``` +//! use rust_htslib::bam::{Flag, check_flag}; +//! # let read_flag = record.flag(); in general this is the way to obtian a flag. +//! let read_flag = 64; +//! assert_eq!(check_flag(read_flag, Flag::FIRST_IN_PAIR, Flag::MATE_UNMAPPED), true); +//! ``` + +/// +/// This structure contains constants representing SAM flag values as u16. +/// Using this structure incurs no runtime cost. +/// +/// ``` +/// use rust_htslib::bam::{Flag}; +/// to get the value of a flag representing a read paired, and reversly mapped. +/// let flag = Flag::PAIRED + Flag::READ_RERVERSE; +/// +/// ``` +pub struct Flag; + +impl Flag { + pub const PAIRED: u16 = 1; + pub const PROPERLY_PAIRED: u16 = 2; + pub const READ_UNMAPPED: u16 = 4; + pub const MATE_UNMAPPED: u16 = 8; + pub const READ_RERVERSE: u16 = 16; + pub const MATE_REVERSE: u16 = 32; + pub const FIRST_IN_PAIR: u16 = 64; + pub const SECOND_IN_PAIR: u16 = 128; + pub const NOT_PRIMARY_ALN: u16 = 256; + pub const FAIL_QC: u16 = 512; + pub const DUPLICATE: u16 = 1024; + pub const SUPPLEMENTARY: u16 = 2048; +} + +pub fn check_flag(flag: u16, in_: u16, not_in: u16) -> bool { + //! This function uses bitwise operations to test if flags are set or not. + //! + //! # Arguments + //! + //! * `flag`: u16 - The record flag you want to test + //! * `in_`: u16 - The flags you want to check if they are set (use 0 for no test) + //! * `not_in`: u16 - The flags you want to check if they are not set (use 0 for no test) + //! + //! # Usage: + //! example: let test if a flag is both paired and fisrt in pair + //! ``` + //! use rust_htslib::bam::{Flag, check_flag}; + //! let read_flag = 18 + //! assert_eq!(check_flag(read_flag, Flag::PAIRED +Flag::FIRST_IN_PAIR, 0), true); + //! ``` + //! let test that the read is mapped. READ_UNMAPPED + //! ``` + //! use rust_htslib::bam::{Flag, check_flag}; + //! let read_flag = 18 + //! assert_eq!(check_flag(read_flag, 0, Flag::READ_UNMAPPED), true); + //! ``` + //! + //! Finally let do a more complexe real example test: + //! ``` + //! use rust_htslib::bam::{Flag, check_flag}; + //! let read_flag = 19 + //! assert_eq!(check_flag(read_flag, Flag::PAIRED + Flag::PROPERLY_PAIRED + Flag::READ_RERVERSE , Flag::READ_UNMAPPED + Flag::MATE_UNMAPPED), true); + //! ``` + //! + //binary flag check + //assert that: - in_ is in n + // - not_in is not in n + // bitwise operation + if (not_in & flag) != 0 { + return false; + } + if (in_ & flag) != in_ { + return false; + } + return true; +} diff --git a/src/bam/mod.rs b/src/bam/mod.rs index 03c334a78..b0c7ce75e 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -7,11 +7,11 @@ pub mod buffer; pub mod ext; +pub mod flags; pub mod header; pub mod index; pub mod pileup; pub mod record; -pub mod sam_flag; #[cfg(feature = "serde_feature")] pub mod record_serde; From 42a83caf100ee702f38e6f85c4111333b2b671a3 Mon Sep 17 00:00:00 2001 From: rLannes Date: Wed, 13 Nov 2024 15:09:38 -0500 Subject: [PATCH 4/7] with module name change the docstring import was not working. Fixed. --- src/bam/flags.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/bam/flags.rs b/src/bam/flags.rs index 8bb74a165..cc1909a92 100644 --- a/src/bam/flags.rs +++ b/src/bam/flags.rs @@ -4,7 +4,7 @@ //! //! For example, the following code tests if the read flag has the FIRST_IN_PAIR flag set and the MATE_UNMAPPED flag not set: //! ``` -//! use rust_htslib::bam::{Flag, check_flag}; +//! use rust_htslib::bam::flags{Flag, check_flag}; //! # let read_flag = record.flag(); in general this is the way to obtian a flag. //! let read_flag = 64; //! assert_eq!(check_flag(read_flag, Flag::FIRST_IN_PAIR, Flag::MATE_UNMAPPED), true); @@ -13,10 +13,10 @@ /// /// This structure contains constants representing SAM flag values as u16. /// Using this structure incurs no runtime cost. -/// +/// /// ``` -/// use rust_htslib::bam::{Flag}; -/// to get the value of a flag representing a read paired, and reversly mapped. +/// use rust_htslib::bam::flags::Flag; +/// // to get the value of a flag representing a read paired, and reversly mapped. /// let flag = Flag::PAIRED + Flag::READ_RERVERSE; /// /// ``` @@ -47,23 +47,23 @@ pub fn check_flag(flag: u16, in_: u16, not_in: u16) -> bool { //! * `not_in`: u16 - The flags you want to check if they are not set (use 0 for no test) //! //! # Usage: - //! example: let test if a flag is both paired and fisrt in pair + //! example: let test if a flag is both paired and first in pair //! ``` - //! use rust_htslib::bam::{Flag, check_flag}; - //! let read_flag = 18 - //! assert_eq!(check_flag(read_flag, Flag::PAIRED +Flag::FIRST_IN_PAIR, 0), true); + //! use rust_htslib::bam::flags::{Flag, check_flag}; + //! let read_flag = 65; + //! assert_eq!(check_flag(read_flag, Flag::PAIRED + Flag::FIRST_IN_PAIR, 0), true); //! ``` //! let test that the read is mapped. READ_UNMAPPED //! ``` - //! use rust_htslib::bam::{Flag, check_flag}; - //! let read_flag = 18 + //! use rust_htslib::bam::flags::{Flag, check_flag}; + //! let read_flag = 18; //! assert_eq!(check_flag(read_flag, 0, Flag::READ_UNMAPPED), true); //! ``` //! //! Finally let do a more complexe real example test: //! ``` - //! use rust_htslib::bam::{Flag, check_flag}; - //! let read_flag = 19 + //! use rust_htslib::bam::flags::{Flag, check_flag}; + //! let read_flag = 19; //! assert_eq!(check_flag(read_flag, Flag::PAIRED + Flag::PROPERLY_PAIRED + Flag::READ_RERVERSE , Flag::READ_UNMAPPED + Flag::MATE_UNMAPPED), true); //! ``` //! From 01383b52786cc20bd59a79add03f96179b8f731b Mon Sep 17 00:00:00 2001 From: rLannes Date: Wed, 13 Nov 2024 15:11:42 -0500 Subject: [PATCH 5/7] typo --- src/bam/flags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bam/flags.rs b/src/bam/flags.rs index cc1909a92..cad423e12 100644 --- a/src/bam/flags.rs +++ b/src/bam/flags.rs @@ -5,7 +5,7 @@ //! For example, the following code tests if the read flag has the FIRST_IN_PAIR flag set and the MATE_UNMAPPED flag not set: //! ``` //! use rust_htslib::bam::flags{Flag, check_flag}; -//! # let read_flag = record.flag(); in general this is the way to obtian a flag. +//! let read_flag = record.flag(); // in general this is the way to obtain a flag. //! let read_flag = 64; //! assert_eq!(check_flag(read_flag, Flag::FIRST_IN_PAIR, Flag::MATE_UNMAPPED), true); //! ``` From 30dfef409f88f96b1b596bded514e2828ec88102 Mon Sep 17 00:00:00 2001 From: rLannes Date: Wed, 13 Nov 2024 18:40:55 -0500 Subject: [PATCH 6/7] re-ran cargo fmt --- src/bam/flags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bam/flags.rs b/src/bam/flags.rs index cad423e12..ed2d8d8fc 100644 --- a/src/bam/flags.rs +++ b/src/bam/flags.rs @@ -13,7 +13,7 @@ /// /// This structure contains constants representing SAM flag values as u16. /// Using this structure incurs no runtime cost. -/// +/// /// ``` /// use rust_htslib::bam::flags::Flag; /// // to get the value of a flag representing a read paired, and reversly mapped. From bfb2db10aa66beb494eb5993608282b1d83e9d98 Mon Sep 17 00:00:00 2001 From: rLannes Date: Wed, 18 Dec 2024 14:14:50 -0500 Subject: [PATCH 7/7] added 2 function is_in_flag() and is_not_in_flag() // updated the docstring --- src/bam/flags.rs | 58 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/bam/flags.rs b/src/bam/flags.rs index ed2d8d8fc..bacd01b09 100644 --- a/src/bam/flags.rs +++ b/src/bam/flags.rs @@ -1,15 +1,14 @@ //! A module that provides an easier way to work with SAM flags. //! It achieves this by providing a struct (`Flag`) with associated constants representing -//! flags, and the `check_flag()` function that allows testing if specific flags are set or not set. +//! flags. And the `is_in_flag()` and `is_not_in_flag()` functions that allow testing if specific flags are set or not set. //! -//! For example, the following code tests if the read flag has the FIRST_IN_PAIR flag set and the MATE_UNMAPPED flag not set: //! ``` -//! use rust_htslib::bam::flags{Flag, check_flag}; +//! use rust_htslib::bam::flags{Flag, is_in_flag, is_not_in_flag}; //! let read_flag = record.flag(); // in general this is the way to obtain a flag. //! let read_flag = 64; -//! assert_eq!(check_flag(read_flag, Flag::FIRST_IN_PAIR, Flag::MATE_UNMAPPED), true); +//! assert_eq!(is_in_flag(read_flag, Flag::FIRST_IN_PAIR), true); +//! assert_eq!(is_not_in_flag(read_flag, Flag::MATE_UNMAPPED), true); //! ``` - /// /// This structure contains constants representing SAM flag values as u16. /// Using this structure incurs no runtime cost. @@ -37,6 +36,54 @@ impl Flag { pub const SUPPLEMENTARY: u16 = 2048; } +pub fn is_not_in_flag(flag: u16, not_in: u16) -> bool { + //! This function uses bitwise operations to test if flags are not set + //! # Arguments + //! * `flag`: u16 - The record flag you want to test + //! * `not_in`: u16 - The flags you want to check if they are not set (use 0 for no test) + //! + //! # Usage: + //! example: let test if a flag is primary alignment and did not fail QC + //! ``` + //! use rust_htslib::bam::flags; + //! use rust_htslib::bam::flags::Flag; + //! let read_flag = 65; + //! assert_eq!(flags::is_not_in_flag(read_flag, Flag::NOT_PRIMARY_ALN + Flag::FAIL_QC), true); + //! ``` + //! let test that the read is mapped. + //! ``` + //! + //! use rust_htslib::bam::flags::{Flag, is_not_in_flag}; + //! let read_flag = 18; + //! assert_eq!(is_not_in_flag(read_flag, Flag::READ_UNMAPPED), true); + //! ``` + //! + if (not_in & flag) != 0 { + return false; + } + true +} +pub fn is_in_flag(flag: u16, in_: u16) -> bool { + //! This function uses bitwise operations to test if flags are set + //! # Arguments + //! * `flag`: u16 - The record flag you want to test + //! * `in_`: u16 - The flags you want to check if they are set (use 0 for no test) + //! + //! # Usage: + //! example: let test if a flag is both paired and first in pair + //! ``` + //! use rust_htslib::bam::flags::{Flag, is_in_flag}; + //! let read_flag = 65; + //! assert_eq!(is_in_flag(read_flag, Flag::PAIRED + Flag::FIRST_IN_PAIR), true); + //! ``` + + if (in_ & flag) != in_ { + return false; + } + true +} + +/* Deprecated pub fn check_flag(flag: u16, in_: u16, not_in: u16) -> bool { //! This function uses bitwise operations to test if flags are set or not. //! @@ -79,3 +126,4 @@ pub fn check_flag(flag: u16, in_: u16, not_in: u16) -> bool { } return true; } +*/