Add unitig streaming iterators and estimate CLI subcommand
Introduce `iter_unitigs` methods across the index cache, content layer, MphfLayer, and typed layer to stream whole reconstructed sequences directly from underlying storage without decomposing into k-mers. Add a corresponding low-level streaming iterator in obiskio for thread-safe, lazy reads from memory-mapped files. Include a new CLI subcommand to compute and display approximate false-positive rates based on provided indexing parameters.
This commit is contained in:
@@ -311,4 +311,16 @@ impl KmerLayer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate over the layer's unitigs (whole sequences, not decomposed
|
||||
/// into k-mers) — the "layer level" step of the layer/partition/index
|
||||
/// chain of unitig iterators; see `KmerPartition::iter_unitigs`/
|
||||
/// `KmerIndex::iter_unitigs`.
|
||||
pub fn iter_unitigs(&self) -> crate::layer::mphf_layer::UnitigIter {
|
||||
match self {
|
||||
KmerLayer::Count { layer, .. } => layer.iter_unitigs(),
|
||||
KmerLayer::Presence { layer, .. } => layer.iter_unitigs(),
|
||||
KmerLayer::Empty { .. } => panic!("Layer::iter_unitigs() called on an Empty layer"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ pub(crate) mod utils;
|
||||
pub use crate::index::error::{OKIError, OKIResult};
|
||||
pub use content_layer::KmerLayer;
|
||||
pub use meta::IndexMode;
|
||||
pub use mphf_layer::{EvidenceKind, KmerBatchIter, KmerIter, MphfLayer, MphfOnly};
|
||||
pub use mphf_layer::{EvidenceKind, KmerBatchIter, KmerIter, MphfLayer, MphfOnly, UnitigIter};
|
||||
pub use typed_layer::{HasLayerContent, HasStorageKind, Hit, LayerContent, LayerData, TypedLayer};
|
||||
|
||||
@@ -341,6 +341,16 @@ impl MphfLayer {
|
||||
(base, batch)
|
||||
})
|
||||
}
|
||||
|
||||
/// Iterate over the layer's unitigs (whole reconstructed sequences, not
|
||||
/// decomposed into k-mers), in the physical order of `unitigs.bin`. Same
|
||||
/// `Send + 'static` shape as [`iter_kmers`](Self::iter_kmers), via
|
||||
/// `UnitigFileReader::iter_unitigs_owned`.
|
||||
pub fn iter_unitigs(&self) -> UnitigIter {
|
||||
UnitigIter {
|
||||
inner: Box::new(self.unitigs.iter_unitigs_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Iterator types ────────────────────────────────────────────────────────────
|
||||
@@ -365,6 +375,24 @@ impl Iterator for KmerIter {
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over the unitigs stored in a layer, whole (not decomposed into
|
||||
/// k-mers). Produced by [`MphfLayer::iter_unitigs`]. Same ownership shape as
|
||||
/// [`KmerIter`] — owns an `Arc<UnitigFileReader>` clone, `Send + 'static`,
|
||||
/// streamed from disk.
|
||||
pub struct UnitigIter {
|
||||
inner: Box<dyn Iterator<Item = (usize, obikseq::Unitig)> + Send>,
|
||||
}
|
||||
|
||||
impl Iterator for UnitigIter {
|
||||
type Item = obikseq::Unitig;
|
||||
|
||||
/// Return the next unitig in iteration order (its `chunk_id` dropped —
|
||||
/// use [`Iterator::enumerate`] if the index within the layer is needed).
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next().map(|(_, unitig)| unitig)
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over batches of canonical kmers stored in a layer.
|
||||
///
|
||||
/// Produced by [`MphfLayer::iter_kmers_batch`]. Each call to [`next`](Self::next)
|
||||
|
||||
@@ -223,6 +223,12 @@ impl<D: LayerData> TypedLayer<D> {
|
||||
self.mphf.enumerate_kmers_batch(n)
|
||||
}
|
||||
|
||||
/// Iterate over the layer's unitigs (whole sequences, not decomposed
|
||||
/// into k-mers).
|
||||
pub fn iter_unitigs(&self) -> crate::layer::mphf_layer::UnitigIter {
|
||||
self.mphf.iter_unitigs()
|
||||
}
|
||||
|
||||
pub fn unitig_writer(out_dir: &Path) -> OKIResult<UnitigFileWriter> {
|
||||
MphfLayer::unitig_writer(out_dir)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user