Skip to content

Commit

Permalink
more movement to anyhow
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob Patro committed May 8, 2022
1 parent c3b7752 commit 912ca01
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 35 deletions.
6 changes: 4 additions & 2 deletions src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

use crate::cellfilter::permit_list_from_file;
use anyhow::anyhow;
use crossbeam_queue::ArrayQueue;
use indicatif::{ProgressBar, ProgressStyle};
#[allow(unused_imports)]
Expand Down Expand Up @@ -38,7 +39,8 @@ pub fn infer(
filter_list: Option<&str>,
output_dir: String,
log: &slog::Logger,
) -> Result<(), Box<dyn std::error::Error>> {
) -> anyhow::Result<()> {
// Box<dyn std::error::Error>> {
info!(
log,
"inferring abundances from equivalence class count input."
Expand All @@ -56,7 +58,7 @@ pub fn infer(
Ok(t) => t.to_csr(),
Err(e) => {
warn!(log, "error reading mtx file{:?}", e);
return Err(Box::new(e));
return Err(anyhow!("error reading mtx format matrix : {}", e));
}
};

Expand Down
13 changes: 7 additions & 6 deletions src/io_utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/// some (hopefully) generally useful I/O related utilities
use anyhow::Context;
use crossbeam_queue::ArrayQueue;
use indicatif::ProgressBar;
use scroll::Pwrite;
Expand All @@ -15,7 +16,7 @@ pub(crate) fn fill_work_queue<T: Read>(
mut br: T,
num_chunks: usize,
pbar: &ProgressBar,
) -> Result<(), Box<dyn std::error::Error>> {
) -> anyhow::Result<()> {
const BUFSIZE: usize = 524208;
// the buffer that will hold our records
let mut buf = vec![0u8; BUFSIZE];
Expand Down Expand Up @@ -58,7 +59,7 @@ pub(crate) fn fill_work_queue<T: Read>(
buf.pwrite::<u32>(nbytes_chunk, boffset)?;
buf.pwrite::<u32>(nrec_chunk, boffset + 4)?;
br.read_exact(&mut buf[(boffset + 8)..(boffset + nbytes_chunk as usize)])
.unwrap();
.context("failed to read from work queue.")?;
cells_in_chunk += 1;
cbytes += nbytes_chunk;
crec += nrec_chunk;
Expand Down Expand Up @@ -113,11 +114,11 @@ pub(crate) fn fill_work_queue_filtered<T: Read>(
mut br: T,
num_chunks: usize,
pbar: &ProgressBar,
) -> Result<(), Box<dyn std::error::Error>> {
) -> anyhow::Result<()> {
let bct = rl_tags.tags[0].typeid;
let umit = rl_tags.tags[1].typeid;
let bc_type = rad_types::decode_int_type_tag(bct).expect("unsupported barcode type id.");
let umi_type = rad_types::decode_int_type_tag(umit).expect("unsupported umi type id.");
let bc_type = rad_types::decode_int_type_tag(bct).context("unsupported barcode type id.")?;
let umi_type = rad_types::decode_int_type_tag(umit).context("unsupported umi type id.")?;

const BUFSIZE: usize = 524208;
// the buffer that will hold our records
Expand Down Expand Up @@ -161,7 +162,7 @@ pub(crate) fn fill_work_queue_filtered<T: Read>(
buf.pwrite::<u32>(nbytes_chunk, boffset)?;
buf.pwrite::<u32>(nrec_chunk, boffset + 4)?;
br.read_exact(&mut buf[(boffset + 8)..(boffset + nbytes_chunk as usize)])
.unwrap();
.context("failed to read from queue.")?;
// get the barcode for this chunk
let (bc, _umi) =
rad_types::Chunk::peek_record(&buf[boffset + 8..], &bc_type, &umi_type);
Expand Down
38 changes: 21 additions & 17 deletions src/quant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause
*/

use anyhow::Context;
use crossbeam_queue::ArrayQueue;
use indicatif::{ProgressBar, ProgressStyle};

Expand Down Expand Up @@ -168,7 +169,7 @@ fn write_eqc_counts(
usa_mode: bool,
output_path: &std::path::Path,
log: &slog::Logger,
) -> bool {
) -> anyhow::Result<bool> {
let eqmap_deref = eqid_map_lock.lock();
let geqmap = eqmap_deref.unwrap();
let num_eqclasses = geqmap.global_eqc.len();
Expand Down Expand Up @@ -197,7 +198,7 @@ fn write_eqc_counts(

// and write it to file.
let mtx_path = output_path.join("geqc_counts.mtx");
sprs::io::write_matrix_market(&mtx_path, &eqmat).expect("could not write geqc_counts.mtx");
sprs::io::write_matrix_market(&mtx_path, &eqmat).context("could not write geqc_counts.mtx")?;

// write the sets of genes that define each eqc
let gn_eq_path = output_path.join("gene_eqclass.txt.gz");
Expand All @@ -209,12 +210,12 @@ fn write_eqc_counts(
// number of genes
gn_eq_writer
.write_all(format!("{}\n", num_genes).as_bytes())
.expect("could not write to gene_eqclass.txt.gz");
.context("could not write to gene_eqclass.txt.gz")?;

// number of classes
gn_eq_writer
.write_all(format!("{}\n", num_eqclasses).as_bytes())
.expect("could not write to gene_eqclass.txt.gz");
.context("could not write to gene_eqclass.txt.gz")?;

// each line describes a class in terms of
// the tab-separated tokens
Expand Down Expand Up @@ -267,11 +268,11 @@ fn write_eqc_counts(
}
gn_eq_writer
.write_all(format!("{}\t", gl).as_bytes())
.expect("could not write to gene_eqclass.txt.gz")
.context("could not write to gene_eqclass.txt.gz")?;
}
gn_eq_writer
.write_all(format!("{}\n", eqid).as_bytes())
.expect("could not write to gene_eqclass.txt.gz");
.context("could not write to gene_eqclass.txt.gz")?;
}
} else {
// if we are running the *standard* mode, then the gene_id
Expand All @@ -280,14 +281,14 @@ fn write_eqc_counts(
for g in gene_list.iter() {
gn_eq_writer
.write_all(format!("{}\t", g).as_bytes())
.expect("could not write to gene_eqclass.txt.gz");
.context("could not write to gene_eqclass.txt.gz")?;
}
gn_eq_writer
.write_all(format!("{}\n", eqid).as_bytes())
.expect("could not write to gene_eqclass.txt.gz");
.context("could not write to gene_eqclass.txt.gz")?;
}
}
true
Ok(true)
}

// TODO: see if we'd rather pass an structure
Expand All @@ -310,20 +311,22 @@ pub fn quantify(
cmdline: &str,
version: &str,
log: &slog::Logger,
) -> Result<(), Box<dyn std::error::Error>> {
) -> anyhow::Result<()> {
let parent = std::path::Path::new(&input_dir);

// read the collate metadata
let collate_md_file =
File::open(parent.join("collate.json")).expect("could not open the collate.json file.");
File::open(parent.join("collate.json")).context("could not open the collate.json file.")?;
let collate_md: serde_json::Value = serde_json::from_reader(&collate_md_file)?;

// is the collated RAD file compressed?
let compressed_input = collate_md["compressed_output"].as_bool().unwrap();
let compressed_input = collate_md["compressed_output"]
.as_bool()
.context("could not read compressed_output field from collate metadata.")?;

if compressed_input {
let i_file =
File::open(parent.join("map.collated.rad.sz")).expect("run collate before quant");
File::open(parent.join("map.collated.rad.sz")).context("run collate before quant")?;
let br = snap::read::FrameDecoder::new(BufReader::new(&i_file));

info!(
Expand Down Expand Up @@ -351,7 +354,8 @@ pub fn quantify(
log,
)
} else {
let i_file = File::open(parent.join("map.collated.rad")).expect("run collate before quant");
let i_file =
File::open(parent.join("map.collated.rad")).context("run collate before quant")?;
let br = BufReader::new(&i_file);

info!(
Expand Down Expand Up @@ -402,7 +406,7 @@ pub fn do_quantify<T: Read>(
cmdline: &str,
version: &str,
log: &slog::Logger,
) -> Result<(), Box<dyn std::error::Error>> {
) -> anyhow::Result<()> {
let parent = std::path::Path::new(&input_dir);
let hdr = rad_types::RadHeader::from_bytes(&mut br);

Expand Down Expand Up @@ -1264,7 +1268,7 @@ pub fn do_quantify<T: Read>(
with_unspliced,
&output_matrix_path,
log,
);
)?;
}

let meta_info = json!({
Expand Down Expand Up @@ -1324,7 +1328,7 @@ pub fn velo_quantify(
_cmdline: &str,
_version: &str,
_log: &slog::Logger,
) -> Result<(), Box<dyn std::error::Error>> {
) -> anyhow::Result<()> {
unimplemented!("not implemented on this branch yet");
//Ok(())
}
28 changes: 18 additions & 10 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::constants as afconst;
use crate::eq_class::IndexedEqList;
use anyhow::{anyhow, Context};
use bstr::io::BufReadExt;
use core::fmt;
use libradicl::utils::SPLICE_MASK_U32;
Expand Down Expand Up @@ -111,7 +112,7 @@ fn parse_tg_spliced_unspliced(
rname_to_id: &HashMap<String, u32, ahash::RandomState>,
gene_names: &mut Vec<String>,
gene_name_to_id: &mut HashMap<String, u32, ahash::RandomState>,
) -> Result<(Vec<u32>, bool), Box<dyn std::error::Error>> {
) -> anyhow::Result<(Vec<u32>, bool)> {
// map each transcript id to the corresponding gene id
// the transcript name can be looked up from the id in the RAD header,
// and the gene name can be looked up from the id in the gene_names
Expand Down Expand Up @@ -159,7 +160,9 @@ fn parse_tg_spliced_unspliced(
// first gid of this gene
tid_to_gid[*transcript_id as usize] = spliced_of(gene_id);
} else {
return Err("Third column in 3 column txp-to-gene file must be S or U".into());
return Err(anyhow!(
"Third column in 3 column txp-to-gene file must be S or U"
));
}
}
}
Expand All @@ -178,7 +181,7 @@ fn parse_tg_spliced(
rname_to_id: &HashMap<String, u32, ahash::RandomState>,
gene_names: &mut Vec<String>,
gene_name_to_id: &mut HashMap<String, u32, ahash::RandomState>,
) -> Result<(Vec<u32>, bool), Box<dyn std::error::Error>> {
) -> anyhow::Result<(Vec<u32>, bool)> {
// map each transcript id to the corresponding gene id
// the transcript name can be looked up from the id in the RAD header,
// and the gene name can be looked up from the id in the gene_names
Expand Down Expand Up @@ -220,7 +223,10 @@ fn parse_tg_spliced(
e
);
*/
return Err(Box::new(e));
return Err(anyhow!(
"failed to parse the transcript-to-gene map : {}.",
e
));
}
}
}
Expand All @@ -239,8 +245,8 @@ pub fn parse_tg_map(
rname_to_id: &HashMap<String, u32, ahash::RandomState>,
gene_names: &mut Vec<String>,
gene_name_to_id: &mut HashMap<String, u32, ahash::RandomState>,
) -> Result<(Vec<u32>, bool), Box<dyn std::error::Error>> {
let t2g_file = std::fs::File::open(tg_map).expect("couldn't open file");
) -> anyhow::Result<(Vec<u32>, bool)> {
let t2g_file = std::fs::File::open(tg_map).context("couldn't open file")?;
let mut rdr = csv::ReaderBuilder::new()
.has_headers(false)
.delimiter(b'\t')
Expand Down Expand Up @@ -270,7 +276,9 @@ pub fn parse_tg_map(
}
_ => {
// not supported
Err("Transcript-gene mapping must have either 2 or 3 columns.".into())
Err(anyhow!(
"Transcript-gene mapping must have either 2 or 3 columns."
))
}
}
}
Expand Down Expand Up @@ -688,18 +696,18 @@ pub fn generate_permitlist_map(
pub fn read_filter_list(
flist: &str,
bclen: u16,
) -> Result<HashSet<u64, ahash::RandomState>, Box<dyn std::error::Error>> {
) -> anyhow::Result<HashSet<u64, ahash::RandomState>> {
let s = ahash::RandomState::with_seeds(2u64, 7u64, 1u64, 8u64);
let mut fset = HashSet::<u64, ahash::RandomState>::with_hasher(s);

let filt_file = std::fs::File::open(flist).expect("couldn't open file");
let filt_file = std::fs::File::open(flist).context("couldn't open file")?;
let reader = BufReader::new(filt_file);

// Read the file line by line using the lines() iterator from std::io::BufRead.
reader
.for_byte_line(|line| {
let mut bnk = BitNuclKmer::new(line, bclen as u8, false);
let (_, k, _) = bnk.next().expect("can't extract kmer");
let (_, k, _) = bnk.next().unwrap();
fset.insert(k.0);
Ok(true)
})
Expand Down

0 comments on commit 912ca01

Please sign in to comment.