6个版本
新版本 0.3.1 | 2024年8月22日 |
---|---|
0.3.0 | 2024年8月20日 |
0.2.4 | 2024年7月1日 |
0.2.3 | 2024年4月21日 |
0.1.2 |
|
#593 in 解析器实现
每月下载量 272
545KB
2K SLoC
bcf_reader
这是一个尝试创建一个轻量级、纯Rust库,以允许高效、跨平台访问BCF文件中的基因型数据。
目前,rust_htslib
包只适用于Linux和macOS(不适用于Windows?)。noodles包是一个适用于多种生物信息学文件格式的纯Rust库,可以在Windows、Linux和macOS上运行。然而,由于内存分配模式,noodles包读取BCF文件中的基因型数据的API可能较慢。此外,这两个包都有大量的依赖项,因为它们提供许多功能并支持广泛的文件格式。
解决内存分配和依赖问题的一种方法是根据其规范手动解析BCF记录(https://samtools.github.io/hts-specs/VCFv4.2.pdf)并在可能的情况下使用迭代器,特别是对于每个样本的字段,如GT和AD。
注意:此包处于早期开发阶段。
使用方法
use bcf_reader::*;
let mut reader = smart_reader("testdata/test2.bcf");
let header = Header::from_string(&read_header(&mut reader));
// find key for a field in INFO or FORMAT or FILTER
let key = header.get_idx_from_dictionary_str("FORMAT", "GT").unwrap();
// access header dictionary
let d = &header.dict_strings()[&key];
assert_eq!(d["ID"], "GT");
assert_eq!(d["Dictionary"], "FORMAT");
/// get chromosome name
assert_eq!(header.get_chrname(0), "Pf3D7_01_v3");
let fmt_ad_key = header
.get_idx_from_dictionary_str("FORMAT", "AD")
.expect("FORMAT/AD not found");
let info_af_key = header
.get_idx_from_dictionary_str("INFO", "AF")
.expect("INFO/AF not found");
// this can be and should be reused to reduce allocation
let mut record = Record::default();
while let Ok(_) = record.read(&mut reader) {
let pos = record.pos();
// use byte ranges and shared buffer to get allele string values
let allele_byte_ranges = record.alleles();
let share_buf = record.buf_shared();
let ref_rng = &allele_byte_ranges[0];
let ref_allele_str =
std::str::from_utf8(&share_buf[ref_rng.start..ref_rng.end]).unwrap();
let alt1_rng = &allele_byte_ranges[1];
let alt1_allele_str =
std::str::from_utf8(&share_buf[alt1_rng.start..alt1_rng.end]).unwrap();
// ...
// access FORMAT/GT via iterator
for nv in record.fmt_gt(&header) {
let (has_no_ploidy, is_missing, is_phased, allele_idx) = nv.gt_val();
// ...
}
// access FORMAT/AD via iterator
for nv in record.fmt_field(fmt_ad_key) {
match nv.int_val() {
None => {}
Some(ad) => {
// ...
}
}
// ...
}
// access FILTERS via itertor
record.filters().for_each(|nv| {
let filter_key = nv.int_val().unwrap() as usize;
let dict_string_map = &header.dict_strings()[&filter_key];
let filter_name = &dict_string_map["ID"];
// ...
});
// access INFO/AF via itertor
record.info_field_numeric(info_af_key).for_each(|nv| {
let af = nv.float_val().unwrap();
// ...
});
}
依赖项
~2MB
~35K SLoC