Skip to content

kaptive.core.genome

Module for loading, parsing, and managing genomic sequence assemblies and FASTA I/O.

This module provides high-performance FASTA file reading using rammappy Rust bindings and encapsulates genome assemblies in the GenomeAssembly dataclass, supported by transparent decompression (.gz, .bz2, .xz).

Classes:

  • FastaReader –

    High-performance FASTA file iterator.

  • GenomeAssembly –

    Container for a genome assembly with support for transparent decompression.

FastaReader

FastaReader(handle: IO[bytes])

              flowchart TD
              kaptive.core.genome.FastaReader[FastaReader]

              

              click kaptive.core.genome.FastaReader href "" "kaptive.core.genome.FastaReader"
            

High-performance FASTA file iterator.

Parses raw binary FASTA streams into SeqRecord instances using optimized C/Rust bindings via rammappy. Assumes the input handle is opened in binary mode ('rb').

Parameters:

  • handle

    (IO[bytes]) –

    An open binary stream containing FASTA sequence data.

Parameters:

  • handle

    (IO[bytes]) –

    Open binary file-like object containing FASTA data.

Methods:

  • __del__ –

    Clean up resources by closing the underlying binary handle if still open.

  • __enter__ –

    Enter the runtime context for the FASTA reader.

  • __exit__ –

    Exit the runtime context and close the underlying binary stream.

  • __iter__ –

    Return the iterator object itself.

  • __next__ –

    Fetch the next sequence record from the parsed FASTA stream.

Source code in src/kaptive/core/genome.py
def __init__(self, handle: IO[bytes]) -> None:
    r"""Initialize the FASTA reader and parse the underlying stream.

    Args:
        handle (IO[bytes]): Open binary file-like object containing FASTA data.
    """
    self._handle = handle
    import rammappy

    # Read the entire stream and parse using rammappy's high-performance Rust parser
    self._parsed = rammappy.fasta.parse_fasta_bytes(self._handle.read())
    self._generator = (SeqRecord(seq=seq, id=name) for name, seq in self._parsed)

__del__

__del__() -> None

Clean up resources by closing the underlying binary handle if still open.

Source code in src/kaptive/core/genome.py
def __del__(self) -> None:
    r"""Clean up resources by closing the underlying binary handle if still open."""
    self._handle.close()

__enter__

__enter__() -> Self

Enter the runtime context for the FASTA reader.

Returns:

  • FastaReader ( Self ) –

    The current reader context manager instance.

Source code in src/kaptive/core/genome.py
def __enter__(self) -> Self:
    r"""Enter the runtime context for the FASTA reader.

    Returns:
        FastaReader: The current reader context manager instance.
    """
    return self

__exit__

__exit__(exc_type: Any, exc_val: Any, exc_tb: Any) -> None

Exit the runtime context and close the underlying binary stream.

Parameters:

  • exc_type

    (Any) –

    Exception type if an exception was raised inside context.

  • exc_val

    (Any) –

    Exception instance if an exception was raised.

  • exc_tb

    (Any) –

    Traceback object if an exception was raised.

Source code in src/kaptive/core/genome.py
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
    r"""Exit the runtime context and close the underlying binary stream.

    Args:
        exc_type (Any): Exception type if an exception was raised inside context.
        exc_val (Any): Exception instance if an exception was raised.
        exc_tb (Any): Traceback object if an exception was raised.
    """
    self._handle.close()

__iter__

__iter__() -> Self

Return the iterator object itself.

Returns:

  • Self –

    Iterator[SeqRecord]: Iterator yielding parsed SeqRecord objects.

Source code in src/kaptive/core/genome.py
def __iter__(self) -> Self:
    r"""Return the iterator object itself.

    Returns:
        Iterator[SeqRecord]: Iterator yielding parsed [`SeqRecord`][kaptive.core.seq.SeqRecord] objects.
    """
    return self

__next__

__next__() -> SeqRecord

Fetch the next sequence record from the parsed FASTA stream.

Returns:

Raises:

  • StopIteration –

    When all FASTA records have been consumed.

Source code in src/kaptive/core/genome.py
def __next__(self) -> SeqRecord:
    r"""Fetch the next sequence record from the parsed FASTA stream.

    Returns:
        SeqRecord: The next FASTA record as a [`SeqRecord`][kaptive.core.seq.SeqRecord].

    Raises:
        StopIteration: When all FASTA records have been consumed.
    """
    return next(self._generator)

