use clap::*;
use intspan::*;
pub fn make_subcommand() -> Command {
Command::new("check")
.about("Check genome locations in block fasta headers")
.after_help(
r###"
* <genome.fa> is a multi-fasta file contains genome sequences
* <infiles> are paths to block fasta files, .fas.gz is supported
* infile == stdin means reading from STDIN
* Need `samtools` in $PATH
"###,
)
.arg(
Arg::new("genome.fa")
.required(true)
.num_args(1)
.index(1)
.help("Path to genome.fa"),
)
.arg(
Arg::new("infiles")
.required(true)
.num_args(1..)
.index(2)
.help("Sets the input files to use"),
)
.arg(
Arg::new("name")
.long("name")
.num_args(1)
.help("Which species to be checked, omit this will check all sequences"),
)
.arg(
Arg::new("outfile")
.long("outfile")
.short('o')
.num_args(1)
.default_value("stdout")
.help("Output filename. [stdout] for screen"),
)
}
pub fn execute(args: &ArgMatches) -> anyhow::Result<()> {
let mut writer = writer(args.get_one::<String>("outfile").unwrap());
let genome = args.get_one::<String>("genome.fa").unwrap();
for infile in args.get_many::<String>("infiles").unwrap() {
let mut reader = reader(infile);
while let Ok(block) = next_fas_block(&mut reader) {
let block_names = block.names;
if args.contains_id("name") {
let name = args.get_one::<String>("name").unwrap();
if block_names.contains(name) {
for entry in &block.entries {
let entry_name = entry.range().name();
if entry_name == name {
let status = check_seq(entry, genome)?;
writer
.write_all(format!("{}\t{}\n", entry.range(), status).as_ref())?;
}
}
}
} else {
for entry in &block.entries {
let status = check_seq(entry, genome)?;
writer.write_all(format!("{}\t{}\n", entry.range(), status).as_ref())?;
}
}
}
}
Ok(())
}
fn check_seq(entry: &FasEntry, genome: &str) -> anyhow::Result<String> {
let range = entry.range();
let seq = if range.strand() == "-" {
bio::alphabets::dna::revcomp(entry.seq())
} else {
entry.seq().to_vec()
};
let seq = std::str::from_utf8(&seq)
.unwrap()
.to_string()
.to_ascii_uppercase();
let pos = format!("{}:{}-{}", range.chr(), range.start(), range.end());
let gseq = get_seq_faidx(genome, &pos)?.to_ascii_uppercase();
let status = if seq == gseq { "OK" } else { "FAILED" };
Ok(status.to_string())
}