Skip to main content

Long-Read Kit

Project description

IsoLens logo

Isoform-aware RNA modification and poly(A) tail analysis for direct RNA sequencing data.

IsoLens

PyPI - Version PyPI - Python Version License: MIT CI

IsoLens is a Python toolkit for isoform-aware analysis of RNA modifications and poly(A) tail lengths from Oxford Nanopore direct RNA sequencing data, explicitly accounting for transcript assignment uncertainty to enable accurate transcript-level profiling.


Why IsoLens?

Most long-read RNA analysis tools either analyze RNA modifications or poly(A) tails without discrimination of transcript isoforms or assign reads to transcripts using hard labels. IsoLens propagates transcript assignment probabilities from Oarfish throughout both modification and poly(A) analyses, enabling more accurate transcript-level estimates for genes with complex isoform structure.

Key capabilities:

  • Isoform-aware RNA modification profiling at single-nucleotide resolution
  • Transcript-level poly(A) tail length estimation with uncertainty propagation
  • Modification site co-occurrence and correlation analysis
  • Differential poly(A) testing between conditions
  • Efficient HDF5 and Parquet outputs for large-scale studies
  • Direct integration with Dorado BAM tags and Oarfish assignments

Quick Start

Install:

pip install isolens

Build transcript-level modification matrices:

python -m isolens.mod_scan -b alignments.bam -a oarfish.lz4 -o mod_scan.h5

Summarize modification sites:

python -m isolens.mod_sites -i mod_scan.h5 -o sites.parquet

Estimate transcript-level poly(A) lengths:

python -m isolens.polya_calc -a oarfish.lz4 -b reads.bam -o polya.tsv.gz -z

Contents


Pipeline Overview

Oarfish (.lz4) ─────┐
                     ├── mod_scan ──► HDF5 ──┬── mod_sites ──► site summary (.parquet/.tsv)
Dorado BAM ─────────┘                        │
                                             └── mod_corr ──► correlations (.parquet/.tsv)
                                                                  + PDF heatmaps (─P)

Oarfish (.lz4) ─────┐
                     ├── polya_calc ──► polya TSV ──┬── polya_merge ──► merged TSV
Minimap2 BAM ───────┘                               │
                                                    ├── polya_diff ──► diff TSV
                                                    └── polya_t2g ───► gene-level TSV

Outputs

Command Output
mod_scan HDF5 read × position modification matrices
mod_sites Per-site modification summaries
mod_corr Pairwise modification site correlations
polya_calc Transcript-level poly(A) estimates
polya_merge Merged replicate poly(A) estimates
polya_diff Differential poly(A) comparison
polya_t2g Gene-level poly(A) summaries

Installation

pip install isolens

Modules

mod_scan — HDF5 read × position matrices

Generates a single HDF5 file containing transcript-specific read-by-position modification matrices. For each transcript, IsoLens constructs an (n_reads × transcript_length) uint8 matrix that encodes the nucleotide state at every position for every aligned read. Nucleotide states are parsed using logic consistent with that implemented in modkit, ensuring compatibility with standard Oxford Nanopore modification annotations.

Encoding: 0 = uncovered, 1 = canonical match, 2 = mismatch, 3 = deletion, 4+ = modification types (configurable).

python -m isolens.mod_scan \
  -b alignments.bam \
  -a oarfish.lz4 \
  -o mod_scan.h5 \
  -c 0.95 \
  -v

Key options:

Flag Description Default
-b, --bam Transcriptome BAM alignment (required)
-a, --oarfish Oarfish assignment probability file (.lz4) (required)
-o, --output Output HDF5 path (required)
-c, --mod-cutoff Modification probability threshold 0.95
-m, --mod-type Modification types to scan for (SAM codes) a,m,17596,17802,19228,69426,19229,19227
-p, --min-asp Minimum assignment probability filter 0.0
-d, --max-depth Max reads per transcript 5000
-t, --threads Worker processes for parallel processing 1
-v, --verbose Print progress to stderr off

mod_sites — Per-position modification summaries

Reads the HDF5 output generated by mod_scan and summarizes modification information into a Parquet or TSV file, with one row per (transcript, position, modification_type). For each site, IsoLens reports modification levels, read coverage, and modification counts, while tracking mismatches and deletions as separate categories rather than treating them as modified or unmodified bases.

Note: When the same modification probability threshold is used (--mod-cutoff in IsoLens and --filter-threshold in modkit), the combination of mod_scan and mod_sites produces unweighted modification counts that match those generated by modkit pileup.

python -m isolens.mod_sites \
  -i mod_scan.h5 \
  -o sites.parquet

Key options:

Flag Description Default
-i, --h5 Input HDF5 from mod_scan (required)
-o, --output Output file (required)
-f, --format Output format: parquet or tsv parquet
-z, --gzip Gzip-compress TSV output off
-s, --sites Predefined modification sites TSV (tx_name, posn) all sites
-p, --min-asp Minimum assignment probability filter 0.0
-x, --transcripts Only process specified transcript IDs all
-v, --verbose Print progress off

Output columns: transcript_id, position, modification_type, n_modified, weighted_modified, n_unmodified, weighted_unmodified, n_mismatch, weighted_mismatch, n_deletion, weighted_deletion, modification_level, weighted_modification_level.


mod_corr — Pairwise modification site correlation

Identifies cooperative or antagonistic relationships between modification sites within the same transcript. Computes both within-type and cross-type correlations using weighted contingency tables.

Metrics: Phi coefficient, odds ratio, Fisher's exact test p-value, Benjamini-Hochberg FDR q-value, mutual information.