GenomeAssembly dataclass

GenomeAssembly(id: str, contigs: Sequences)

Container for a genome assembly with support for transparent decompression.

Stores contig sequence data as a contiguous memory block using Sequences and supports thread-safe, lazy-cached index creation for high-performance sequence alignment.

Attributes:

  • id (str) –

    Unique genome assembly identifier.

  • contigs (Sequences) –

    Structure-of-Arrays container Sequences holding all contig sequences.

  • id_map (dict[str, int]) –

    Mapping from contig ID to sequence index offset within contigs.

  • rammappy_index (Any) –

    Lazy-cached rammappy.Index object for sequence lookups.

Methods:

  • __getitem__ –

    Retrieve raw sequence bytes for a contig by its identifier.

  • __iter__ –

    Iterate over contigs in the assembly.

  • __len__ –

    Calculate the total number of base pairs across all contigs in the assembly.

  • __post_init__ –

    Initialize derived fields such as id_map after dataclass creation.

  • __str__ –

    Return the string representation of the assembly.

  • ensure –

    Ensure the input object is coerced into a GenomeAssembly.

  • from_file –

    Load a genome assembly from a FASTA file path.

  • from_records –

    Construct a GenomeAssembly from sequence records.

  • from_stream –

    Load a genome assembly from an open binary stream.

  • get_rammappy_index –

    Lazily build and return a thread-safe cached rammappy.Index for the assembly.

__getitem__

__getitem__(item: str) -> bytes

Retrieve raw sequence bytes for a contig by its identifier.

Parameters:

  • item

    (str) –

    Contig identifier string.

Returns:

  • bytes ( bytes ) –

    Contig sequence bytes.

Raises:

  • KeyError –

    If item is not a recognized contig identifier in id_map.

Source code in src/kaptive/core/genome.py
def __getitem__(self, item: str) -> bytes:
    r"""Retrieve raw sequence bytes for a contig by its identifier.

    Args:
        item (str): Contig identifier string.

    Returns:
        bytes: Contig sequence bytes.

    Raises:
        KeyError: If `item` is not a recognized contig identifier in `id_map`.
    """
    idx = self.id_map[item]
    offset_val = self.contigs.offsets[idx]
    length_val = self.contigs.lengths[idx]
    return self.contigs.seqs[offset_val : offset_val + length_val].tobytes()

__iter__

__iter__() -> Iterator[SeqRecord]

Iterate over contigs in the assembly.

Returns:

Source code in src/kaptive/core/genome.py
def __iter__(self) -> Iterator[SeqRecord]:
    r"""Iterate over contigs in the assembly.

    Returns:
        Iterator[SeqRecord]: An iterator over [`SeqRecord`][kaptive.core.seq.SeqRecord] contigs.
    """
    return iter(self.contigs)

__len__

__len__() -> int

Calculate the total number of base pairs across all contigs in the assembly.

Returns:

  • int ( int ) –

    Cumulative sequence length in base pairs.

Source code in src/kaptive/core/genome.py
def __len__(self) -> int:
    r"""Calculate the total number of base pairs across all contigs in the assembly.

    Returns:
        int: Cumulative sequence length in base pairs.
    """
    return len(self.contigs.seqs)

__post_init__

__post_init__() -> None

Initialize derived fields such as id_map after dataclass creation.

Source code in src/kaptive/core/genome.py
def __post_init__(self) -> None:
    r"""Initialize derived fields such as `id_map` after dataclass creation."""
    object.__setattr__(self, "id_map", {name: i for i, name in enumerate(self.contigs.ids)})

__str__

__str__() -> str

Return the string representation of the assembly.

Returns:

  • str ( str ) –

    Assembly identifier string (id).

Source code in src/kaptive/core/genome.py
def __str__(self) -> str:
    r"""Return the string representation of the assembly.

    Returns:
        str: Assembly identifier string (`id`).
    """
    return self.id

ensure classmethod

ensure(genome: Self | str | Path | IO[bytes]) -> Self

Ensure the input object is coerced into a GenomeAssembly.

Parameters:

  • genome

    (Self | str | Path | IO[bytes]) –

    Existing assembly object, file path, or binary FASTA stream.

Returns:

