Skip to main content

Long-Read Kit

Project description

IsoLens logo

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

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 isoform uncertainty
  • 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 × position modification matrices. For each transcript, it builds a (n_reads × tx_length) uint8 matrix encoding the alignment state at every position.

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 from mod_scan and produces a Parquet or TSV file with one row per (transcript, position, modification type). Computes modification levels and tracks mismatches and deletions separately.

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.2.0.tar.gz (38.1 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.2.0-py3-none-any.whl (35.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: isolens-0.2.0.tar.gz
  • Upload date:
  • Size: 38.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for isolens-0.2.0.tar.gz
Algorithm Hash digest
SHA256 0cdde4f030403e83d7d8480e08f190f45b0ab4d9f4c7129e628ebee65297be17
MD5 551517e538bcf7265e1015ab02740330
BLAKE2b-256 35727091d0ce12c49da7ffd0e9aad9bbb468cd26a0ce783817635e7cc29b98c5

See more details on using hashes here.

File details

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

File metadata

  • Download URL: isolens-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 35.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for isolens-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b26e1947068776bf7ebfbcd6d0552ad3eb1308c61ae0fe61e76ca0448ab22dc3
MD5 5a22fa07031d58910eb405e8b22a3fdf
BLAKE2b-256 ec85f3ab31ae644b218cc8a552d81bda633baffbbff3426364464ccb54a1c660

See more details on using hashes here.

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