Expand description
Read and write SLOW5 (text) and BLOW5 (binary) files containing Oxford Nanopore Technologies sequencing signal data.
This is an independent Rust re-implementation of hasindu2008/slow5lib, wire-compatible with the C version. The C implementation is the reference specification; this crate is designed to produce and consume byte-identical files.
§Quick start
§Reading records sequentially
use slow5lib::{Slow5Reader, Result};
fn main() -> Result<()> {
let mut reader = Slow5Reader::open("reads.blow5")?;
for record in reader.records() {
let r = record?;
println!("{}: {} samples", r.read_id, r.raw_signal.len());
}
Ok(())
}§Random access by read id
use slow5lib::{Slow5IndexedReader, Result};
fn main() -> Result<()> {
// Builds the index on first open; loads it on subsequent opens.
let reader = Slow5IndexedReader::open("reads.blow5")?;
let rec = reader.get("50abece6-9476-46be-a86f-d48cc3fddeb6")?;
println!("{} samples", rec.raw_signal.len());
Ok(())
}§Writing a BLOW5 file
use slow5lib::{Slow5Writer, record::Record, Result};
use slow5lib::header::{Header, RecordCompression, SignalCompression, ReadGroup};
use slow5lib::aux::AuxMeta;
use std::collections::HashMap;
fn main() -> Result<()> {
let header = Header {
version: (0, 2, 0),
num_read_groups: 1,
record_compression: RecordCompression::Zstd,
signal_compression: SignalCompression::SvbZd,
read_groups: vec![ReadGroup::default()],
aux_meta: AuxMeta::default(),
};
let mut writer = Slow5Writer::create("out.blow5", header)?;
let record = Record {
read_id: "my-read-001".to_string(),
read_group: 0,
digitisation: 2048.0,
offset: -224.0,
range: 1463.0,
sampling_rate: 4000.0,
raw_signal: vec![512i16, 515, 510, 518, 511],
aux: HashMap::new(),
};
writer.write(&record)?;
writer.finish()
}§Parallel write (batch)
Compress a batch of records across the rayon thread pool, then write sequentially.
Requires features = ["rayon"] in your Cargo.toml.
ⓘ
use slow5lib::{Slow5Writer, Result};
use slow5lib::header::{Header, RecordCompression, SignalCompression, ReadGroup};
use slow5lib::aux::AuxMeta;
fn main() -> Result<()> {
let header = Header {
version: (0, 2, 0),
num_read_groups: 1,
record_compression: RecordCompression::Zstd,
signal_compression: SignalCompression::SvbZd,
read_groups: vec![ReadGroup::default()],
aux_meta: AuxMeta::default(),
};
let records = vec![]; // normally populated from a reader
let mut writer = Slow5Writer::create("out.blow5", header)?;
writer.write_all_par(&records)?;
writer.finish()
}§Parallel decompression
Reads all compressed records in one sequential I/O pass, then decompresses
across the rayon thread pool with no lock contention.
Requires features = ["rayon"] in your Cargo.toml.
ⓘ
use slow5lib::{Slow5Reader, Result};
use rayon::prelude::*;
fn main() -> Result<()> {
let mut reader = Slow5Reader::open("reads.blow5")?;
reader.par_records().for_each(|rec| {
let r = rec.unwrap();
println!("{}: {} samples", r.read_id, r.raw_signal.len());
});
Ok(())
}§Main types
| Type | Purpose |
|---|---|
Slow5Reader | Sequential reading (SLOW5 and BLOW5) |
Slow5IndexedReader | Random access by read id (BLOW5) |
Slow5Writer | Write SLOW5 or BLOW5 files sequentially |
ParallelSlow5Writer | BLOW5 writer with background I/O thread |
Slow5WriteHandle | Cloneable write handle for ParallelSlow5Writer |
Record | Fully decoded record with raw signal |
RawRecord | Compressed record bytes; call decompress() to get a Record |
Header | File-level metadata and compression settings |
Re-exports§
pub use aux::AuxMeta;pub use aux::AuxType;pub use aux::AuxValue;pub use error::Result;pub use error::SlowError;pub use header::Header;pub use index::Index;pub use indexed_reader::Slow5IndexedReader;pub use reader::Slow5Reader;pub use record::RawRecord;pub use record::Record;pub use writer::ParallelSlow5Writer;pub use writer::Slow5WriteHandle;pub use writer::Slow5Writer;