Source code in src/kaptive/core/genome.py
@classmethod
def ensure(cls, genome: Self | str | Path | IO[bytes]) -> Self:
    r"""Ensure the input object is coerced into a [`GenomeAssembly`][kaptive.core.genome.GenomeAssembly].

    Args:
        genome (Self | str | Path | IO[bytes]): Existing assembly object, file path,
            or binary FASTA stream.

    Returns:
        GenomeAssembly: Validated or loaded [`GenomeAssembly`][kaptive.core.genome.GenomeAssembly] instance.
    """
    if isinstance(genome, cls):
        return genome
    elif isinstance(genome, (str, Path)):
        return cls.from_file(genome)
    return cls.from_stream(genome)  # type: ignore

from_file classmethod

from_file(filepath: str | Path) -> Self

Load a genome assembly from a FASTA file path.

Supports plain .fasta / .fa / .fna files as well as compressed .gz, .bz2, and .xz files.

Parameters:

  • filepath

    (str | Path) –

    Path to the target FASTA file.

Returns:

Raises:

Source code in src/kaptive/core/genome.py
@classmethod
def from_file(cls, filepath: str | Path) -> Self:
    r"""Load a genome assembly from a FASTA file path.

    Supports plain `.fasta` / `.fa` / `.fna` files as well as compressed
    `.gz`, `.bz2`, and `.xz` files.

    Args:
        filepath (str | Path): Path to the target FASTA file.

    Returns:
        GenomeAssembly: Loaded [`GenomeAssembly`][kaptive.core.genome.GenomeAssembly] instance.

    Raises:
        NotImplementedError: If the file format or compression extension is unsupported.
    """
    filepath = Path(filepath)
    if not (m := cls._SEQUENCE_FILE_REGEX.search(filepath.name)):
        raise NotImplementedError(f"Unsupported format: {filepath}")

    with cls._OPENERS.get(m.group("compression"), open)(filepath, mode="rb") as handle:
        return cls.from_stream(handle, filepath.name.removesuffix(m.group()))

from_records classmethod

from_records(id_: str, records: Iterable[SeqRecord]) -> Self

Construct a GenomeAssembly from sequence records.

Parameters:

Returns:

Source code in src/kaptive/core/genome.py
@classmethod
def from_records(cls, id_: str, records: Iterable[SeqRecord]) -> Self:
    r"""Construct a [`GenomeAssembly`][kaptive.core.genome.GenomeAssembly] from sequence records.

    Args:
        id_ (str): Genome assembly identifier.
        records (Iterable[SeqRecord]): Iterable of [`SeqRecord`][kaptive.core.seq.SeqRecord] objects.

    Returns:
        GenomeAssembly: Constructed [`GenomeAssembly`][kaptive.core.genome.GenomeAssembly] instance.
    """
    return cls(id_, Sequences.from_records(list(records)))

from_stream classmethod

from_stream(handle: IO[bytes], id_: str | None = None) -> Self

Load a genome assembly from an open binary stream.

Parameters:

  • handle

    (IO[bytes]) –

    Open binary FASTA stream handle.

  • id_

    (str | None, default: None ) –

    Custom assembly identifier. If None, derived from handle name or defaults to 'unknown'.

Returns:

Source code in src/kaptive/core/genome.py
@classmethod
def from_stream(cls, handle: IO[bytes], id_: str | None = None) -> Self:
    r"""Load a genome assembly from an open binary stream.

    Args:
        handle (IO[bytes]): Open binary FASTA stream handle.
        id_ (str | None): Custom assembly identifier. If None, derived from
            handle name or defaults to `'unknown'`.

    Returns:
        GenomeAssembly: Loaded [`GenomeAssembly`][kaptive.core.genome.GenomeAssembly] instance.
    """
    with FastaReader(handle) as records:
        return cls.from_records(id_ or getattr(handle, "name", "unknown"), records)

get_rammappy_index

get_rammappy_index() -> Any

Lazily build and return a thread-safe cached rammappy.Index for the assembly.

Returns:

  • Any ( Any ) –

    The compiled rammappy.Index instance.

Source code in src/kaptive/core/genome.py
def get_rammappy_index(self) -> Any:
    r"""Lazily build and return a thread-safe cached `rammappy.Index` for the assembly.

    Returns:
        Any: The compiled `rammappy.Index` instance.
    """
    if self.rammappy_index is None:
        with self._index_lock:
            if self.rammappy_index is None:
                import rammappy

                contig_seqs = [(c.id.encode(), c.seq) for c in self.contigs]
                idx = rammappy.Index.build(contig_seqs)
                object.__setattr__(self, "rammappy_index", idx)
    return self.rammappy_index