polaranges
Draft for a Rust-first genomic range library built on top of Polars and
ruranges-core.
The first goal is a RangeFrame wrapper that:
- owns a
polars::DataFrame, - validates interval semantics (
Start,End, non-null,Start < End), - factorizes
match_bycolumns into denseu32group ids, - calls the overlap kernels in
ruranges-core, and - uses the returned row indices to gather rows back out of Polars.
This keeps the heavy overlap logic in Rust while leaning on Polars for table storage and projection.
Why row indices first?
Polars does not have a pandas-style index, and that is fine here. The natural
primitive from ruranges-core is a pair of row-id vectors:
left[i]is a row in the queryRangeFrameright[i]is the matching row in the targetRangeFrame
That means the library can expose both:
overlap_pairs(...) -> OverlapPairsoverlap(...) -> RangeFrame
where overlap() is only sugar for self.take_rows(&pairs.left).
This is the same shape as pyrunges: the high-level operation is a thin layer
over a low-level kernel that returns row matches.
Current draft scope
The draft in src/ keeps v1 intentionally narrow:
- generic
RangeFramewith configurable start/end column names overlap_pairs()overlap()- row gathering with
take_rows() - pure Rust
match_byfactorization for strings, booleans, and integer columns
The draft currently normalizes coordinates to i64 before calling
ruranges-core. That keeps the first version simple and fully Rust-native.
A later optimization can add zero-copy dispatch for i32 and i64.