rseqc-redux is a modernized fork of RSeQC (RNA-seq Quality Control), originally by Liguo Wang. It updates the RSeQC 5.0.1 codebase with modern Python packaging, comprehensive tests, and CI — while preserving the original functionality.
- Python 3.10 or higher
- Indexed BAM files (
.bamwith corresponding.bam.baiindex files) - A BED-format gene model / reference annotation
Core dependencies are automatically installed:
pysam— BAM/SAM file handlingbx-python— Interval indexing and overlapnumpy— Numerical operationspyBigWig— BigWig file I/Omatplotlib/logomaker— Plotting
pip install rseqc-reduxgit clone https://github.com/semenko/rseqc-redux.git
cd rseqc-redux
pip install .git clone https://github.com/semenko/rseqc-redux.git
cd rseqc-redux
uv sync# Basic BAM statistics
bam_stat -i sample.bam
# Infer RNA-seq strandedness
infer_experiment -r gene_model.bed -i sample.bam
# Transcript integrity number
tin -i sample.bam -r gene_model.bed
# Gene body coverage
geneBody_coverage -r gene_model.bed -i sample.bam -o output
# Read distribution over genomic features
read_distribution -r gene_model.bed -i sample.bam
# Junction annotation
junction_annotation -r gene_model.bed -i sample.bam -o output| Tool | Description |
|---|---|
bam_stat |
Summarize mapping statistics of a BAM file |
bam2fq |
Convert BAM alignments to FASTQ format |
bam2wig |
Convert BAM to wiggle/BigWig |
divide_bam |
Equally divide BAM file into n parts |
split_bam |
Split BAM by chromosome |
split_paired_bam |
Split paired-end BAM into two single-end BAMs |
infer_experiment |
Infer RNA-seq strandedness |
inner_distance |
Inner distance between read pairs |
RNA_fragment_size |
Fragment size statistics per gene |
tin |
Calculate Transcript Integrity Number |
geneBody_coverage |
Gene body coverage profile |
geneBody_coverage2 |
Gene body coverage from BigWig input |
read_distribution |
Reads over genomic features (CDS, UTR, intron, etc.) |
read_duplication |
Read duplication rate |
read_GC |
GC content of reads |
read_NVC |
Nucleotide composition (ACGT) along reads |
read_quality |
Per-position quality scores |
read_hexamer |
Hexamer frequency analysis |
junction_annotation |
Annotate splice junctions |
junction_saturation |
Splice junction saturation analysis |
FPKM_count |
FPKM expression quantification |
FPKM-UQ |
Upper-quartile normalized FPKM |
RPKM_saturation |
RPKM saturation analysis |
mismatch_profile |
Mismatch profile along reads |
insertion_profile |
Insertion profile along reads |
deletion_profile |
Deletion profile along reads |
clipping_profile |
Clipping profile along reads |
normalize_bigwig |
Normalize BigWig signal to fixed wigsum |
overlay_bigwig |
Pairwise operations on two BigWig files |
sc_bamStat |
Single-cell RNA-seq mapping statistics |
sc_editMatrix |
Barcode/UMI error correction heatmaps |
sc_seqLogo |
DNA sequence logo from FASTQ/FASTA |
sc_seqQual |
Sequencing quality heatmap from FASTQ |
Benchmarked against RSeQC 5.0.4 on the official RSeQC test data (chr22 subset, ~430K paired-end reads). See benchmark-data/BENCHMARK_REPORT.md for the full report with profiling details.
| Script | Original | Redux | Speedup |
|---|---|---|---|
tin |
23.7s | 3.4s | 7.1x |
geneBody_coverage |
19.8s | 3.5s | 5.7x |
bam_stat |
3.5s | 0.8s | 4.2x |
RPKM_saturation |
3.9s | 1.4s | 2.8x |
read_NVC |
2.7s | 1.5s | 1.8x |
clipping_profile |
1.0s | 0.7s | 1.5x |
| All other scripts | ~1.0x |
Key optimizations: pysam count_coverage() replacing manual pileup iteration (tin, geneBody_coverage), numpy vectorization (read_NVC, RPKM_saturation), single-pass CIGAR loops (clipping/insertion profiles), and dead code removal (bam_stat).
fetch_exon() in bam_cigar.py had a long-standing bug inherited from the original RSeQC: soft clip CIGAR operations incorrectly advanced the reference coordinate, shifting exon boundaries rightward for reads with leading soft clips. The sibling function fetch_intron() already handled this correctly. This affects output from any script that resolves read-to-genome exon coordinates: bam2wig, read_distribution, read_duplication, RPKM_saturation, FPKM_count, and inner_distance.
Should I re-run my analyses? Almost certainly not. The shifts are small (1–10 bp, matching the soft clip length) and only affect the ~5% of reads with leading soft clips. Gene-level counts, coverage profiles, and quality metrics change by amounts well below meaningful thresholds. See CHANGES.md for a per-script impact table.
Contributions are welcome!
# Install development dependencies
uv sync
# Run tests
uv run pytest
# Run full test matrix
uv run nox
# Lint and format
uv run ruff check .
uv run ruff format .
# Type check
uv run mypy rseqc/Distributed under the terms of the GPLv3+ license, rseqc-redux is free and open source software.
If you encounter any problems, please file an issue with a description of the problem, steps to reproduce, and relevant error messages.
Original RSeQC by Liguo Wang — rseqc.sourceforge.net
Modernization by Nick Semenkovich (@semenko).