#![forbid(unsafe_code)]
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
struct ReadmeExamples;
pub mod arrays;
pub mod bam;
pub mod bbi;
pub mod bytes;
pub mod error;
#[cfg(test)]
mod fuzz;
pub mod genomes;
pub mod genomic;
pub mod hic;
#[cfg(feature = "npz")]
pub mod npz;
pub mod parallel;
pub mod progress;
pub mod source;
pub use error::{Error, Result};
pub use genomes::get_chr_sizes;
#[allow(clippy::large_enum_variant)]
pub enum Reader {
Bbi(bbi::BbiReader),
Bam(bam::BamReader),
HiC(hic::HiCReader),
}
#[derive(Debug, Clone)]
pub struct OpenOptions {
pub parallel: i64,
pub zoom_correction: f64,
pub block_size: Option<u64>,
pub max_blocks: Option<usize>,
pub index_path: Option<String>,
}
impl Default for OpenOptions {
fn default() -> Self {
Self {
parallel: -1,
zoom_correction: 1.0 / 3.0,
block_size: None,
max_blocks: None,
index_path: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FileKind {
BigWig,
BigBed,
Bam,
HiC,
}
pub fn sniff_source(source: &dyn source::ByteSource) -> Result<FileKind> {
let head = source.read_at(0, 4)?;
if head.len() < 4 {
return Err(Error::format(
source.path(),
"file is too short to carry a magic number",
));
}
if &head[..3] == b"HIC" {
return Ok(FileKind::HiC);
}
let magic = u32::from_le_bytes([head[0], head[1], head[2], head[3]]);
match magic {
bbi::BIGWIG_MAGIC => return Ok(FileKind::BigWig),
bbi::BIGBED_MAGIC => return Ok(FileKind::BigBed),
bbi::header::BIGWIG_MAGIC_SWAPPED | bbi::header::BIGBED_MAGIC_SWAPPED => {
return Err(Error::format(source.path(), "incompatible endianness"))
}
_ => {}
}
if head[0] == 0x1F && head[1] == 0x8B {
return Ok(FileKind::Bam);
}
Err(Error::format(
source.path(),
"not a bigwig, bigbed, bam or hic file",
))
}
pub fn sniff(path: &str) -> Result<FileKind> {
let source = source::open(path, Some(4096), Some(1))?;
sniff_source(source.as_ref())
}
pub fn open(path: &str, options: OpenOptions) -> Result<Reader> {
let source = source::open(path, options.block_size, options.max_blocks)?;
match sniff_source(source.as_ref())? {
FileKind::BigWig | FileKind::BigBed => Ok(Reader::Bbi(bbi::BbiReader::from_source(
source,
path,
options.parallel,
options.zoom_correction,
)?)),
FileKind::Bam => Ok(Reader::Bam(bam::BamReader::from_source(
source,
path,
options.index_path.as_deref(),
options.parallel,
options.block_size,
options.max_blocks,
)?)),
FileKind::HiC => Ok(Reader::HiC(hic::HiCReader::from_source(
source,
path,
options.parallel,
)?)),
}
}