use std::hash::BuildHasherDefault;
use std::ops::Range;
use crate::base::{kmer::*, kmergenerator::*};
use crate::hashed::*;
#[allow(unused_imports)]
use crate::sketching::minhash::{minhash_distance, MinHashCount, MinHashDist};
use probminhash::invhash;
use probminhash::superminhasher::*;
use log::info;
use log::trace;
pub fn sketch_seqrange_superminhash(
seq: &Sequence,
range: &Range<usize>,
kmer_size: usize,
sketch_size: usize,
) -> Vec<f64> {
info!("seqsketcher : entering superminhash_sketch_sequence");
let bh = BuildHasherDefault::<NoHashHasher>::default();
let mut sminhash: SuperMinHash<f64, u32, NoHashHasher> = SuperMinHash::new(sketch_size, bh);
match kmer_size {
16 => {
let mut kmergen = KmerSeqIterator::<Kmer16b32bit>::new(16, seq);
kmergen.set_range(range.start, range.end).unwrap();
while let Some(kmer) = kmergen.next() {
let canonical = kmer.reverse_complement().min(kmer);
let hashval = invhash::int32_hash(canonical.0);
sminhash.sketch(&hashval).unwrap();
}
sminhash.get_hsketch().clone()
}
9..=15 => {
let mut kmergen = KmerSeqIterator::<Kmer32bit>::new(kmer_size as u8, seq);
kmergen.set_range(range.start, range.end).unwrap();
while let Some(kmer) = kmergen.next() {
let canonical = kmer.reverse_complement().min(kmer);
let hashval = invhash::int32_hash(canonical.0);
sminhash.sketch(&hashval).unwrap();
} info!("seqsketcher : got a superminhash_sketch");
sminhash.get_hsketch().clone()
}
_ => panic!(
"sketch_sequence_superminhash , unimplemented kmer_size {} {} {} ",
kmer_size,
file!(),
line!()
),
}
}
pub fn sketch_seqrange_minhash(
seq: &Sequence,
range: &Range<usize>,
kmer_size: usize,
sketch_size: usize,
) -> Vec<HashCount<u32>> {
trace!("seqsketcher : entering sketch_seqrange_minhash");
let mut minhash: MinHashCount<u32, NoHashHasher> = MinHashCount::new(sketch_size, true);
match kmer_size {
16 => {
let mut kmergen = KmerSeqIterator::<Kmer16b32bit>::new(16, seq);
if kmergen.set_range(range.start, range.end).is_err() {
println!(
"sketch_seqrange_minhash: bad range, start = {} , end = {}",
range.start, range.end
);
panic!("bad range");
}
while let Some(kmer) = kmergen.next() {
let canonical = kmer.reverse_complement().min(kmer);
let hashval = invhash::int32_hash(canonical.0);
minhash.push(&hashval);
} minhash.get_sketchcount()
}
9..=15 => {
let mut kmergen = KmerSeqIterator::<Kmer32bit>::new(kmer_size as u8, seq);
if kmergen.set_range(range.start, range.end).is_err() {
println!(
"sketch_seqrange_minhash: bad range, start = {} , end = {}",
range.start, range.end
);
panic!("bad range");
}
while let Some(kmer) = kmergen.next() {
let canonical = kmer.reverse_complement().min(kmer);
let hashval = invhash::int32_hash(canonical.0);
minhash.push(&hashval);
} minhash.get_sketchcount()
}
_ => panic!(
"sketch_sequence_minhash , unimplemented kmer_size {} {} {} ",
kmer_size,
file!(),
line!()
),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_minhash_overlapping_ranges_kmer16b() {
let seqstr = String::from(
"TCAAAGGGAAACATTCAAAATCAGTATGCGCCCGTTCAGTTACGTATTGCTCTCGCTAATGAGATGGGCTGGGTACAGAG",
);
let slu8 = seqstr.as_bytes();
let seq = Sequence::new(slu8, 2);
let range1: Range<usize> = Range { start: 1, end: 65 };
let kmer_size: usize = 16;
let sketch_size: usize = 20;
trace!(" sketching 1");
let sk1 = sketch_seqrange_minhash(&seq, &range1, kmer_size, sketch_size);
let range2: Range<usize> = Range { start: 35, end: 75 };
trace!("\n sketching 2");
let sk2 = sketch_seqrange_minhash(&seq, &range2, kmer_size, sketch_size);
let resdist: MinHashDist = minhash_distance(&sk1, &sk2);
println!(
"distance minhash (contain, dist, common, total): {} {} {} {} ",
resdist.0, resdist.1, resdist.2, resdist.3
);
assert!(resdist.3 >= 3);
}
#[test]
fn test_minhash_overlapping_ranges_kmer10b() {
let seqstr = String::from(
"TCAAAGGGAAACATTCAAAATCAGTATGCGCCCGTTCAGTTACGTATTGCTCTCGCTAATGAGATGGGCTGGGTACAGAG",
);
let slu8 = seqstr.as_bytes();
let seq = Sequence::new(slu8, 2);
let range1: Range<usize> = Range { start: 1, end: 65 };
let kmer_size: usize = 10;
let sketch_size: usize = 20;
trace!(" sketching 1");
let sk1 = sketch_seqrange_minhash(&seq, &range1, kmer_size, sketch_size);
let range2: Range<usize> = Range { start: 35, end: 75 };
trace!("\n sketching 2");
let sk2 = sketch_seqrange_minhash(&seq, &range2, kmer_size, sketch_size);
let resdist: MinHashDist = minhash_distance(&sk1, &sk2);
println!(
"distance super minhash (contain, dist, common, total): {} {} {} {} ",
resdist.0, resdist.1, resdist.2, resdist.3
);
assert!(resdist.3 == 20);
}
#[test]
fn test_superminhash_overlapping_ranges_kmer16b() {
let seqstr = String::from(
"TCAAAGGGAAACATTCAAAATCAGTATGCGCCCGTTCAGTTACGTATTGCTCTCGCTAATGAGATGGGCTGGGTACAGAG",
);
let slu8 = seqstr.as_bytes();
let seq = Sequence::new(slu8, 2);
let range1: Range<usize> = Range { start: 1, end: 65 };
let kmer_size: usize = 16;
let sketch_size: usize = 50;
trace!(" sketching 1");
let sk1 = sketch_seqrange_superminhash(&seq, &range1, kmer_size, sketch_size);
let range2: Range<usize> = Range { start: 35, end: 75 };
trace!("\n sketching 2");
let sk2 = sketch_seqrange_superminhash(&seq, &range2, kmer_size, sketch_size);
let resdist = get_jaccard_index_estimate(&sk1, &sk2).unwrap();
println!(
"distance super minhash (contain, dist, common, total): {} ",
resdist
);
assert!(resdist >= 0.15);
}
#[test]
fn test_superminhash_overlapping_ranges_kmer10b() {
let seqstr = String::from(
"TCAAAGGGAAACATTCAAAATCAGTATGCGCCCGTTCAGTTACGTATTGCTCTCGCTAATGAGATGGGCTGGGTACAGAG",
);
let slu8 = seqstr.as_bytes();
let seq = Sequence::new(slu8, 2);
let range1: Range<usize> = Range { start: 1, end: 65 };
let kmer_size: usize = 10;
let sketch_size: usize = 20;
trace!(" sketching 1");
let sk1 = sketch_seqrange_superminhash(&seq, &range1, kmer_size, sketch_size);
let range2: Range<usize> = Range { start: 35, end: 75 };
trace!("\n sketching 2");
let sk2 = sketch_seqrange_superminhash(&seq, &range2, kmer_size, sketch_size);
let resdist = get_jaccard_index_estimate(&sk1, &sk2).unwrap();
println!("distance super minhash : {} ", resdist);
assert!(resdist >= 0.2);
} }