python -m isolens.mod_corr \
  -i mod_scan.h5 \
  -s sites.parquet \
  -o correlations.parquet \
  -m 10

Key options:

Flag Description Default
-i, --h5 Input HDF5 from mod_scan (required)
-s, --sites Site summary from mod_sites (required)
-o, --output Output file (required)
-m, --min-support Minimum n_modified for a site to be considered 10
-p, --min-asp Minimum assignment probability filter 0.0
-f, --format Output format: parquet or tsv parquet
-P, --plot Generate PDF heatmap per transcript in this directory off
-x, --transcripts Only process specified transcript IDs all
-v, --verbose Print progress off

Output columns: transcript_id, site1, site2, modification_type, n11, n10, n01, n00 (and weighted variants), phi, weighted_phi, odds_ratio, p_value, q_value, mutual_information, weighted_mutual_information.

When -P is used, generates rotated triangular heatmap PDFs per transcript showing the correlation matrix and site positions along the transcript body.


polya_calc — Poly(A) tail length estimation

Extracts poly(A) tail lengths from Dorado's pt:i BAM tags, weighted by Oarfish assignment probabilities.

python -m isolens.polya_calc \
  -a oarfish.lz4 \
  -b reads.bam \
  -o polya.tsv.gz \
  -z

Output columns: tx_name, tx_idx, n_reads, pa_wlen (weighted mean), probs (comma-separated), pa_lens (comma-separated).


polya_merge — Merge poly(A) replicates

Combines two poly(A) TSV files from separate replicates, recomputing weighted average tail lengths from the pooled per-read data.

python -m isolens.polya_merge \
  -i1 rep1.tsv.gz \
  -i2 rep2.tsv.gz \
  -o merged.tsv.gz

polya_diff — Differential poly(A) comparison

Compares poly(A) length distributions between two conditions using a weighted two-sample Kolmogorov-Smirnov test with Kish's effective sample size correction.

python -m isolens.polya_diff \
  -c1 control.tsv.gz \
  -c2 treatment.tsv.gz \
  -o diff.tsv

Output columns: tx_name (or gene_id), n_reads_1, pa_wlen_1, n_reads_2, pa_wlen_2, stat (KS statistic), p_value.


polya_t2g — Transcript-to-gene aggregation

Aggregates transcript-level poly(A) estimates to the gene level using a user-provided tx_name → gene_id mapping file.

python -m isolens.polya_t2g \
  -i polya.tsv.gz \
  -m tx2gene.tsv \
  -o gene_polya.tsv.gz

Python API

The core data structures and parsing functions are available for programmatic use:

from isolens._parsing import parse_oarfish

tx_names, prob_map, name_to_id = parse_oarfish("assignments.lz4")

# tx_names: list[str]
# prob_map: dict[int, list[TargetAssignment]]
# name_to_id: dict[str, int]

Input Data Requirements

File Source Required tags / format
Transcriptome BAM minimap2 + Dorado MM/ML (base modifications), pt:i (poly(A) tail length)
Oarfish assignments Oarfish LZ4-compressed read-to-transcript probability map

The BAM should be coordinate-sorted and aligned to a transcriptome reference.

Typical preprocessing:

minimap2 --eqx -N 100 -ax map-ont -y transcriptome.fa reads.fastq \
  | samtools sort -o alignments.bam

samtools index alignments.bam

Development

git clone https://github.com/gxelab/isolens.git
cd isolens
pip install -e ".[dev]"

Run without installing:

uv run python -m isolens.mod_scan \
  -b ... \
  -a ... \
  -o ...

Run tests:

pytest

Lint and format:

ruff check src tests
ruff format src tests

Example Data

The examples/ directory contains a small test dataset (subset of two Drosophila transcripts) suitable for verifying changes.

python -m isolens.mod_scan \
  -b examples/example.txmap.bam \
  -a examples/example.lz4 \
  -o example.mod_scan.h5 \
  -c 0.95 -v

python -m isolens.mod_sites \
  -i example.mod_scan.h5 \
  -o example.sites.parquet

python -m isolens.polya_calc \
  -a examples/example.lz4 \
  -b examples/example.txmap.bam \
  -o example.polya.tsv.gz -z

License

Distributed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

isolens-0.3.0.tar.gz (52.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

isolens-0.3.0-py3-none-any.whl (41.3 kB view details)

Uploaded Python 3

File details

Details for the file isolens-0.3.0.tar.gz.

File metadata

  • Download URL: isolens-0.3.0.tar.gz
  • Upload date:
  • Size: 52.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for isolens-0.3.0.tar.gz
Algorithm Hash digest
SHA256 3c81dcfc3c91bb4f08ea2a68711377530f4ca6b56baaf353baf7813288425d2d
MD5 42d246ccc69ea9c3a2b5f6d579ad4ff2
BLAKE2b-256 9eabd5498a116238c6e0958e869e753d5f7f9d4b1b995284d754e77796bad0d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for isolens-0.3.0.tar.gz:

Publisher: publish.yml on gxelab/isolens

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file isolens-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: isolens-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 41.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for isolens-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 30db07453974867a83eb27f7661c6f39254b11ebf3fc846cf98c9dc071c7036d
MD5 4810ebfc9d682c476143daeb2349a9de
BLAKE2b-256 e30719375108560fdba7c73b554b3dc4b5c1337073118413c1a6ce49b1b6b276

See more details on using hashes here.

Provenance

The following attestation bundles were made for isolens-0.3.0-py3-none-any.whl:

Publisher: publish.yml on gxelab/isolens

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page