runlength
Generic run-length encoded sequences in Rust, with plan-based arithmetic. It is
the successor to pyrle, with a new API and
any value type, not just f64.
| Crate | Contents |
|---|---|
runlength |
The core: generic Rle<V>, plans, merging, batches, coverage. Depends only on rayon. |
runlength-arrow |
The same over Apache Arrow arrays, so values can be any Arrow type, and batch keys are Arrow tables. |
runlength-py |
The runlength Python package (pyo3). Works with polars, pandas, pyarrow and numpy; none of them is required. |
Python
import polars as pl
import runlength as rl
df = pl.DataFrame({
"Chromosome": ["chr1", "chr1", "chr2"],
"Strand": ["+", "-", "+"],
"Start": [0, 2, 5],
"End": [3, 4, 7],
"Score": [0.5, 2.0, 1.0],
})
keys = df.select("Chromosome", "Strand")
cov = rl.coverage_by_key(keys, df["Start"], df["End"]) # an RleBatch
cov.get(("chr1", "+")) # Rle(length=3, runs=1, dtype=Int64) ...
(cov + cov).to_polars() # Chromosome, Strand, start, end, value
pl.DataFrame(cov.mean()) # Chromosome, Strand, mean
per_chrom = cov.collapse(drop="Strand") # add the strands together
starts, ends = (per_chrom.get("chr1") > 0).ranges() # back to intervals
best = rl.coverage_by_key(keys, df["Start"], df["End"], df["Score"], agg="max", fill=None)
cov.slice_agg(keys, df["Start"], df["End"], agg="mean") # mean coverage per interval, no copies
a = rl.Rle([3, 2], ["x", "y"]) # values of any type
b = rl.Rle([1, 4], pl.Series(["p", "q"]))
a.zip_with(b, lambda x, y: x + y, backend="polars") # any function, any library
a.plan(b) # or just the plan: (ends, idx_a, idx_b)
Inputs can be polars or pandas Series and DataFrames, pyarrow or numpy arrays,
or lists. Outputs (rle.values, rle.runs, batch.keys, ...) speak the Arrow
PyCapsule interface, so pl.Series(x), pa.array(x) and np.asarray(x) read
them without copying. ==, < etc. are element-wise and return boolean Rles;
a.equals(b) compares whole sequences.
Build it locally with cd crates/runlength-py && maturin develop --release.
use runlength::prelude::*;
let a = Rle::from_runs(&[3, 2], vec![1, 2])?;
let b = Rle::from_runs(&[1, 4], vec![10, 20])?;
// The plan only looks at run boundaries...
let p = a.plan_with(&b);
assert_eq!(p.ends, vec![1, 3, 5]);
assert_eq!((p.idx_a, p.idx_b), (vec![0, 0, 1], vec![0, 1, 1]));
// ...so any operation works on any value types.
let labels = a.zip_with(&b, None, None, |x, y| format!("{x}/{y}"))?;
// Operators pad the shorter side with zero and merge the result.
assert_eq!((&a + &b).to_dense(), vec![11, 21, 21, 22, 22]);
What's in it
| Area | API |
|---|---|
| Sequences | Rle<V> (owned), RleRef<V> (borrowed), shared methods on RleLike |
| Combining | plan, zip_with, zip_with_raw, + - * / & | ^, unary - and !, elem_eq/ne/lt/le/gt/ge |
| Merging | merge, merge_by(pred), merge_mask(mask, Keep), merge_plan(mask), is_merged |
| Slicing | get, slice, getitems (many slices → batch), slice_view and slice_reduce (reduce many slices without copying) |
| Rearranging | shift, reversed, concat, ranges_where |
| Many inputs | plan_many, zip_many |
| Reductions | sum, mean, variance(ddof), std(ddof), min, max (all weighted by run length) |
| Batches | RleBatch<K, V>: many sequences under any hashable keys, joins with How::{Outer, Inner, Left, Right}, collapse, concat, shift, reversed, slice_reduce, parallel with rayon |
| Coverage | coverage_sum, coverage_count, coverage_max, coverage_min (with _by_key variants), and overlap_plan / overlap_plan_by_key for any other aggregation |
Conventions
- Positions are
i64; every sequence starts at 0; intervals are[start, end). - Neighbouring runs merge when values are identical:
NaNmerges withNaN,-0.0does not merge with0.0. - Operations merge by default;
_rawvariants and plans do not. - Combining sequences of different lengths pads the shorter one with a fill
value. Operators use zero. With
zip_with, passingNonemakes unequal lengths an error.
See docs/design.md for the reasoning behind these choices.
Development
cargo test # unit, property and doc tests
PROPTEST_CASES=5000 cargo test --release # more property-test cases
cargo run --release --example bench # rough timings
cd crates/runlength-py && maturin develop --release && pytest tests
# Regenerate the pyrle cross-check cases (needs a Python that imports pyrle):
PYTHONPATH=~/code/pyrle python3.12 scripts/gen_pyrle_fixtures.py
# Check the reference port of pyranges' to_rle / to_bigwig against
# pyranges1 + pyrle (needs both installed, plus pyBigWig):
PYTHONPATH=~/code/pyrle python scripts/pyranges_port.py 1000
Releasing
Versions of all three crates move together. Bump version in each
crates/*/Cargo.toml (and the runlength version that runlength-arrow
requires), commit, then push a tag:
git tag py-v0.2.0 && git push origin py-v0.2.0 # wheels + sdist to PyPI
git tag rust-v0.2.0 && git push origin rust-v0.2.0 # runlength, runlength-arrow to crates.io
.github/workflows/release.yml checks that the tag matches the crate
versions, builds wheels for Linux (x86_64, aarch64), macOS (universal2) and
Windows, tests them, and publishes. Run it by hand from the Actions tab to
build and test the wheels without publishing.
One-time setup: add pyranges/runlength with workflow release.yml as a
trusted publisher on PyPI, and save a crates.io token as the
CARGO_REGISTRY_TOKEN repository secret.
Metadata
Release files for runlength 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| runlength-0.1.0.tar.gz | 126.7 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| runlength-0.1.0-cp311-abi3-win_amd64.whl | CPython 3.11 | abi3 | Windows x86-64 | Details |
| runlength-0.1.0-cp311-abi3-manylinux_2_28_x86_64.whl | CPython 3.11 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| runlength-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl | CPython 3.11 | abi3 | Linux glibc 2.28+ ARM64 | Details |
| runlength-0.1.0-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.11 | abi3 | macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64 | Details |
Total release size: 23.7 MB
Release files / runlength-0.1.0.tar.gz
| Download URL | runlength-0.1.0.tar.gz |
|---|---|
| Size | 126.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2db118d9e71eca6168ead9a2ebfa71827b195a003b86952cbda6a3f4efb13171
|
|
BLAKE2b-256 checksum How to use checksums |
1e1201162d63c48861115d9060861b7da6d2d1c0c3dfc6e2af65f052191670bb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / runlength-0.1.0-cp311-abi3-win_amd64.whl
| Download URL | runlength-0.1.0-cp311-abi3-win_amd64.whl |
|---|---|
| Size | 4.5 MB |
| Tags | CPython 3.11 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
35968ee200755db4774805c299cf119f2f7fbff62495887d03e722e25e0f98bd
|
|
BLAKE2b-256 checksum How to use checksums |
852f04435ead6bc1013730a4392f1a7cc5b0464ab4505927cd56e12221a5cb10
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / runlength-0.1.0-cp311-abi3-manylinux_2_28_x86_64.whl
| Download URL | runlength-0.1.0-cp311-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 5.0 MB |
| Tags | CPython 3.11 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
b15ae6c59fce0fb24e92b985ccf732a6b072dd36091b079635dde3f03c0767e5
|
|
BLAKE2b-256 checksum How to use checksums |
fc2341094a669140300905c666c81f386059590f14d28e8c116c89d8193cc6da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / runlength-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl
| Download URL | runlength-0.1.0-cp311-abi3-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 5.1 MB |
| Tags | CPython 3.11 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
2f7672fa51be8c3715b32cebc0092c239887341268534fae98f5c4f74bb307ec
|
|
BLAKE2b-256 checksum How to use checksums |
b23830173c4008e81f1b7df99304241ea8879f48ecc6cc3c502a614da7838a59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / runlength-0.1.0-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | runlength-0.1.0-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 8.9 MB |
| Tags | CPython 3.11 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
4551f1d3ef714a66128a7e538707294fd0d1f858a47c2af8b6e09d4fe946f964
|
|
BLAKE2b-256 checksum How to use checksums |
00819bb19e9e7267bcc0b5c0bb30f78865a29cdebb58507603a2a206730b950c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency log