spearfish (Python)
Python bindings for spearfish, a fast long-read
RNA-seq mapper to the transcriptome. Load or build an index, make a mapper from a preset and
settings, and map reads one at a time, in batches, or straight from a FASTA/FASTQ file. The
results are the same as spearfish map's: every reported transcript per read, best first, with
its score and spans.
Install
From a checkout (Rust 1.89 or newer and maturin):
cd crates/py-spearfish
pip install . # or, while developing: maturin develop --release
One wheel serves CPython 3.9 and later (the stable ABI). NumPy is required; pandas is
optional, for to_pandas().
Quick start
import spearfish
index = spearfish.Index.load("transcripts.sfi") # written by `spearfish index`
mapper = spearfish.Mapper(index, "ont") # preset: "ont", "drna" or "hifi"
read = mapper.map("ACGT...") # one read
if read.is_mapped:
hit = read.best
print(hit.transcript, hit.gene, hit.strand, hit.score,
hit.query_start, hit.query_end, hit.target_start, hit.target_end)
for batch in mapper.map_file("reads.fq.gz"): # a whole file, read and mapped in Rust
df = batch.to_pandas() # one row per hit, like the CLI's TSV
Indexes
index = spearfish.Index.load("transcripts.sfi") # memory-mapped
# Build from a FASTA (optionally compressed). GENCODE headers (tx|gene|...) give genes.
index = spearfish.Index.build("gencode.transcripts.fa.gz", threads=16) # in memory
index = spearfish.Index.build("gencode.transcripts.fa.gz", "gencode.sfi") # to a file
# ... or from sequences: a dict, or (name, seq) / (name, gene, seq) tuples.
index = spearfish.Index.build([("tx1", "gene1", "ACGT..."), ("tx2", "gene1", "ACGG...")])
# Genes from a table, or inferred from shared sequence when there are none.
index = spearfish.Index.build("transcripts.fa", t2g="t2g.tsv") # or a dict {tx: gene}
index = spearfish.Index.build("transcripts.fa", infer_genes=True)
Index.build takes the options of spearfish index: scheme, hpc, mask_genes,
collapse, threads, and allow_collisions. An index tells you about itself:
num_transcripts, num_genes, transcript_names(), transcript_lengths(),
transcript_gene(i), gene_names(), transcript_id(name), scheme, hpc, id, manifest
(what built it and from what), and build_report (construction statistics, for an index built
in this process).
Mappers, presets and settings
mapper = spearfish.Mapper(index, "hifi")
mapper = spearfish.Mapper(index, "ont", extend_ends=True, tie_kappa=5.0, threads=8)
mapper = index.mapper("drna") # the same thing
The preset sets every default. Keyword arguments change single settings, as spearfish map's
flags do: spearfish.SETTINGS lists them, and None keeps the preset's value. An unknown
setting raises TypeError; an invalid value, or settings that contradict each other, raise
ValueError. Settings that have no effect, such as tie-break settings with tiebreak=False, are
logged as warnings through Python's logging module, under the spearfish logger.
mapper.settings # what you changed
mapper.options # every parameter the mapper runs with
spearfish.resolve_settings("hifi", extend_ends=True) # the same, without an index
Most settings are numbers or booleans. A few take strings:
strands:"both","fwd"or"rev".rescue_window:"full","PAD,DIV"or(pad, div).chainer:"oracle","refine"or("refine", beam).
Mapping
| Call | Input | Returns | Use it for |
|---|---|---|---|
mapper.map(seq, name=None) |
one sequence (str or bytes) |
MappedRead |
interactive use, a few reads |
mapper.map_batch(seqs, names=None) |
an iterable of sequences | MappingBatch |
reads already in memory |
mapper.map_records(records, chunk_size=20000) |
an iterable of sequences or (name, seq, ...) tuples, as mappy.fastx_read and pyfastx give them |
iterator of MappingBatch |
streams from other readers |
mapper.map_file(path, chunk_size=20000) |
a FASTA/FASTQ file (plain, gzip, bzip2 or zstd; "-" for stdin) |
iterator of MappingBatch |
whole files |
Results come back in input order. A MappedRead has the following fields:
nameandlength;hits(a tuple ofHit, best first) andbest;is_mapped,low_coverageandrescued;probabilities(), the hits' relative likelihoods,exp(-(best - score) / SCORE_DENOM)normalized to sum to 1.
A Hit has the following fields:
- the transcript:
transcript,transcript_id,geneandtranscript_length; - the match:
rank,strand(orreverse) andscore; - the spans:
query_start,query_end,target_startandtarget_end, in raw bases, half-open, with query spans on the read's forward strand; - the chain:
anchors,anchored,max_discrepancyandextended.
A MappingBatch keeps its results in Rust until you ask for them:
batch[i]and iteration giveMappedReadobjects;batch.hit_columns()andbatch.read_columns()give whole columns as NumPy arrays, without creating a Python object per hit;batch.to_pandas(unmapped=False)gives one row per hit, with transcripts as a categorical column.
Writing spearfish map's formats
A batch writes exactly what spearfish map writes, through the same library code:
with open("reads.tsv", "wb") as tsv, open("reads.paf", "wb") as paf, \
spearfish.RadWriter("reads.rad", mapper) as rad:
tsv.write(spearfish.TSV_HEADER.encode())
for batch in mapper.map_file("reads.fq.gz"):
batch.write_tsv(tsv) # or batch.to_tsv() -> bytes
batch.write_paf(paf) # or batch.to_paf()
rad.write(batch) # RAD for `oarfish -a`
- TSV: one line per hit, plus one
*line per unmapped read. - PAF: unmapped reads are left out.
- Read names: reads without names are named by their position in the batch.
- Files: binary and text files both work.
- RAD:
RadWriterrecords the mapper's preset, settings and index in the file's header. It moves the file into place, with its read counts, when thewithblock ends. On an exception, or if the writer is never closed, no file is left. The codec is"lz4"(default),"zstd"or"none".
Why batches
Mapping one long read costs far more than one call from Python into Rust, so calling map per
read costs little on one thread. The difference is parallelism:
- Batch calls (
map_batch,map_records,map_file) map on the mapper's own thread pool (threads=, default every CPU), with the GIL released, and run at close tospearfish map's speed. - The iterators work ahead. While your code works on one batch from
map_fileormap_records, the next chunk is already mapping in the background.map_filealso reads and decompresses on a thread of its own. Time spent on each batch in Python (to_pandas, filtering, writing) is therefore hidden behind mapping, as long as it takes less time than mapping a chunk. mapfrom several Python threads also releases the GIL while it maps, and a mapper can be shared between threads. But building each result's Python objects needs the GIL, so this stops scaling after a few threads.
For more than a few thousand reads, use a batch call. The iterators hold a few chunks at a
time: the one you are using, the one mapping, and for map_file one being read. So memory
stays flat as long as you drop each batch when you are done with it; chunk_size sets the
scale. Columnar results (hit_columns, to_pandas) are the cheapest to consume.
Thread safety
Index and Mapper are immutable and thread-safe; share one of each across threads. The
iterators returned by map_file and map_records are meant for one consumer: if a second
thread calls next() on a map_records iterator while the first is in it, it raises
RuntimeError rather than wait.
Releases
.github/workflows/publish-python.yml builds abi3 wheels and an sdist:
- wheels for Linux x86-64 and arm64 (manylinux) and macOS (universal2);
- every wheel is tested on the platforms it serves before anything is published.
To release:
- Push a tag
py-spearfish-vX.Y.Z, whereX.Y.Zis the workspace version. - The workflow publishes to PyPI by trusted publishing.
Run by hand, the workflow builds and tests, and publishes to TestPyPI if asked.
Development
cd crates/py-spearfish
maturin develop --release
pytest tests
The tests use the toy transcriptome in fixtures/toy.
Metadata
Release files for spearfish 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| spearfish-0.1.0.tar.gz | 244.1 kB | With provenance | Details for spearfish-0.1.0.tar.gz |
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| spearfish-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details for spearfish-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
| spearfish-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ ARM64 | Details for spearfish-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
| spearfish-0.1.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.9 | abi3 | macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64 | Details for spearfish-0.1.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
Total release size: 6.5 MB
Release files / spearfish-0.1.0.tar.gz
| Download URL | spearfish-0.1.0.tar.gz |
|---|---|
| Size | 244.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e80d8c9a3c911b598255325ff918fca709ed542cc8fc2d57ad19d2fcc852f7b8
|
|
BLAKE2b-256 checksum How to use checksums |
d4cdd94b76e5256d079e8e2cc099c7181d3f13a04453480b6dce69e16173e8fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / spearfish-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | spearfish-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
806978587c03db9011ee4352f7b1cb8cb965c5eed7b0ed5a1ebef7e321c57532
|
|
BLAKE2b-256 checksum How to use checksums |
2b522f980954570aa572677a92db40835998b222f76921c7d5de72dbf573d4e4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / spearfish-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | spearfish-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
7c2e23bff3b03c0cf5c769c1c008f929b34d5b015d383633a86e49212b809c06
|
|
BLAKE2b-256 checksum How to use checksums |
ccf00a1e388dc72993b5114ff63e42cefbf8877541bdb61ec71e3e47058005dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / spearfish-0.1.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | spearfish-0.1.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 2.9 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
54b940925c65227d0eec9fcb01067ba67489af36f110a3820f0b1f65f71f0ef9
|
|
BLAKE2b-256 checksum How to use checksums |
e8e0a931ba22e4f693a777ed466d5ddfb35420dbad1137b597a44da102a737b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logSecurity for spearfish 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 4 files in this release have been uploaded with provenance metadata.
Attestation for spearfish-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.