use crate::error::ProcessingResult;
use crate::kmer::encoding::{decode_kmer, reverse_complement_u128};
use crate::kmer::operations::reverse_complement_bits;
pub fn canonical_kmer(kmer_encoded: u64, k: usize) -> ProcessingResult<u64> {
let rev_comp = reverse_complement_bits(kmer_encoded, k)?;
Ok(if kmer_encoded <= rev_comp {
kmer_encoded
} else {
rev_comp
})
}
pub fn is_canonical(kmer_encoded: u64, k: usize) -> ProcessingResult<bool> {
let rev_comp = reverse_complement_bits(kmer_encoded, k)?;
Ok(kmer_encoded <= rev_comp)
}
pub fn get_both_orientations(kmer_encoded: u64, k: usize) -> ProcessingResult<(String, String)> {
let forward = decode_kmer(kmer_encoded, k);
let rev_comp_bits = reverse_complement_bits(kmer_encoded, k)?;
let rev_comp = decode_kmer(rev_comp_bits, k);
Ok((forward, rev_comp))
}
pub fn canonical_kmer_u128(kmer_encoded: u128, k: usize) -> ProcessingResult<u128> {
let rev_comp = reverse_complement_u128(kmer_encoded, k);
Ok(if kmer_encoded <= rev_comp {
kmer_encoded
} else {
rev_comp
})
}
pub fn is_canonical_u128(kmer_encoded: u128, k: usize) -> ProcessingResult<bool> {
let rev_comp = reverse_complement_u128(kmer_encoded, k);
Ok(kmer_encoded <= rev_comp)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::kmer::encoding::{encode_kmer, encode_kmer_u128};
#[test]
fn test_canonical_kmer() {
let atgc_encoded = encode_kmer("ATGC").unwrap();
let canonical = canonical_kmer(atgc_encoded, 4).unwrap();
assert_eq!(canonical, atgc_encoded);
}
#[test]
fn test_palindrome_kmer() {
let atat_encoded = encode_kmer("ATAT").unwrap();
let canonical = canonical_kmer(atat_encoded, 4).unwrap();
assert_eq!(canonical, atat_encoded);
}
#[test]
fn test_is_canonical() {
let atgc_encoded = encode_kmer("ATGC").unwrap();
assert!(is_canonical(atgc_encoded, 4).unwrap());
let gcat_encoded = encode_kmer("GCAT").unwrap();
assert!(!is_canonical(gcat_encoded, 4).unwrap());
}
#[test]
fn test_get_both_orientations() {
let atgc_encoded = encode_kmer("ATGC").unwrap();
let (forward, rev_comp) = get_both_orientations(atgc_encoded, 4).unwrap();
assert_eq!(forward, "ATGC");
assert_eq!(rev_comp, "GCAT");
}
#[test]
fn test_canonical_kmer_u128_reverse_complement() {
let seq1 = "GAAAAAAAAAAAA";
let seq2 = "TTTTTTTTTTTTC";
let encoded1 = encode_kmer_u128(seq1).unwrap();
let encoded2 = encode_kmer_u128(seq2).unwrap();
let canonical1 = canonical_kmer_u128(encoded1, seq1.len()).unwrap();
let canonical2 = canonical_kmer_u128(encoded2, seq2.len()).unwrap();
assert_eq!(canonical1, canonical2);
}
}