prll-ri 1.0.6

Parallel-RI, parallel executable binary to wrap RIblast.
Documentation
#![feature(test)]

extern crate getopts;
extern crate bio;
extern crate time;
extern crate test;
extern crate prll_ri;

use getopts::Options;
use std::process::Command;
use std::path::Path;
use bio::io::fasta;
use time::now;
use prll_ri::*;

pub fn rn_riblast_in_srl(args: &Vec<String>) {
  let prgrm = args[0].clone();
  let mut opts = Options::new();
  opts.reqopt("i", "", "RNA seqs in single file of FASTA format", "STR");
  opts.reqopt("o", "", "Path to output dir.", "STR");
  opts.reqopt("d", "", "Path to database", "STR");
  opts.optopt("l", "", "Max size of seed length (Default: 20)", "UINT");
  opts.optopt("e", "", "Interaction energy threshold for seed search (Default: -6.5)", "FLOAT");
  opts.optopt("f", "", "Hybridization energy threshold for removal of interaction candidates before gapped extension (Default: -3.05)", "FLOAT");
  opts.optopt("x", "", "Dropout length in gapped extension (Default: 18)", "UINT");
  opts.optopt("y", "", "Dropout length in gapless extension (Default: 5)", "UINT");
  opts.optopt("t", "", "# of threads in multithreading (Default: system val.)", "UINT");
  opts.optopt("b", "", "Path to RIblast binary (Default: system val.)", "STR");
  opts.optflag("h", "help", "Print help menu");
  let mtchs = match opts.parse(&args[1 ..]) {
    Ok(mtch) => {mtch}
    Err(fl) => {prnt_usg(&prgrm, &opts); panic!(fl.to_string())}
  };
  if mtchs.opt_present("h") {
    prnt_usg(&prgrm, &opts);
    return;
  }
  let riblast_pth = if mtchs.opt_present("b") {
    mtchs.opt_str("b").expect("Retrieving path to RIblast from command args failed. ")
  } else {
    String::from("RIblast")
  };
  let tm_stmp = now();
  let tm_stmp = (tm_stmp.tm_year + 1900).to_string() + "-" + &(tm_stmp.tm_mon + 1).to_string() + "-" + &tm_stmp.tm_mday.to_string() + "-" + &tm_stmp.tm_hour.to_string() + ":" + &tm_stmp.tm_min.to_string() + ":" + &tm_stmp.tm_sec.to_string();
  let tmp = String::from("/tmp/prll_ri_") + &tm_stmp;
  let tmp = Path::new(&tmp);
  if !tmp.exists() {
    Command::new("mkdir").arg(tmp.to_str().expect("Parsing temporary dir. path failed. ")).output().expect("Creating temporary dir. failed. ");
  }
  let inpt = mtchs.opt_str("i").expect("Retrieving input file path from command args failed. ");
  let otpt_dr = mtchs.opt_str("o").expect("Retrieving output dir. path from command args failed. ");
  let otpt_dr = Path::new(&otpt_dr);
  if !otpt_dr.exists() {
    Command::new("mkdir").arg(otpt_dr.to_str().expect("Parsing output dir. path failed. ")).output().expect("Creating output dir. failed. ");
  }
  let mut args = Vec::new();
  let opts = vec!["d", "l", "e", "f", "x", "y"];
  let opt_dflt_vls = vec!["", "20", "-6.5", "-3.05", "18", "5"];
  for itr_pr in opts.iter().zip(opt_dflt_vls.iter()) {
    let (opt, opt_dflt_vl) = itr_pr;
    let mut arg = String::from("-");
    arg.push_str(opt);
    args.push(arg);
    if mtchs.opt_present(opt) {
      args.push(String::from(mtchs.opt_str(opt).expect("Retrieving option failed. ")));
    } else {
      args.push(String::from(*opt_dflt_vl));
    }
  }
  let fasta_rdr = fasta::Reader::from_file(Path::new(&inpt)).ok().expect("Reading FASTA file failed. ");
  for (_i, rc) in fasta_rdr.records().enumerate() {
    let dt = rc.ok().expect("Reading FASTA record failed. ");
    let dt_id = dt.id().expect("Record ID is missing. ");
    let tmp_otpt = tmp.join(String::from(dt_id) + ".fa");
    let otpt = otpt_dr.join(dt_id);
    let mut fasta_wrtr = fasta::Writer::to_file(Path::new(&tmp_otpt)).ok().expect("Writing into FASTA file is blocked. ");
    let _rslt = fasta_wrtr.write_record(&dt);
    let _rslt = fasta_wrtr.flush();
    let mut riblast_args = args.clone();
    riblast_args.insert(0, String::from("ris"));
    riblast_args.push(String::from("-i"));
    riblast_args.push(String::from(tmp_otpt.to_str().expect("Parsing temporary file path failed. ")));
    riblast_args.push(String::from("-o"));
    riblast_args.push(String::from(otpt.to_str().expect("Parsing output dir. path failed. ")));
    let mut riblast_arg_slcs = Vec::new();
    for riblast_arg in &riblast_args {
      riblast_arg_slcs.push(riblast_arg.as_str());
    }
    let otpt = Command::new(&riblast_pth).args(&riblast_arg_slcs).output().expect("RIblast failed. ");
    println!("Status: {}", otpt.status);
    println!("stdout: {}", String::from_utf8_lossy(&otpt.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&otpt.stderr));
    assert!(otpt.status.success());
  }
  Command::new("rm").args(&["-rf", tmp.to_str().expect("Parsing temporary dir. path failed. ")]).output().expect("Removing temporary dir. failed. ");
}

#[cfg(test)]
mod tsts {
  use super::*;
  use time::precise_time_ns;
  use prll_ri::rn_riblast_in_prll;

  #[test]
  fn tst_riblast_in_prll() {
    let mut args = Vec::new();
    args.push(String::from("prll-ri"));
    args.push(String::from("-i"));
    args.push(String::from("asts/fnc_ncrnas.fa"));
    args.push(String::from("-o"));
    args.push(String::from("asts/prll_ri"));
    args.push(String::from("-d"));
    args.push(String::from("asts/s_pmb_rna_db/s_pmb_rna_db"));
    let bgn = precise_time_ns();
    rn_riblast_in_prll(&args);
    let elps_tm = precise_time_ns() - bgn;
    let bgn = precise_time_ns();
    rn_riblast_in_srl(&args);
    let spd_rt = (precise_time_ns() - bgn) as f32 / elps_tm as f32;
    println!("{} times faster than serial form. ", spd_rt);
  }
}