extern crate fasten;
extern crate getopts;
extern crate rand;
use std::io::BufReader;
use std::io::BufRead;
use std::io::stdin;
use std::io::Stdin;
use std::cmp::min;
use rand::prelude::*;
use fasten::fasten_base_options;
use fasten::fasten_base_options_matches;
const READ_SEPARATOR :char = '~';
fn main(){
let mut opts = fasten_base_options();
opts.optopt("t", "target-depth", "The target depth of kmer.", "INT");
let matches = fasten_base_options_matches("Normalizes reads based on kmer coverage.", opts);
let target_depth :u32 = matches.opt_str("target-depth")
.expect("need --target-depth")
.parse()
.expect("Convert target-depth to integer");
let stdin = stdin();
let paired_end = matches.opt_present("paired-end");
normalize_coverage(stdin, target_depth, paired_end);
}
fn normalize_coverage (stdin:Stdin, target_depth:u32, paired_end:bool) {
let mut rng = rand::thread_rng();
let my_buffer=BufReader::new(stdin);
let mut buffer_iter = my_buffer.lines();
while let Some(line_opt) = buffer_iter.next() {
let line = line_opt.expect("read the next line");
let mut f :Vec<&str> = line.split("\t").collect();
if f.len() < 3 {
continue;
}
let kmer_count :Vec<&str> = f.splice(0..2, vec![]).collect();
let _count :u32 = kmer_count[1].parse().unwrap();
let num_reads_orig :usize = f.len();
let mut num_reads_to_keep :usize = min(
target_depth,
num_reads_orig as u32
) as usize;
if paired_end {
num_reads_to_keep = (num_reads_to_keep as f32 / 2.0).ceil() as usize;
}
f.shuffle(&mut rng);
let reads_to_keep :Vec<&str> = f.splice(0..num_reads_to_keep, vec![]).collect();
print_reads(reads_to_keep);
}
}
fn print_reads (reads:Vec<&str>) {
for entry in reads{
let entry_string = entry.replace(READ_SEPARATOR, "\n");
println!("{}", entry_string);
}
}