Skip to content

API Reference

Asaf Zorea edited this page Jan 25, 2026 · 1 revision

API Reference

Module: fastaccess

Classes

FastaStore

High-level interface for indexed FASTA file access with caching.

from fastaccess import FastaStore

FastaStore(path, use_cache=True, cache_dir=None)

Initialize a FastaStore and build or load the index.

Parameters:

  • path (str): Path to the FASTA file (.fa, .fasta, .fa.gz, .fasta.gz)
  • use_cache (bool, optional): If True, save/load index from .fidx cache file. Default: True
  • cache_dir (str, optional): Custom directory for cache file. If None, uses same directory as FASTA. Useful when FASTA directory is read-only. Default: None

Raises:

  • FileNotFoundError: If FASTA file doesn't exist
  • IOError: If FASTA file cannot be read

Example:

# Basic usage
fa = FastaStore("genome.fa")

# Disable caching
fa = FastaStore("genome.fa", use_cache=False)

# Custom cache directory
fa = FastaStore("/readonly/genome.fa", cache_dir="/tmp/cache")

Instance Methods

fetch(name, start, stop, reverse_complement=False)

Fetch a single subsequence using 1-based inclusive coordinates.

Parameters:

  • name (str): Sequence name (from FASTA header, without '>')
  • start (int): Start position (1-based, inclusive)
  • stop (int): Stop position (1-based, inclusive)
  • reverse_complement (bool, optional): If True, return reverse complement. Default: False

Returns:

  • str: Uppercase string containing the requested subsequence

Raises:

  • KeyError: If sequence name not found in index
  • ValueError: If coordinates are invalid:
    • start < 1
    • stop < start
    • stop > sequence_length

Example:

seq = fa.fetch("chr1", 1000, 2000)
print(len(seq))  # 1001 (inclusive range)

# Reverse complement
rc = fa.fetch("chr1", 1000, 2000, reverse_complement=True)

Coordinate System:

1-based inclusive (standard bioinformatics):

  • fetch("chr1", 1, 100) returns 100 bases
  • fetch("chr1", 100, 100) returns 1 base

fetch_many(queries)

Fetch multiple subsequences in batch.

Parameters:

  • queries (List[Tuple[str, int, int]]): List of (name, start, stop) tuples

Returns:

  • List[str]: List of uppercase strings, one for each query in order

Raises:

  • KeyError: If any sequence name not found
  • ValueError: If any coordinates are invalid

Example:

queries = [
    ("chr1", 1000, 2000),
    ("chr2", 500, 600),
    ("chr3", 100, 150),
]
sequences = fa.fetch_many(queries)
# Returns list of 3 sequences

Performance: Uses C++ batch fetch when available for better performance.


list_sequences()

Get a list of all sequence names in the FASTA file.

Returns:

  • List[str]: List of sequence names in the order they appear in the FASTA

Example:

names = fa.list_sequences()
print(names)  # ["chr1", "chr2", ..., "chrX", "chrY"]

get_length(name)

Get the length of a sequence.

Parameters:

  • name (str): Sequence name

Returns:

  • int: Length of the sequence in bases

Raises:

  • KeyError: If sequence name not found

Example:

length = fa.get_length("chr1")
print(f"chr1 is {length:,} bp long")

get_description(name)

Get the description text from a sequence header.

Parameters:

  • name (str): Sequence name

Returns:

  • str: Description text (everything after the name in the FASTA header line)

Raises:

  • KeyError: If sequence name not found

Example:

desc = fa.get_description("chr1")
# For ">chr1 Homo sapiens chromosome 1"
# Returns "Homo sapiens chromosome 1"

get_info(name)

Get all metadata for a sequence.

Parameters:

  • name (str): Sequence name

Returns:

  • dict: Dictionary with keys:
    • name (str): Sequence name
    • description (str): Header description
    • length (int): Sequence length in bases

Raises:

  • KeyError: If sequence name not found

Example:

info = fa.get_info("chr1")
print(info)
# {'name': 'chr1', 'description': '...', 'length': 248956422}

rebuild_index()

