extern crate clap;
extern crate env_logger;
extern crate exitcode;
extern crate log;
use clap::{App, Arg, value_t, values_t};
use log::{error, info};
use std::collections::BTreeMap;
use std::fs::File;
use fastleng::fastx_loader::gather_multifastx_stats;
use fastleng::length_stats::{compute_length_stats, LengthStats};
const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");
fn main() {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
let matches = App::new("fastleng")
.version(VERSION.unwrap_or("?"))
.author("J. Matthew Holt <mholt@pacificbiosciences.com>")
.about("fastleng - a sequence length statistics generator for fastx/uBAM files")
.arg(
Arg::with_name("out_json")
.short("o")
.long("--out-json")
.takes_value(true)
.help("The output statistics json (default: stdout)")
)
.arg(
Arg::with_name("length_json")
.short("l")
.long("--length-json")
.takes_value(true)
.help("Saves the length counts to a specified json")
)
.arg(
Arg::with_name("FASTX")
.help("The FASTQ/A or uBAM file(s) to gather stats on, gzip accepted")
.required(true)
.multiple(true)
.index(1)
)
.get_matches();
let fastx_fns: Vec<String> = values_t!(matches.values_of("FASTX"), String).unwrap_or_else(|_| vec![]);
let out_fn: String = value_t!(matches.value_of("out_json"), String).unwrap_or_else(|_| "stdout".to_string());
let length_fn: String = value_t!(matches.value_of("length_json"), String).unwrap_or_else(|_| "".to_string());
info!("Input parameters (required):");
info!("\tFASTX: {:?}", fastx_fns);
info!("Optional Parameters:");
info!("\tout_json: {:?}", out_fn);
info!("\tlength_json: {:?}", length_fn);
for fastx_fn in fastx_fns.iter() {
match File::open(fastx_fn) {
Ok(_) => {}
Err(e) => {
error!("Failed to open file: {:?}", fastx_fn);
error!("Error: {:?}", e);
std::process::exit(exitcode::NOINPUT);
}
};
}
if out_fn != "stdout" {
match File::create(&out_fn) {
Ok(file) => file,
Err(e) => {
error!("Failed to create output JSON file: {:?}", out_fn);
error!("Error: {:?}", e);
std::process::exit(exitcode::CANTCREAT);
}
};
}
if !length_fn.is_empty() {
match File::create(&length_fn) {
Ok(file) => file,
Err(e) => {
error!("Failed to create output JSON file: {:?}", length_fn);
error!("Error: {:?}", e);
std::process::exit(exitcode::CANTCREAT);
}
};
}
let length_counts: BTreeMap<usize, u64> = match gather_multifastx_stats(&fastx_fns) {
Ok(result) => result,
Err(e) => {
error!("Error while parsing input files: {:?}", fastx_fns);
error!("Error: {:?}", e);
std::process::exit(exitcode::IOERR);
}
};
let length_metrics: LengthStats = compute_length_stats(&length_counts);
let json_format: String = serde_json::to_string(&length_metrics).unwrap();
info!("Length metrics: {}", json_format);
if out_fn == "stdout" {
let pretty_json: String = serde_json::to_string_pretty(&length_metrics).unwrap();
println!("{pretty_json}");
}
else {
info!("Saving results to file: {:?}", out_fn);
let out_file = match File::create(&out_fn) {
Ok(file) => file,
Err(e) => {
error!("Failed to create output JSON file: {:?}", out_fn);
error!("Error: {:?}", e);
std::process::exit(exitcode::CANTCREAT);
}
};
serde_json::to_writer_pretty(out_file, &length_metrics).unwrap();
}
if !length_fn.is_empty() {
info!("Saving length counts to file: {:?}", length_fn);
let out_file = match File::create(&length_fn) {
Ok(file) => file,
Err(e) => {
error!("Failed to create output JSON file: {:?}", length_fn);
error!("Error: {:?}", e);
std::process::exit(exitcode::CANTCREAT);
}
};
serde_json::to_writer_pretty(out_file, &length_counts).unwrap();
}
info!("Processes successfully finished.")
}