Rust基因组数据处理库rust-htslib的使用:支持SAM/BAM/CRAM/VCF/BCF等格式的高效读写与操作
Rust基因组数据处理库rust-htslib的使用:支持SAM/BAM/CRAM/VCF/BCF等格式的高效读写与操作
简介
rust-htslib是一个提供HTSlib绑定和高级Rust API的库,用于读写BAM文件。它支持多种基因组数据格式包括SAM、BAM、CRAM、VCF和BCF等。
安装
在Cargo.toml中添加以下依赖:
[dependencies]
rust-htslib = "*"
或者运行以下命令:
cargo add rust-htslib
功能选项
默认情况下,rust-htslib链接到bzip2-sys
和lzma-sys
以支持完整的CRAM功能。如果不需要CRAM支持,可以禁用这些功能:
[dependencies]
rust-htslib = { version = "*", default-features = false }
其他可选功能:
serde
:支持bam::Record
的序列化/反序列化curl
:HTTP文件访问支持s3
和gcs
:S3和Google Cloud Storage支持(测试版)bindgen
:为htslib生成绑定(会显著增加构建时间)
完整示例
以下是一个使用rust-htslib读取BAM文件的完整示例:
use rust_htslib::{bam, bam::Read};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 打开BAM文件
let mut bam = bam::Reader::from_path("input.bam")?;
// 创建BAM头信息
let header = bam::Header::from_template(bam.header());
// 创建输出BAM文件
let mut out = bam::Writer::from_path("output.bam", &header, bam::Format::Bam)?;
// 遍历所有记录
for result in bam.records() {
let mut record = result?;
// 在这里处理每条记录
// 例如:过滤质量值大于20的记录
if record.mapq() > 20 {
out.write(&record)?;
}
}
Ok(())
}
另一个示例,展示如何读取VCF文件:
use rust_htslib::{vcf, vcf::Read};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 打开VCF文件
let mut vcf = vcf::Reader::from_path("input.vcf")?;
// 创建输出VCF文件
let header = vcf::Header::from_template(vcf.header());
let mut out = vcf::Writer::从路径("output.vcf", &header, false)?;
// 遍历所有变异记录
for result in vcf.records() {
let record = result?;
// 在这里处理每条变异记录
// 例如:过滤PASS的变异
if record.is_pass() {
out.write(&record)?;
}
}
Ok(())
}
替代方案
noodles是另一个由Michael Macias实现的纯Rust方案,实现了htslib的大部分C功能(仍处于实验阶段)。
作者
- Johannes Köster
- Christopher Schröder
- Patrick Marks
- David Lähnemann
- Manuel Holtgrewe
- Julian Gehring
许可证
MIT许可证
更多完整示例
示例1:BAM文件索引查询
use rust_htslib::{bam, bam::IndexedReader};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建索引读取器
let mut bam = bam::IndexedReader::from_path("input.bam")?;
// 查询特定区域
let tid = 0; // 染色体ID
let start = 10000; // 起始位置
let end = 20000; // 结束位置
// 获取区域内的记录
for record in bam.query(tid, start, end)? {
let record = record?;
println!("Found record at {}", record.pos());
}
Ok(())
}
示例2:BCF文件写入
use rust_htslib::bcf::{self, Read, Writer, Format};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 读取BCF文件
let mut bcf = bcf::Reader::from_path("input.bcf")?;
// 创建输出BCF文件
let header = bcf::Header::from_template(bcf.header());
let mut out = bcf::Writer::from_path("output.bcf", &header, false, Format::BCF)?;
// 遍历记录并写入
for result in bcf.records() {
let record = result?;
out.write(&record)?;
}
Ok(())
}
示例3:SAM文件转换
use rust_htslib::{sam, bam};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 读取SAM文件
let mut sam = sam::Reader::from_path("input.sam")?;
// 创建BAM输出文件
let header = bam::Header::from_template(sam.header());
let mut bam = bam::Writer::from_path("output.bam", &header, bam::Format::Bam)?;
// 转换记录
for record in sam.records() {
let record = record?;
bam.write(&record.to_bam())?;
}
Ok(())
}
1 回复
Rust基因组数据处理库rust-htslib的使用指南
概述
rust-htslib是Rust语言对HTSlib(C库)的绑定,提供了高效处理基因组数据的接口,支持多种常见生物信息学文件格式:
- 序列比对格式:SAM/BAM/CRAM
- 变异数据格式:VCF/BCF
- 索引格式:CSI/BAI/TBI
安装方法
在Cargo.toml中添加依赖:
[dependencies]
htslib = "0.40"
核心功能与使用示例
1. BAM文件读取
use htslib::{bam, bam::Read};
fn read_bam_file(path: &str) -> Result<(), Box<dyn std::error::Error>> {
// 打开BAM文件
let mut bam = bam::Reader::from_path(path)?;
// 遍历所有记录
for record in bam.records() {
let record = record?;
println!("Read {} at position {}:{}",
bam::record::Record::qname(&record),
record.tid(),
record.pos());
}
Ok(())
}
2. BAM文件写入
use htslib::{bam, bam::Write};
fn write Bam文件写入
```rust
use htslib::{bam, bam::Write};
fn write_bam_file(input: &str, output: &str) -> Result<(), Box<dyn std::error::Error>> {
// 读取输入文件
let mut in_bam = bam::Reader::from_path(input)?;
// 创建输出文件
let header = bam::Header::from_template(in_bam.header());
let mut out_bam = bam::Writer::from_path(output, &header, bam::Format::Bam)?;
// 复制记录
for record in in_bam.records() {
out_bam.write(&record?)?;
}
Ok(())
}
3. VCF文件处理
use htslib::{vcf, vcf::Read};
fn process_vcf(path: &str) -> Result<(), Box<dyn std::error::Error>> {
// 打开VCF文件
let mut vcf = vcf::Reader::from_path path)?;
// 读取头信息
let header = vcf.header().clone();
// 遍历变异记录
for record in vcf.records() {
let record = record?;
println!("Variant at {}:{}", record.chrom(), record.pos());
// 获取基因型信息
if let Some(gt) = record.genotypes() {
for sample in gt.iter() {
println!("Sample genotype: {:?}", sample);
}
}
}
Ok(())
}
4. 使用索引进行区域查询
use htslib::{bam, bam::IndexedReader};
fn query_region(bam_path: &str, region: &str) -> Result<(), Box<dyn std::error::Error>> {
// 创建带索引的读取器
let mut bam = bam::IndexedReader::from_path(bam_path)?;
// 解析区域字符串
let (tid, start, end) = bam.parse_region(region)?;
// 查询特定区域
bam.fetch((tid, start, end))?;
// 遍历区域内的记录
for record in bam.records() {
let record = record?;
println!("Read in region: {}", bam::record::Record::qname(&record));
}
Ok(())
}
高级特性
多线程处理
use htslib::bam;
use rayon::prelude::*;
fn parallel_process(bam_path: &str) -> Result<(), Box<dyn std::error::Error>> {
let bam = bam::IndexedReader::from_path(bam_path)?;
// 收集所有记录(注意内存使用)
let records: Vec<_> = bam.records().collect::<Result<Vec<_>, _>>()?;
// 并行处理
records.par_iter().for_each(|record| {
// 处理每条记录
let _length = record.seq().len();
// 其他处理...
});
Ok(())
}
自定义记录过滤
use htslib::bam;
fn filter_records(bam_path: &str, min_qual: u8) -> Result<(), Box<dyn std::error::Error>> {
let mut bam = bam::Reader::from_path(bam_path)?;
for record in bam.records() {
let record = record?;
// 过滤低质量记录
if record.mapq() >= min_qual {
println!("High quality read: {}", bam::record::Record::qname(&record));
}
}
Ok(())
}
性能提示
- 使用
IndexedReader
进行区域查询比全文件扫描快得多 - 批量处理记录比逐条处理更高效
- 对于大型文件,考虑使用多线程处理
- 避免频繁的内存分配,重用记录对象
错误处理
rust-htslib使用Rust的标准错误处理机制,建议使用?
操作符或match
表达式处理可能的错误:
match bam::Reader::from_path("input.bam") {
Ok(reader) => {
// 处理文件
},
Err(e) => {
eprintln!("Failed to open BAM file: {}", e);
// 错误处理
}
}
完整示例
下面是一个完整的示例,展示如何使用rust-htslib从BAM文件中读取数据并进行简单分析:
use htslib::{bam, bam::Read};
fn analyze_bam(bam_path: &str) -> Result<(), Box<dyn std::error::Error>> {
// 打开BAM文件
let mut bam = bam::Reader::from_path(bam_path)?;
// 获取参考序列信息
let header = bam.header();
let targets = header.target_names();
println!("Reference sequences: {:?}", targets);
// 统计读取数和映射质量
let mut total_reads = 0;
let mut mapped_reads = 0;
let mut total_mapq = 0;
for record in bam.records() {
let record = record?;
total_reads += 1;
// 检查是否映射
if !record.is_unmapped() {
mapped_reads += 1;
total_mapq += record.mapq() as usize;
}
}
// 计算结果
let mapping_rate = mapped_reads as f64 / total_reads as f64 * 100.0;
let avg_mapq = if mapped_reads > 0 {
total_mapq as f64 / mapped_reads as f64
} else {
0.0
};
println!("Total reads: {}", total_reads);
println!("Mapped reads: {}", mapped_reads);
println!("Mapping rate: {:.2}%", mapping_rate);
println!("Average mapping quality: {:.2}", avg_mapq);
Ok(())
}
fn main() {
if let Err(e) = analyze_bam("example.bam") {
eprintln!("Error analyzing BAM file: {}", e);
}
}
总结
rust-htslib提供了高性能的基因组数据处理能力,结合Rust的安全性和并发特性,非常适合构建高效、可靠的生物信息学分析工具。通过合理使用其API,可以处理大规模基因组数据,同时保证代码的安全性和性能。