Force rebuild of the index and update cache.

Returns:

  • None

Example:

# FASTA file was modified, rebuild index
fa.rebuild_index()

Note: This is rarely needed as index is automatically rebuilt if FASTA modification time changes.


is_cached()

Check if this instance was loaded from cache.

Returns:

  • bool: True if loaded from cache, False if index was built

Example:

if fa.is_cached():
    print("Loaded from cache (fast)")
else:
    print("Built new index (slower)")

cache_exists()

Check if a cache file exists for this FASTA.

Returns:

  • bool: True if cache file exists

Example:

if fa.cache_exists():
    print(f"Cache file: {fa.get_cache_path()}")

get_cache_path()

Get the path to the cache file.

Returns:

  • str: Absolute path to .fidx cache file

Example:

print(fa.get_cache_path())
# /path/to/genome.fa.fidx

delete_cache()

Delete the cache file if it exists.

Returns:

  • bool: True if cache was deleted, False if it didn't exist or couldn't be deleted

Example:

if fa.delete_cache():
    print("Cache deleted successfully")

Module Functions

using_cpp_backend()

Check if the C++ backend is active.

Returns:

  • bool: True if C++ backend is being used, False if pure Python

Example:

from fastaccess import using_cpp_backend

if using_cpp_backend():
    print("C++ backend active - optimal performance")
else:
    print("Python backend active")

Data Structures

Internal: Entry (dataclass)

Index entry for a sequence. Not directly exposed in API but used internally.

Fields:

  • name (str): Sequence identifier
  • description (str): Header description text
  • length (int): Total sequence length in bases
  • line_blen (int): Bases per line (0 for unwrapped)
  • line_len (int): Bytes per line including newlines
  • offset (int): Byte offset to first base in file

Type Hints

from typing import List, Tuple

# Method signatures
def fetch(name: str, start: int, stop: int,
          reverse_complement: bool = False) -> str: ...

def fetch_many(queries: List[Tuple[str, int, int]]) -> List[str]: ...

def list_sequences() -> List[str]: ...

def get_length(name: str) -> int: ...

def get_description(name: str) -> str: ...

def get_info(name: str) -> dict: ...

Exceptions

KeyError

Raised when a sequence name is not found in the index.

try:
    seq = fa.fetch("chr99", 1, 100)
except KeyError as e:
    print(f"Sequence not found: {e}")

ValueError

Raised when coordinates are invalid.

Invalid coordinate conditions:

  • Start position < 1
  • Stop position < start position
  • Stop position > sequence length
try:
    seq = fa.fetch("chr1", -10, 100)  # Negative start
except ValueError as e:
    print(f"Invalid coordinates: {e}")

try:
    seq = fa.fetch("chr1", 2000, 1000)  # Stop < start
except ValueError as e:
    print(f"Invalid range: {e}")

try:
    seq = fa.fetch("chr1", 1, 999999999)  # Beyond sequence length
except ValueError as e:
    print(f"Out of range: {e}")

Version Information

import fastaccess

print(fastaccess.__version__)  # "0.2.1"

Backend Selection

FastAccess automatically selects the best available backend:

  1. C++ backend (if built from source) - 13x faster indexing, 14x faster reverse complement
  2. Pure Python backend (fallback) - Always available, no dependencies

Check which is active:

from fastaccess import using_cpp_backend

if using_cpp_backend():
    # C++ backend active
    pass
else:
    # Python backend active
    pass

Both backends produce identical results and share the same API.


Thread Safety

FastaStore is NOT thread-safe. Create separate instances for each thread:

from concurrent.futures import ThreadPoolExecutor
from fastaccess import FastaStore

def process_region(region):
    # Each thread creates its own instance
    fa = FastaStore("genome.fa")  # Cache makes this fast
    name, start, stop = region
    return fa.fetch(name, start, stop)

regions = [("chr1", i, i+1000) for i in range(1, 10000, 1000)]

with ThreadPoolExecutor(max_workers=4) as executor:
    results = executor.map(process_region, regions)

The .fidx cache file makes creating multiple instances very fast.


See Also