extern crate getopts;
extern crate fasten;
extern crate regex;
extern crate threadpool;
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use regex::Regex;
use threadpool::ThreadPool;
use std::sync::mpsc::channel;
use fasten::fasten_base_options;
use fasten::fasten_base_options_matches;
fn main(){
let mut opts = fasten_base_options();
opts.optopt("r","regex","Regular expression (default: '.')","STRING");
opts.optopt("w","which","Which field to match on? ID, SEQ, QUAL. Default: SEQ","String");
let matches = fasten_base_options_matches("Filter reads based on a regular expression.", opts);
let (tx, rx):(std::sync::mpsc::Sender<String>,std::sync::mpsc::Receiver<String>) = channel();
let my_file = File::open("/dev/stdin").expect("Could not open file");
let my_buffer=BufReader::new(my_file);
let is_paired_end=matches.opt_present("paired-end");
let which_field:String={
if matches.opt_present("which") {
matches.opt_str("which").expect("ERROR parsing --which")
.to_uppercase()
} else {
"SEQ".to_string()
}
};
let num_cpus:usize = {
if matches.opt_present("numcpus") {
matches.opt_str("numcpus").expect("ERROR parsing --numcpus")
.parse()
.expect("ERROR: numcpus is not an integer")
} else {
1
}
};
let regex_param={
if matches.opt_present("regex") {
matches.opt_str("regex")
.expect("ERROR: could not parse regex parameter")
} else {
String::from(".")
}
};
let _regex = Regex::new(®ex_param)
.expect("malformed seq regex given by --regex");
if matches.opt_present("verbose") {
eprintln!("Regular expression: {}",regex_param);
}
let pool = ThreadPool::new(num_cpus);
let mut buffer_iter = my_buffer.lines();
while let Some(line) = buffer_iter.next() {
let id = line.expect("ERROR reading the ID line");
let seq = buffer_iter.next().expect("ERROR reading a sequence line")
.expect("ERROR reading a sequence line");
buffer_iter.next().expect("ERROR reading a plus line")
.expect("ERROR reading the plus line");
let qual= buffer_iter.next().expect("ERROR reading a qual line")
.expect("ERROR reading a qual line");
let mut all_id =id.clone();
let mut all_seq =seq.clone();
let mut all_qual =qual.clone();
let mut id2 =String::new();
let mut seq2 =String::new();
let mut qual2 =String::new();
if is_paired_end {
id2 = buffer_iter.next().expect("ERROR reading the ID line")
.expect("ERROR reading the ID line");
seq2 = buffer_iter.next().expect("ERROR reading a sequence line")
.expect("ERROR reading a sequence line");
buffer_iter.next().expect("ERROR reading a plus line")
.expect("ERROR reading the plus line");
qual2= buffer_iter.next().expect("ERROR reading a qual line")
.expect("ERROR reading a qual line");
all_id.push_str(&id2);
all_seq.push_str(&seq2);
all_qual.push_str(&qual2);
}
let the_field = String::from(&which_field);
let regex_param2 = regex_param.clone();
let tx2 = tx.clone();
pool.execute(move|| {
let regex = Regex::new(®ex_param2)
.expect("malformed seq regex within thread, given by --regex");
let should_print:bool = match the_field.as_str(){
"SEQ" => {
regex.is_match(&all_seq)
},
"ID" => {
regex.is_match(&all_id)
},
"QUAL" => {
regex.is_match(&all_qual)
},
_ => {
panic!("{} is not a valid key to match on", &the_field);
}
};
if should_print {
if is_paired_end {
tx2.send(format!("{}\n{}\n+\n{}\n{}\n{}\n+\n{}",
id, seq, qual,
id2,seq2,qual2
)).unwrap();
} else {
tx2.send(format!("{}\n{}\n+\n{}",
id, seq, qual
)).unwrap();
}
}
});
}
pool.join();
drop(tx); let receiver = rx.iter();
for entry in receiver {
println!("{}",entry);
}
}