Skip to main content

A Python interface to rammap, the Rust implementation of minimap2

Project description

🔗🐍🧬 rammappy Stars

PyO3 bindings and Python interface to rammap, the Rust implementation of minimap2.

Release PyPI ruff ty Code style: black

⚠️ Warning

This library is still a work-in-progress, and in an experimental stage, with API breaks very likely between minor versions.


🗺️ Overview

minimap2 is a widely used mapping tool for nucleotide sequences. rammap1 is a reimplementation of minimap2 in Rust, demonstrating perfect concordance while enabling performance optimizations for modern architectures. It maintains Rust's stronger memory safety constraints and provides a modular architecture.

rammappy is a Python module, implemented using the PyO3 framework, that provides bindings to rammap. It directly links to the rammap-core crate, which provides the following advantages:

  • zero-copy: Sequences are passed around as contiguous blocks of C-memory storing the byte sequences.
  • multithreaded: True parallel alignment inside a detached thread context that completely drops the Python GIL during batch processing.
  • lazy evaluation: Iterator-based result generation ensures massive mapping tasks don't blow up system memory.

🔧 Installing

rammappy can be installed directly from PyPI, which hosts some pre-built CPython wheels.

If you are building from source or working on development, we prefer using uv for environment and dependency management, along with just as a command runner:

just install

(This command wraps uv venv --allow-existing and uv pip install -e .)

💡 Examples

🧠 Building an Index In-Memory

A significant advantage of rammappy over mappy (the official minimap2 Python bindings) is the ability to build an Index directly from in-memory sequences. In mappy, reference sequences must generally be read from a FASTA file on disk. rammappy allows you to skip the disk I/O entirely:

import rammappy

# Define reference sequences
refs = [
    (b"chr1", b"ACGT" * 1000),
    (b"chr2", b"TGCA" * 1000)
]

# Build the index completely in-memory
index = rammappy.Index.build(refs, k=15, w=10)

# Optionally save it for later use
index.save("reference.mmi")

# You can also fetch sequences directly from the index!
print(index.seq("chr1", start=0, end=10))

🔨 Instantiating an Aligner

You can create an aligner by providing the built index and a preset configuration.

# Pass the in-memory index directly to the Aligner
aligner = rammappy.Aligner(index, preset=rammappy.Preset.Sr)

🔬 Batch Alignment

Querying multiple sequences can be done via map_batch, which drops the GIL and runs in parallel using Rust's Rayon ecosystem:

queries = [
    (b"query1", b"ACGT" * 20),
    (b"query2", b"CGTA" * 20),
]

batch_results = aligner.map_batch(queries)

# Lazy-evaluate the iterator to pull hits
for i, mappings in enumerate(batch_results):
    first_hit = next(iter(mappings), None)
    if first_hit:
        print(f"Query {i+1} mapped to {first_hit.target_name.decode()} at {first_hit.target_start}")

📊 Exploring Sketchers

Direct access to seeding algorithms is available for customized genomic sketching:

sketcher = rammappy.MinimizerSketcher(kmer_len=15, window_len=10)
seed = sketcher.sketch(b"ACTG" * 50)[0]
print(f"Minimizer at position {seed.x} with y-value {seed.y}")

🏗️ Architecture & Implementation Philosophy

The overriding goal for this project was to establish extremely performant, zero-copy FFI bindings linking the Rust core API to Python. A focus was applied to maintain "bare metal Rust" speeds while providing a clean and "lazy" Python API.

graph TD
    A[Python Application] -->|Bytes & Queries| B[rammappy PyO3 FFI]
    B -->|GIL Dropped| C[Rayon Thread Pool]
    C -->|Zero-Copy Raw Pointers| D[rammap-core]
    D -->|Alignment Results| C
    C -->|Lazy Iterators| B
    B -->|Python Mapping Objects| A

Zero-Copy Evaluation Using bytes

Python strings (str) perform computationally expensive UTF-8 allocations and validation mechanisms. rammappy universally prefers Python byte-strings (bytes in Python, mapped to &[u8] in Rust). Data entering the alignment algorithm uses Bound<'py, PyBytes>, mapping directly to contiguous blocks of C-memory storing the sequences. Retrieving genomic strings mapping fields (e.g., CIGAR/MD/CS strings) exposes byte payloads directly without additional UTF-8 reallocations during FFI crossings.

In-Memory Indexing vs Disk I/O

Traditional bindings like mappy force users to write target sequences to a FASTA file before an index can be built and queried. rammappy decouples the Index from the Aligner, allowing indexes to be built dynamically from raw memory bytes inside Python, completely eliminating disk I/O bottlenecks for dynamic or programmatic reference generation.

Parallel Scaling and the Python GIL

Scaling genomic query alignments in parallel on multi-core systems mandates threading. However, the presence of the Python Global Interpreter Lock (GIL) poses problems, as normal PyO3 structures retain a lock on the main Python thread.

