| Crates.io | iitree-rs |
| lib.rs | iitree-rs |
| version | 0.1.1 |
| created_at | 2025-11-05 15:40:36.442511+00 |
| updated_at | 2025-11-05 20:23:05.888429+00 |
| description | Implicit augmented interval tree (IAITree/cgranges) with memory-mapped disk storage |
| homepage | |
| repository | https://github.com/pangenome/iitree-rs |
| max_upload_size | |
| id | 1918179 |
| size | 37,246 |
Implicit Augmented Interval Tree in Rust with Disk-Backed Storage
A Rust implementation of the IAITree/cgranges algorithm with memory-mapped disk storage for handling large interval datasets.
Ord + Copy typesIntervals are stored in a sorted flat array and interpreted as an implicit complete binary tree. Each node is augmented with the maximum end position in its subtree, enabling efficient pruning during queries.
Based on the cgranges algorithm by Heng Li.
| Operation | Time | Space |
|---|---|---|
| Build (index) | O(n log n) | O(n) |
| Query (overlap) | O(log n + k) | - |
| Memory per interval | - | 32 bytes* |
*For Interval<u64, u64>. Scales with type sizes.
Add to your Cargo.toml:
[dependencies]
iitree-rs = "0.1"
use iitree_rs::{IITree, Interval};
fn main() -> std::io::Result<()> {
// Create tree backed by a file on disk
let mut tree = IITree::new("my_intervals.iitree")?;
// Start writer thread
tree.open_writer()?;
// Add intervals [start, end) with associated data
tree.add(10, 20, 1)?;
tree.add(15, 25, 2)?;
tree.add(30, 40, 3)?;
// Build the index (sorts and augments on disk)
tree.index()?;
// Query overlaps with [18, 22)
tree.overlap(18, 22, |idx, start, end, data| {
println!("Interval {}: [{}, {}) data={}", idx, start, end, data);
})?;
// Output:
// Interval 0: [10, 20) data=1
// Interval 1: [15, 25) data=2
Ok(())
}
use iitree_rs::IITree;
// Use custom position and data types
let mut tree: IITree<u32, String> = IITree::new();
tree.add(100, 200, "gene1".to_string());
tree.add(150, 250, "gene2".to_string());
tree.index();
tree.overlap(175, 225, |_, start, end, data| {
println!("[{}, {}): {}", start, end, data);
});
use iitree_rs::IITree;
let mut tree = IITree::new();
tree.add(10, 30, "A");
tree.add(20, 40, "B");
tree.add(25, 35, "C");
tree.index();
// Collect all overlapping intervals
let mut results = Vec::new();
tree.overlap(22, 28, |_, start, end, data| {
results.push((start, end, data));
});
assert_eq!(results.len(), 3);
assert_eq!(results, vec![(10, 30, "A"), (20, 40, "B"), (25, 35, "C")]);
use iitree_rs::IITree;
// Store genomic features with their positions
let mut features = IITree::new();
features.add(1000, 2000, "exon1");
features.add(3000, 4000, "exon2");
features.add(5000, 6000, "exon3");
features.add(1500, 3500, "intron1");
features.index();
// Find features overlapping position 3500
features.overlap(3500, 3501, |_, start, end, name| {
println!("{}: [{}, {})", name, start, end);
});
// Output:
// intron1: [1500, 3500)
// exon2: [3000, 4000)
Interval<S, T>Represents an interval with start, end, and associated data.
pub struct Interval<S, T> {
pub st: S, // Start position (inclusive)
pub en: S, // End position (exclusive)
pub max: S, // Max end in subtree (computed during indexing)
pub data: T, // Associated data
}
IITree<S, T>The interval tree container.
new() -> Self - Create an empty treeadd(start: S, end: S, data: T) - Add an intervalindex() - Sort and build the tree (required before queries)overlap<F>(st: S, en: S, func: F) - Find overlaps with [st, en)
FnMut(index: usize, start: S, end: S, data: T)len() -> usize - Number of intervalsis_empty() -> bool - Check if tree is emptyget(index: usize) -> Option<&Interval<S, T>> - Direct access to intervalBenchmarked on:
Performance characteristics match the C++ mmmulti::iitree implementation.
Run tests:
cargo test
Run comprehensive cgranges validation:
cargo test --release -- test_cgranges
The cgranges tests validate correctness by:
✅ Fully Implemented (v0.1):
🚧 Future Enhancements:
MIT
Contributions welcome! This crate is being developed as part of the seqwish Rust migration project.