blobtk 0.8.1

Core utilities for BlobToolKit.
Documentation
use std::collections::HashSet;
use std::io::Write;
use std::path::PathBuf;

extern crate needletail;
use needletail::parser::{write_fasta, LineEnding};
use needletail::FastxReader;

use crate::fastq::{open_fastx, suffix_file_name};
use crate::io::get_writer;
use crate::utils::styled_progress_bar;

fn trim_seq_id(input: &[u8]) -> Vec<u8> {
    input
        .iter()
        .copied()
        .by_ref()
        .take_while(|&x| x != b' ')
        .collect()
}

fn subsample_fasta<F: Fn()>(
    seq_names: &HashSet<Vec<u8>>,
    mut reader: Box<dyn FastxReader>,
    writer: &mut dyn Write,
    callback: &Option<F>,
) {
    let total = seq_names.len();
    let progress_bar = styled_progress_bar(total, "Subsampling FASTA");

    while let Some(record) = reader.next() {
        let seqrec = record.as_ref().expect("invalid record");
        let seq_id: Vec<u8> = trim_seq_id(seqrec.id());
        if seq_names.contains(&seq_id) {
            write_fasta(seqrec.id(), &seqrec.seq(), writer, LineEnding::Unix)
                .expect("Unable to write FASTA");
            progress_bar.inc(1);
            if progress_bar.position() as usize == total {
                break;
            }
        }

        if let Some(cb) = callback {
            cb()
        }
    }
    progress_bar.finish();
}

pub fn subsample<F: Fn()>(
    seq_names: &HashSet<Vec<u8>>,
    fasta_path: &Option<PathBuf>,
    fasta_out: &bool,
    suffix: &String,
    callback: &Option<F>,
) {
    if fasta_path.is_none() {
        return;
    }
    if !fasta_out {
        return;
    }

    let reader = open_fastx(fasta_path);
    let out_path = suffix_file_name(fasta_path.as_ref().unwrap(), suffix);
    let mut writer = get_writer(&Some(out_path));

    if let Some(r) = reader {
        subsample_fasta(seq_names, r, &mut *writer, callback);
    }
}