The Solution: We collect batches of targets mapped to pointers and lengths. We wrap these representations in a custom struct RawQuery { name_ptr, seq_ptr, ... }. We implement unsafe impl Send for RawQuery and unsafe impl Sync for RawQuery, allowing pointer transmission across thread boundaries. The GIL is then released via py.detach(|| { ... }), and rayon handles iterating and distributing alignments across all CPU cores. unsafe { std::slice::from_raw_parts } safely rebuilds the byte vectors in the isolated thread spaces, as the parent function's stack guarantees the memory allocation outlives the closure.

Lazy Materialization

Rather than computing alignment lists as heavy Vec<Mapping> aggregates and immediately converting every hit to a Python-native object (costing heavy FFI time), rammappy returns a MappingIterator. A MappingIterator acts as an opaque handle holding the vector of internal RustMapping entries. Only when a user invokes next(iterator) is the memory read and a single Python Mapping object initialized and surfaced over the FFI boundary.


👏 Acknowledgments

We would like to thank the original authors of rammap, Jeremy R. Wang and Heng Li, for their high-performance reimplementation of minimap2 in Rust.

📚 References

  1. Jeremy R. Wang and Heng Li. Memory-safe high-performance sequence mapping with rammap (2026). bioRxiv. 10.64898/2026.05.26.726289.

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

rammappy-0.1.0-cp314-cp314-macosx_11_0_arm64.whl (720.3 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

rammappy-0.1.0-cp312-cp312-win_amd64.whl (649.8 kB view details)

Uploaded CPython 3.12Windows x86-64

rammappy-0.1.0-cp312-cp312-manylinux_2_34_x86_64.whl (873.9 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

rammappy-0.1.0-cp310-abi3-win_amd64.whl (26.9 kB view details)

Uploaded CPython 3.10+Windows x86-64

rammappy-0.1.0-cp310-abi3-macosx_11_0_arm64.whl (26.9 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file rammappy-0.1.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rammappy-0.1.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5f48bd0182051f99c1d68467ac7ca535688a6ade9f37799294f36ddf1e916b45
MD5 23b1d219217cb3dbdc128035afd1249c
BLAKE2b-256 ccbe158ba86350eb58914ff40e9cf19df679e56fadf1acfb2ede60258518c9a3

See more details on using hashes here.

Provenance

The following attestation bundles were made for rammappy-0.1.0-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: publish.yml on tomdstanton/rammappy

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

File details

Details for the file rammappy-0.1.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: rammappy-0.1.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 649.8 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rammappy-0.1.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 617dd4917754aefea70d2a92adf208a7ae45436bbce0c74dddc45022e4f8febe
MD5 c28a79803af0738a76b08456ba75b2a9
BLAKE2b-256 0899190c5e1b4a9d1f7a5b306f3b232377672c0fd51b2a110ad1d03f423c136b

See more details on using hashes here.

Provenance

The following attestation bundles were made for rammappy-0.1.0-cp312-cp312-win_amd64.whl:

Publisher: publish.yml on tomdstanton/rammappy

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

File details

Details for the file rammappy-0.1.0-cp312-cp312-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for rammappy-0.1.0-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 58cd69e22439686604d21728008bfbf5379c88cdf3dc5550c9f3b57cf9bb15e9
MD5 f7717b15ebbfd6fddd7ecf2ffb9c65a8
BLAKE2b-256 a4da63bcb884c4471d8131a29b324f05c1823e7d722030acda93bc4c4920e901

See more details on using hashes here.

Provenance

The following attestation bundles were made for rammappy-0.1.0-cp312-cp312-manylinux_2_34_x86_64.whl:

Publisher: publish.yml on tomdstanton/rammappy

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

File details

Details for the file rammappy-0.1.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: rammappy-0.1.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 26.9 kB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rammappy-0.1.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 8d35c4a41ae6b40c60c2a42d2dc13befad636fbe997b9ca184400f853a0420f4
MD5 819106935b62715a90a6a1aa1077b09f
BLAKE2b-256 642e04252ec27e25a35d9ebf4105a7f704373ff6bee6ebef8567fea17e157d54

See more details on using hashes here.

Provenance

The following attestation bundles were made for rammappy-0.1.0-cp310-abi3-win_amd64.whl:

Publisher: publish.yml on tomdstanton/rammappy

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

File details

Details for the file rammappy-0.1.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rammappy-0.1.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a7df797356b24584f89f99fb35376d4d8e010dc588248b2bdbd73e421a862856
MD5 a36e659908378acf4b5b430a2dcd31c2
BLAKE2b-256 42be5dd25f145dba7c12df1ea81457b195da50382123398c232ab5bffdbba65f

See more details on using hashes here.

Provenance

The following attestation bundles were made for rammappy-0.1.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on tomdstanton/rammappy

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