Genomic operations
polars-bio implements the common genomic interval operations with a DataFrame API (both Polars and Pandas) and a native parallel engine. The comparison tables below map each operation to its equivalent in other libraries and link to the polars-bio API reference.
On this page: Interval operations ยท Pileup / depth
Genomic ranges operations
| operation | Bioframe | polars-bio | PyRanges0 | PyRanges1 | Pybedtools | GenomicRanges |
|---|---|---|---|---|---|---|
| overlap | overlap | overlap | join1 | join_overlaps | intersect2 | find_overlaps3 |
| nearest | closest | nearest | nearest | nearest_ranges | closest4 | nearest5 |
| count_overlaps | count_overlaps | count_overlaps | count_overlaps | count_overlaps | intersect6 | count_overlaps |
| cluster | cluster | cluster | cluster | cluster_overlaps | cluster | |
| merge | merge | merge | merge | merge_overlaps | merge | reduce7 |
| complement | complement | complement | complement_ranges | complement | gaps8 | |
| subtract | subtract | subtract | subtract | subtract_overlaps | subtract | subtract |
| coverage | coverage | coverage | coverage | coverage | coverage | |
| expand | expand | expand | extend | extend_ranges | slop | resize |
| sort | sort_bedframe | sort | sort | sort_ranges | sort | sort |
| read_table | read_table | read_table | read_bed | read_bed | BedTool | read_bed |
Note
- There is an overlap method in PyRanges, but its output is only limited to indices of intervals from the other Dataframe that overlap. In Bioframe's benchmark also join method instead of overlap was used.
- wa and wb options used to obtain a comparable output.
- Output contains only a list with the same length as query, containing hits to overlapping indices. Data transformation is required to obtain the same output as in other libraries. Since the performance was far worse than in more efficient libraries anyway, additional data transformation was not included in the benchmark.
- s=first was used to obtain a comparable output.
- select="arbitrary" was used to obtain a comparable output.
- -c flag used with
intersectto count overlaps per feature. - GenomicRanges exposes merge as reduce().
- GenomicRanges exposes complement as gaps().
Limitations
For now polars-bio uses int32 positions encoding for interval operations (issue) meaning that it does not support operation on chromosomes longer than 2Gb. int64 support is planned for future releases (issue).
Pileup operations
Per-base read depth computation from alignment files using CIGAR operations. Produces mosdepth-compatible coverage blocks.
| Feature | mosdepth | samtools depth | polars-bio |
|---|---|---|---|
| depth |
import polars_bio as pb
# Compute per-base depth from a BAM file
df = pb.depth("alignments.bam").collect()
# With MAPQ filter (equivalent to samtools depth -q 20)
df = pb.depth("alignments.bam", min_mapping_quality=20).collect()
# Via SQL
df = pb.sql("SELECT * FROM depth('alignments.bam')").collect()
FastQC quality control
Streaming FastQC quality-control modules over FASTQ files (plain, .gz, or BGZF) in a single out-of-core pass. All 12 core modules are implemented and bit-exact against FastQC 0.12.1 (--nogroup), computed in parallel and merged, so results are identical regardless of the number of partitions.
| Module | Module | Module |
|---|---|---|
basic_stats |
per_base_quality |
per_seq_quality |
per_base_content |
per_seq_gc |
per_base_n |
seq_length |
overrepresented |
adapter_content |
dup_levels |
per_tile_quality |
kmer_content |
import polars_bio as pb
# One streaming pass computes every module; access each as a LazyFrame.
qc = pb.fastqc("reads_R1.fastq.gz")
qc.per_base_quality.collect()
qc.per_tile_quality.collect()
qc.summary().collect() # PASS/WARN/FAIL status per module
# Compute only selected modules
qc = pb.fastqc("reads_R1.fastq.gz", modules=["basic_stats", "adapter_content"])
# Via SQL (tidy long-form output)
df = pb.sql("SELECT * FROM fastqc('reads_R1.fastq.gz')").collect()
Note
per_tile_quality and kmer_content reproduce FastQC's own subsampling
(per-tile: 10% after the first 10k reads; kmer: 2% of reads, file-order
dependent). Exact k-mer parity therefore requires a single-partition scan;
the other ten modules are partition-invariant and exact on all reads.
dup_levels/overrepresented use FastQC's 100k-unique observation
cutoff, matching FastQC's estimate on high-diversity libraries.