Data access#
The rotifer.db package gives every biological data source the same
cursor interface: dictionary-style access for one entry
(cursor[accession]), lazy iteration for large queries
(fetchone), and bulk retrieval (fetchall). Cursors track which
identifiers could not be resolved, retry recoverable failures, and
can delegate to one another, so a query first checks fast local
resources and only then reaches remote services. This page is the
curated entry point; the generated API pages linked below hold the
full reference and are the template for documenting other ROTIFER
modules.
Modules#
High level delegators for sequences, genomes, feature tables, gene neighborhoods, IPG reports and taxonomy.
E-utilities backends: EFetch and ELink access to every NCBI database.
Checksum verified genome downloads from the NCBI FTP site.
The same genome cursors, served from a local mirror of the NCBI genomes repository.
Fast sequence retrieval from FASTA files indexed with Easel’s esl-sfetch.
NCBI Taxonomy lineages from the local ETE toolkit database.
Gene neighborhoods and IPG reports from local SQLite3 stores.
Identifier mapping through the UniProt REST API, with AlphaFold DB and PDB structure links.
The base classes behind every cursor: batching, retries, delegation and missing entry bookkeeping.
Quickstart#
Every snippet below downloads live data, so run them on a machine with network access. Cursors accept single accessions or any iterable of accessions.
Fetch annotated protein records from NCBI:
from rotifer.db import ncbi
sc = ncbi.SequenceCursor(database="protein")
records = sc.fetchall(["YP_009724395.1", "WP_063732599.1"])
for rec in records:
print(rec.id, rec.description)
Download whole genomes, or just their feature tables, by assembly accession:
from rotifer.db import ncbi
gfc = ncbi.GenomeFeaturesCursor(progress=True)
df = gfc.fetchall(["GCA_018744545.1", "GCA_901308185.1"])
print(df.groupby("assembly").pid.nunique())
Fetch the genomic region around the genes encoding target proteins:
from rotifer.db import ncbi
gnc = ncbi.GeneNeighborhoodCursor(before=5, after=5, progress=True)
df = gnc.fetchall(["WP_012291365.1", "WP_013208129.1"])
print(df[df["query"] == 1].filter(["pid", "block_id", "assembly"]))
Resolve NCBI Taxonomy identifiers to named lineages, using the local ETE toolkit database first:
from rotifer.db import ncbi
tc = ncbi.TaxonomyCursor()
taxa = tc.fetchall([2599, 562])
print(taxa.filter(["taxid", "organism", "lineage"]))
Fetch sequences from an esl-sfetch indexed FASTA file, without touching the network:
from rotifer.db.local import easel
fc = easel.FastaCursor("/databases/fadb/nr/nr")
seqs = fc.fetchall(["WP_063732599.1"])
Map GenBank CDS accessions to UniProtKB and collect AlphaFold DB structure links:
from rotifer.db.uniprot.webapi import idmapping
links = idmapping.AF_link(["BAE76179.1", "AAC73502.1"])
print(links.filter(["From", "Entry", "urlAF"]))
Supported databases#
The table is sortable and searchable. “Network” marks resources that contact a remote service at query time.
Resource |
Module |
Entry points |
Identifier types |
Network |
Cached |
|---|---|---|---|---|---|
NCBI Entrez (E-utilities) |
SequenceCursor, FastaCursor, IPGCursor, TaxonomyCursor, NucleotideFeaturesCursor, GeneNeighborhoodCursor, elink |
protein, nucleotide and taxonomy accessions |
yes |
no |
|
NCBI FTP genomes |
connection, GenomeCursor, GenomeFeaturesCursor, GeneNeighborhoodCursor |
assembly accessions (GCA_, GCF_) |
yes |
downloads pass through the cache directory |
|
NCBI genome mirror |
GenomeCursor, GenomeFeaturesCursor, GeneNeighborhoodCursor |
assembly accessions (GCA_, GCF_) |
no |
reads a local mirror tree |
|
Indexed FASTA files (Easel) |
FastaCursor |
sequence accessions |
no |
builds .ssi indices on first use |
|
NCBI Taxonomy (ETE toolkit) |
TaxonomyCursor |
taxonomy identifiers |
no, after the first ete3 setup |
local SQLite copy of the taxonomy dump |
|
SQLite3 stores |
GeneNeighborhoodCursor, IPGCursor |
protein accessions |
no |
the database file itself |
|
UniProt REST API |
genbank_to_uniprot, AF_link, af_to_seq |
EMBL/GenBank/DDBJ CDS and UniProtKB accessions |
yes |
no |
|
NCBI delegators |
SequenceCursor, FastaCursor, GenomeCursor, GenomeFeaturesCursor, GeneNeighborhoodCursor, IPGCursor, TaxonomyCursor, assemblies |
mixed, backend dependent |
only when local backends miss |
through the local backends |
Tuning#
Batching, threads and retries
Every remote cursor accepts batch_size (accessions per request),
threads (parallel workers) and tries (attempts per batch).
Entrez cursors cap threads at 3 without an NCBI API key and at 10
with one; set the NCBI_API_KEY environment variable to raise the
cap. When batch_size is unset, the input is divided evenly among
the workers.
Giving up on unrecoverable errors
Cursors keep a giveup set of error message substrings. An error
matching any of them marks the affected accessions as unrecoverable
and stops further attempts. Gene neighborhood cursors give up on
HTTP 400 responses, on proteins without IPG reports and, unless
eukaryotes=True, on eukaryotic genomes.
Local mirrors and SQLite acceleration
ncbi.GeneNeighborhoodCursor accepts mirror (one path or a list
of paths to local NCBI genome mirrors) and save (a SQLite3
database of previously processed neighborhoods). Both are queried
before any remote source. The mirror entry of the NCBI
configuration file makes the mirror the default for every genome
cursor.
Inspecting failures
After any fetch, cursor.missing is a dataframe of unresolved
accessions with the last error message and whether a retry could
succeed. missing_ids(retry=True) lists the accessions worth
retrying; remove_missing() clears the registry.
Common patterns#
Fetch protein sequences with a local first, remote second strategy:
import rotifer.db as rdb
seqs = rdb.proteins(
["WP_063732599.1", "YP_009724395.1"],
methods=["esl_sfetch", "entrez"],
)
Collect gene neighborhoods for many proteins, reusing one IPG download:
from rotifer.db import ncbi
query = ["WP_012291365.1", "WP_013208129.1", "WP_122330970.1"]
ic = ncbi.IPGCursor(progress=True)
ipgs = ic.fetchall(query)
gnc = ncbi.GeneNeighborhoodCursor(progress=True)
df = gnc.fetchall(query, ipgs=ipgs)
Stream large genome sets instead of holding them all in memory:
from rotifer.db import ncbi
gfc = ncbi.GenomeFeaturesCursor(progress=True)
for table in gfc.fetchone(assembly_list):
table[table.type == "CDS"].to_csv("cds.tsv", sep="\t", mode="a")
Annotate an assembly report with taxonomy and check what failed:
from rotifer.db import ncbi
reports = ncbi.assemblies(targets=["refseq"])
tc = ncbi.TaxonomyCursor()
taxa = tc.fetchall(reports.taxid.unique().tolist())
print(tc.missing)
Attach AlphaFold models to a sequence object:
from rotifer.db.uniprot.webapi import idmapping
with_structures = idmapping.af_to_seq(seqobj)