# `serogen.core`

Core Structure-of-Arrays (SoA) protocols, genomic intervals, sequence &amp; alphabet engines, k-mer/randstrobe indices, banded Smith-Waterman-Gotoh alignment, clustering, and graph models.

---

## Container Protocols (`serogen.core.collections`)

## collections

Protocol contracts and Numba kernels for Structure-of-Arrays (SoA) scalar views and batched containers.

This module defines formal protocols (`ScalarView`, `BatchedContainer`, and `RaggedArrayContainer`) and shared offset/ragged-slicing mechanics that govern high-performance, vectorized containers across SeroGen.

Classes:

| Name | Description |
| --- | --- |
| `ScalarView` | Formal structural contract for immutable scalar views into a `BatchedContainer`. |
| `BatchedContainer` | A formal contract for Structure-of-Arrays (SoA) and batched containers. |
| `RaggedArrayContainer` | A formal contract for ragged Structure-of-Arrays (SoA) containers. |

Functions:

| Name | Description |
| --- | --- |
| `lengths_to_offsets` | Compute 0-based exclusive prefix-sum offsets from a 1D array of element lengths. |
| `normalize_indices` | Normalize a slice, boolean mask, or integer index sequence into a 1D `int32` index array. |

### ScalarView

Bases: `Protocol`

Formal structural contract for immutable scalar views into a `BatchedContainer`.

All scalar views must be `@dataclass(slots=True, frozen=True)` records representing a single element extracted from a Structure-of-Arrays (SoA) batch container.

### BatchedContainer

Bases: `Protocol`

A formal contract for Structure-of-Arrays (SoA) and batched containers.

This protocol ensures that all high-performance vectorized collections provide a standard interface for instantiation, iteration, concatenation, and indexing without relying on slow dynamic mixins or runtime type introspection.

Class Type Parameters:

| Name | Bound or Constraints | Description | Default |
| --- | --- | --- | --- |
| `T` | `ScalarView` | The `ScalarView` dataclass returned when accessing a single index. | *required* |
| `S` | `BatchedContainer[Any, Any]` | The batched container type returned when indexing with slices or array masks. | *required* |

Methods:

| Name | Description |
| --- | --- |
| `empty` | Create an empty, 0-length collection with correctly typed arrays. |
| `concat` | Concatenate multiple collections into a single, larger collection. |

#### empty

```python
empty() -> Self
```

Create an empty, 0-length collection with correctly typed arrays.

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `S` | `Self` | An empty instance of the container. |

#### concat

```python
concat(batches: Iterable[Self]) -> Self
```

Concatenate multiple collections into a single, larger collection.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `batches` | `Iterable[S]` | An iterable of collections of the same type. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `S` | `Self` | A new, combined collection. |

Raises:

| Type | Description |
| --- | --- |
| `ValueError` | If the input iterable is empty or contains incompatible batches. |

### RaggedArrayContainer

Bases: `BatchedContainer[T, S]`, `Protocol`

A formal contract for ragged Structure-of-Arrays (SoA) containers.

Ragged containers store variable-length data (such as sequences, cluster members, or CIGAR operations) in a flat, contiguous memory layout, managing element boundaries using `offsets` and `lengths` arrays.

Methods:

| Name | Description |
| --- | --- |
| `lengths_to_offsets` | Compute 0-based starting offsets from a 1D `lengths` array. |

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `offsets` | `ndarray[tuple[int], dtype[int32]]` | Starting indices into the flat data array for each record. |
| `lengths` | `ndarray[tuple[int], dtype[int32]]` | Lengths of each record. |
| `indptr` | `ndarray[tuple[int], dtype[int32]]` | CSR-compatible \\((N + 1)\\)-length index pointer array (`[0, *cumsum(lengths)]`). |

#### offsets

```python
offsets: ndarray[tuple[int], dtype[int32]]
```

Starting indices into the flat data array for each record.

#### lengths

```python
lengths: ndarray[tuple[int], dtype[int32]]
```

Lengths of each record.

#### indptr

```python
indptr: ndarray[tuple[int], dtype[int32]]
```

CSR-compatible \\((N + 1)\\)-length index pointer array (`[0, *cumsum(lengths)]`).

#### lengths\_to\_offsets

```python
lengths_to_offsets(lengths: ndarray[tuple[int], dtype[int32]]) -> ndarray[tuple[int], dtype[int32]]
```

Compute 0-based starting offsets from a 1D `lengths` array.

### lengths\_to\_offsets

```python
lengths_to_offsets(lengths: ndarray[tuple[int], dtype[int32]]) -> ndarray[tuple[int], dtype[int32]]
```

Compute 0-based exclusive prefix-sum offsets from a 1D array of element lengths.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `lengths` | `ndarray[tuple[int], dtype[int32]]` | 1D array of non-negative record lengths (`int32`). | *required* |

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[int32]]` | np.ndarray\[tuple\[int\], np.dtype\[np.int32\]\]: 1D `int32` array of starting offsets. |

### normalize\_indices

```python
normalize_indices(item: slice | ndarray[Any, Any] | list[Any], n: int) -> ndarray[tuple[int], dtype[int32]]
```

Normalize a slice, boolean mask, or integer index sequence into a 1D `int32` index array.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `item` | `slice \| ndarray[Any, Any] \| list[Any]` | Slice, boolean mask array, or integer index sequence/array. | *required* |
| `n` | `int` | Total number of records in the target container. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[int32]]` | np.ndarray\[tuple\[int\], np.dtype\[np.int32\]\]: Resolved 0-based `int32` indices. |

---

## Genomic Intervals (`serogen.core.interval`)

## interval

Genomic interval representation, strand orientations, and vectorized Structure-of-Arrays operations.

This module provides discrete coordinate intervals via `Interval`, strand representations via `Strand`, and high-performance, vectorized interval collections via `Intervals`.

Classes:

| Name | Description |
| --- | --- |
| `Strand` | Integer representation of genomic strand orientation. |
| `Interval` | A single 0-based, half-open genomic interval with strand orientation. |
| `Intervals` | A high-performance Structure-of-Arrays (SoA) collection of genomic intervals. |

### Strand

Bases: `IntEnum`

Integer representation of genomic strand orientation.

Supports conversion from common string formats (`'+'`, `'-'`, `'1'`, `'-1'`).

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `FORWARD` | `int` | Forward strand (`+1`). |
| `REVERSE` | `int` | Reverse strand (`-1`). |
| `UNSTRANDED` | `int` | Unstranded or unknown orientation (`0`). |

### Interval

A single 0-based, half-open genomic interval with strand orientation.

Represents a discrete sequence segment defined by `start` (inclusive), `end` (exclusive), and `strand` orientation.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `start` | `int` | 0-based starting position (inclusive). |
| `end` | `int` | 0-based ending position (exclusive). |
| `strand` | `Strand` | Strand orientation `Strand`. |

### Intervals

Bases: `BatchedContainer[Interval, 'Intervals']`

A high-performance Structure-of-Arrays (SoA) collection of genomic intervals.

Stores starts, ends, and strands as parallel 1D NumPy arrays for memory-efficient vectorized operations and Numba spatial algorithms.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `starts` | `ndarray[tuple[int], dtype[int32]]` | 1D array of 0-based start coordinates. |
| `ends` | `ndarray[tuple[int], dtype[int32]]` | 1D array of 0-based end coordinates. |
| `strands` | `ndarray[tuple[int], dtype[int8]]` | 1D array of strand values (+1, -1, 0). |

Methods:

| Name | Description |
| --- | --- |
| `empty` | Create an empty `Intervals` object with zero-length arrays. |
| `concat` | Concatenate multiple `Intervals` collections into a single batch. |

#### lengths

```python
lengths: ndarray[tuple[int], dtype[int32]]
```

Compute the lengths of all intervals in base pairs (`ends - starts`).

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[int32]]` | np.ndarray\[tuple\[int\], np.dtype\[np.int32\]\]: 1D array of interval lengths. |

#### empty

```python
empty() -> Self
```

Create an empty `Intervals` object with zero-length arrays.

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Intervals` | `Self` | Empty `Intervals` collection. |

#### concat

```python
concat(batches: Iterable[Self]) -> Self
```

Concatenate multiple `Intervals` collections into a single batch.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `batches` | `Iterable[Intervals]` | Iterable of `Intervals` objects to merge. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Intervals` | `Self` | Concatenated `Intervals` collection. |

Raises:

| Type | Description |
| --- | --- |
| `ValueError` | If `batches` is empty. |

---

## Genome Assemblies &amp; FASTA I/O (`serogen.core.genome`, `serogen.core.io`)

## genome

Classes:

| Name | Description |
| --- | --- |
| `GenomeAssembly` | Container for a genome assembly with support for transparent decompression. |

### GenomeAssembly

Bases: `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:

| Name | Type | Description |
| --- | --- | --- |
| `id` | `bytes` | Unique genome assembly identifier. |

Methods:

| Name | Description |
| --- | --- |
| `ensure` | Ensure the input object is coerced into a `GenomeAssembly`. |
| `from_fasta` | Construct a GenomeAssembly directly from raw binary FASTA data. |
| `from_file` | Load a genome assembly from a FASTA file path. |
| `from_stream` | Load a genome assembly from an open binary stream. |
| `from_records` | Construct a `GenomeAssembly` from sequence records. |

#### ensure

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

Ensure the input object is coerced into a `GenomeAssembly`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `genome` | `Self \| str \| Path \| IO[bytes]` | Existing assembly object, file path, or binary FASTA stream. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `GenomeAssembly` | `Self` | Validated or loaded `GenomeAssembly` instance. |

#### from\_fasta

```python
from_fasta(data: bytes | bytearray | memoryview, id_: bytes | str = b'unknown', *, truncate_id: bool = True, uppercase: bool = True) -> Self
```

Construct a GenomeAssembly directly from raw binary FASTA data.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `data` | `bytes \| bytearray \| memoryview` | Raw binary FASTA contents. | *required* |
| `id_` | `bytes \| str` | Genome assembly identifier. | `b'unknown'` |
| `truncate_id` | `bool` | If `True`, truncates header IDs at first whitespace. | `True` |
| `uppercase` | `bool` | If `True`, normalizes sequence bytes to uppercase ASCII. | `True` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `GenomeAssembly` | `Self` | Constructed `GenomeAssembly` instance. |

#### from\_file

```python
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:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `filepath` | `str \| Path` | Path to the target FASTA file. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `GenomeAssembly` | `Self` | Loaded `GenomeAssembly` instance. |

Raises:

| Type | Description |
| --- | --- |
| `NotImplementedError` | If the file format or compression extension is unsupported. |

#### from\_stream

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

Load a genome assembly from an open binary stream.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `handle` | `IO[bytes]` | Open binary FASTA stream handle. | *required* |
| `id_` | `bytes \| str \| None` | Custom assembly identifier. If None, derived from handle name or defaults to `b'unknown'`. | `None` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `GenomeAssembly` | `Self` | Loaded `GenomeAssembly` instance. |

#### from\_records

```python
from_records(records: list[Sequence] | tuple[Sequence, ...] | Iterable[Sequence], id_: bytes | str = b'unknown') -> Self
```

Construct a `GenomeAssembly` from sequence records.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `records` | `Iterable[Sequence]` | Iterable of `Sequence` objects. | *required* |
| `id_` | `bytes \| str` | Genome assembly identifier. | `b'unknown'` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `GenomeAssembly` | `Self` | Constructed `GenomeAssembly` instance. |

## fasta

High-performance C-level and zero-copy NumPy FASTA I/O.

Classes:

| Name | Description |
| --- | --- |
| `FastaReader` | High-performance stateful FASTA stream iterator and vectorized batch loader. |

### FastaReader

Bases: `Iterator[Sequence]`

High-performance stateful FASTA stream iterator and vectorized batch loader.

Streams binary FASTA handles in chunks, splitting on `\n>` boundaries and applying C-level `bytes.translate` to yield `Sequence` instances with \\(O(1)\\) memory overhead, or loads an entire stream at once into a contiguous `Sequences` Structure-of-Arrays container via `load`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `handle` | `IO[bytes] \| BufferedIOBase \| RawIOBase` | Open binary stream (`IO[bytes]`) containing FASTA sequence data. | *required* |
| `truncate_id` | `bool` | If `True`, truncates header IDs at the first whitespace character. | `True` |
| `uppercase` | `bool` | If `True`, normalizes sequence bytes to uppercase ASCII. | `True` |
| `chunk_size` | `int` | Read buffer size in bytes for streaming iteration (default 4 MiB). | `4 * 1024 * 1024` |

Methods:

| Name | Description |
| --- | --- |
| `from_bytes` | Construct a `FastaReader` from an in-memory binary buffer. |
| `close` | Close the underlying binary stream. |
| `load` | Load the FASTA stream into memory as a contiguous `Sequences` batch. |

#### from\_bytes

```python
from_bytes(data: bytes | bytearray | memoryview, truncate_id: bool = True, uppercase: bool = True, chunk_size: int = 4 * 1024 * 1024) -> Self
```

Construct a `FastaReader` from an in-memory binary buffer.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `data` | `bytes \| bytearray \| memoryview` | Raw binary FASTA buffer (`bytes`, `bytearray`, or `memoryview`). | *required* |
| `truncate_id` | `bool` | If `True`, truncates header IDs at the first whitespace character. | `True` |
| `uppercase` | `bool` | If `True`, normalizes sequence bytes to uppercase ASCII. | `True` |
| `chunk_size` | `int` | Read buffer size in bytes for streaming iteration. | `4 * 1024 * 1024` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `FastaReader` | `Self` | Reader wrapping the binary buffer. |

#### close

```python
close() -> None
```

Close the underlying binary stream.

#### load

```python
load() -> Sequences
```

Load the FASTA stream into memory as a contiguous `Sequences` batch.

Uses C-level `bytes.split`, `bytes.partition`, and 256-byte lookup table `bytes.translate` combined with a single `bytearray.join` allocation and zero-copy `np.frombuffer` view.

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Sequences` | Packed Structure-of-Arrays container of all parsed sequences. |

---

## Alphabets &amp; Genetic Codes (`serogen.core.seq.alphabet`)

## alphabet

ASCII-based biological alphabets, translation tables, and genetic codes.

This module provides high-performance ASCII alphabet definitions (`Alphabet`) with pre-computed 256-byte lookup tables for instant \\(O(1)\\) k-mer bit-packing and reduced alphabet transformations, alongside translation tables (`GeneticCode`) for vectorised parallel protein translation.

Classes:

| Name | Description |
| --- | --- |
| ``[`Alphabet`][serogen.core.seq.alphabet.Alphabet]`` | ASCII biological alphabet representation with dual LUTs. |
| ``[`GeneticCode`][serogen.core.seq.alphabet.GeneticCode]`` | Translation table and genetic code representation. |
| ``[`AlphabetError`][serogen.core.seq.alphabet.AlphabetError]`` | Base exception for alphabet operations. |

### AlphabetError

Bases: `ValueError`

Raised when an alphabet definition is invalid or an operation is incompatible.

### Alphabet

ASCII biological alphabet with pre-computed lookup tables and dynamic singleton caching.

Provides pre-computed 256-byte lookup tables: - `kmer_lut`: Maps ASCII characters to dense \\(\[0 \\dots K-1\]\\) integers (with unknown characters mapped to \\(K\\)) for on-the-fly rolling k-mer and syncmer bit-packing in L1 cache. - `ascii_lut`: Maps ASCII characters to canonical uppercase / reduced group representative ASCII bytes. - `complement_lut`: 256-element byte translation table for nucleotide complementation.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `symbols` | `bytes` | Canonical uppercase ASCII symbols representing distinct alphabet states. |
| `complement` | `bytes \| None` | Complemented symbols corresponding to `symbols` (for nucleotide alphabets). |
| `bits_per_char` | `int` | Exact bit width required to represent characters (\\((\\text{len}-1).\\text{bit\\\_length}()\\)). |
| `default_k` | `int` | Recommended default k-mer size for indexing. |
| `supports_canonical` | `bool` | Whether reverse-complement canonicalization is valid. |
| `kmer_lut` | `ndarray` | Read-only 256-byte array for \\(O(1)\\) dense integer mapping. |
| `ascii_lut` | `ndarray` | Read-only 256-byte array for \\(O(1)\\) ASCII normalization / reduction. |
| `complement_lut` | `ndarray \| None` | Read-only 256-byte array for nucleotide complementation. |

Methods:

| Name | Description |
| --- | --- |
| `masker` | Calculate k-mer bit-shift parameters and word mask for sequence hashing. |
| `encode` | Encode ASCII sequence bytes into dense integer values \[0..K-1\]. |
| `reduce` | Perform vectorized reduction of ASCII sequence bytes into reduced representative ASCII characters. |

#### masker

```python
masker(k: int) -> tuple[int, int, type[uint32 | uint64]]
```

Calculate k-mer bit-shift parameters and word mask for sequence hashing.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `k` | `int` | K-mer length. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `tuple[int, int, type[uint32 \| uint64]]` | tuple\[int, int, type\[np.uint32 \| np.uint64\]\]: Tuple of (bits\_per\_char, bitmask, integer\_dtype). |

#### encode

```python
encode(seq: bytes | bytearray | memoryview | ndarray[tuple[int], dtype[uint8]]) -> ndarray[tuple[int], dtype[uint8]]
```

Encode ASCII sequence bytes into dense integer values \[0..K-1\].

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `seq` | `bytes \| bytearray \| memoryview \| ndarray` | Input sequence bytes or 1D array. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[uint8]]` | np.ndarray\[tuple\[int\], np.dtype\[np.uint8\]\]: Array of dense integer indices. |

#### reduce

```python
reduce(seq: bytes | bytearray | memoryview | ndarray[tuple[int], dtype[uint8]]) -> bytes | ndarray[tuple[int], dtype[uint8]]
```

Perform vectorized reduction of ASCII sequence bytes into reduced representative ASCII characters.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `seq` | `bytes \| bytearray \| memoryview \| ndarray` | Input sequence bytes or 1D array. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `bytes \| ndarray[tuple[int], dtype[uint8]]` | bytes \| np.ndarray\[tuple\[int\], np.dtype\[np.uint8\]\]: Reduced sequence(s) in ASCII format. |

### GeneticCode

NCBI Translation Table representation for codon translation and complementation.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `table_id` | `int` | NCBI translation table integer identifier. |
| `name` | `str` | Descriptive name of the genetic code. |
| `start_codons` | `frozenset[bytes]` | Valid 3-base start codon byte triplets. |
| `stop_codons` | `frozenset[bytes]` | Valid 3-base stop codon byte triplets. |

Methods:

| Name | Description |
| --- | --- |
| `from_table` | Resolve a `GeneticCode` instance by NCBI translation table ID (`1, 4, 11, 15, 25`) or name. |
| `is_coding` | Check if a nucleotide sequence starts with a valid start codon and ends with a stop codon. |
| `translate` | Translate a single nucleotide sequence into an ASCII protein sequence. |
| `translate_ragged` | Translate a ragged batch of nucleotide sequences in parallel. |

#### from\_table

```python
from_table(table: int | str | GeneticCode) -> GeneticCode
```

Resolve a `GeneticCode` instance by NCBI translation table ID (`1, 4, 11, 15, 25`) or name.

#### is\_coding

```python
is_coding(seq: bytes) -> bool
```

Check if a nucleotide sequence starts with a valid start codon and ends with a stop codon.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `seq` | `bytes` | Nucleotide sequence to check. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `bool` | `bool` | True if length \>= 3 and starts with a valid start codon and ends with a stop codon. |

#### translate

```python
translate(seq: bytes | bytearray | memoryview | ndarray[tuple[int], dtype[uint8]], frame: int = 0, to_stop: bool = False) -> ndarray[tuple[int], dtype[uint8]]
```

Translate a single nucleotide sequence into an ASCII protein sequence.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `seq` | `bytes \| bytearray \| memoryview \| ndarray` | Input nucleotide sequence. | *required* |
| `frame` | `int` | Reading frame offset (0, 1, or 2). Defaults to 0. | `0` |
| `to_stop` | `bool` | If True, truncates translation at the first stop codon (\*). Defaults to False. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[uint8]]` | np.ndarray\[tuple\[int\], np.dtype\[np.uint8\]\]: Translated protein sequence in ASCII format. |

#### translate\_ragged

```python
translate_ragged(seqs: ndarray[tuple[int], dtype[uint8]], offsets: ndarray[tuple[int], dtype[int32]], lengths: ndarray[tuple[int], dtype[int32]], frames: ndarray[tuple[int], dtype[int8]] | None = None, to_stop: bool = False) -> tuple[ndarray[tuple[int], dtype[uint8]], ndarray[tuple[int], dtype[int32]], ndarray[tuple[int], dtype[int32]]]
```

Translate a ragged batch of nucleotide sequences in parallel.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `seqs` | `ndarray[tuple[int], dtype[uint8]]` | Concatenated nucleotide sequence bytes. | *required* |
| `offsets` | `ndarray[tuple[int], dtype[int32]]` | Start offsets per sequence. | *required* |
| `lengths` | `ndarray[tuple[int], dtype[int32]]` | Sequence lengths. | *required* |
| `frames` | `ndarray[tuple[int], dtype[int8]] \| None` | Reading frame offsets (0, 1, or 2) per sequence. | `None` |
| `to_stop` | `bool` | If True, truncates translation at the first stop codon (\*). Defaults to False. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `tuple[ndarray[tuple[int], dtype[uint8]], ndarray[tuple[int], dtype[int32]], ndarray[tuple[int], dtype[int32]]]` | tuple\[np.ndarray, np.ndarray, np.ndarray\]: Tuple of (out\_seqs, out\_offsets, out\_lengths) arrays. |

---

## Sequence Containers (`serogen.core.seq.seq`)

## seq

Biological sequence data structures, SoA containers, and translation utilities.

This module provides high-performance data structures for storing, manipulating, and translating biological sequences (DNA, RNA, protein). Sequences are stored either as individual immutable `Sequence` instances or as contiguous, flat arrays in `Sequences` Structure-of-Arrays (SoA) containers.

**Key Classes**

- `Sequence`: Immutable container for a single sequence record.
- `Sequences`: Memory-efficient, Numba-accelerated SoA container.
- `GeneticCode`: NCBI genetic code translator.

Classes:

| Name | Description |
| --- | --- |
| `Sequence` | A simple, immutable container for a single biological sequence. |
| `Sequences` | A high-performance SoA container for biological sequences. |
| `BacterialTranslationTable` | NCBI Translation Table 11 utilities for bacterial codon translation and complementation. |

### Sequence

A simple, immutable container for a single biological sequence.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `id` | `bytes` | Unique identifier or name of the sequence. |
| `seq` | `bytes` | Raw sequence data (e.g. DNA, RNA, or protein). |

Methods:

| Name | Description |
| --- | --- |
| `to_fasta` | Format the sequence record as a standard FASTA byte string. |
| `translate` | Translate a nucleotide sequence into a protein sequence using the specified genetic code. |

#### to\_fasta

```python
to_fasta() -> bytes
```

Format the sequence record as a standard FASTA byte string.

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `bytes` | `bytes` | FASTA formatted byte representation of the record. |

#### translate

```python
translate(code: GeneticCode = bacterial, frame: int = 0, to_stop: bool = False) -> Sequence
```

Translate a nucleotide sequence into a protein sequence using the specified genetic code.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `code` | `GeneticCode` | Genetic code translation table to use. Defaults to `GeneticCode.bacterial`. | `bacterial` |
| `frame` | `int` | Reading frame offset (0, 1, or 2). Defaults to 0. | `0` |
| `to_stop` | `bool` | If True, truncates translation at the first stop codon (\*). Defaults to False. | `False` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequence` | `Sequence` | New sequence record containing the translated protein sequence. |

### Sequences

Bases: `RaggedArrayContainer['Sequence', 'Sequences']`

A high-performance SoA container for biological sequences.

Stores multiple sequences in a flat, contiguous memory layout using a 1D NumPy array of unsigned 8-bit integers (`np.uint8`). Individual sequences are accessed via parallel arrays of offsets and lengths.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `ids` | `ndarray` | 1D byte string array of identifiers for each sequence. |
| `seqs` | `ndarray` | Single flat 1D array containing all sequence byte data concatenated. |
| `offsets` | `ndarray` | 1D array of start indices in `seqs`. |
| `lengths` | `ndarray` | 1D array of sequence lengths. |

Methods:

| Name | Description |
| --- | --- |
| `to_fasta` | Format the entire batch as a single FASTA byte string. |
| `empty` | Create an empty Sequences object with zero-length arrays. |
| `concat` | Concatenate multiple Sequences containers into a single larger collection. |
| `unique` | Return a new Sequences container containing only unique sequences. |
| `index_of` | Return the integer index or 1D index array corresponding to the given identifier(s). |
| `by_ids` | Fetch sequence record(s) matching the specified identifier(s). |
| `from_bytes` | Construct Sequences from a collection of raw sequence byte strings. |
| `from_records` | Construct Sequences from a collection of Sequence objects. |
| `extract` | Vectorized sub-sequence extraction from the batch. |
| `encode` | Encode sequence bytes into dense integer values \[0..K-1\] according to the given Alphabet. |
| `reduce` | Vectorized reduction of sequence characters using a reduced Alphabet. |
| `translate` | Vectorized translation of nucleotide sequences into protein sequences. |

#### internal\_stops

```python
internal_stops: ndarray
```

Vectorized check for internal stop codons in protein sequences.

Scans each sequence for the stop codon character ('\*') before the final position using a Numba kernel.

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | np.ndarray: A 1D boolean array where True indicates presence of an internal stop. |

#### to\_fasta

```python
to_fasta(use_indices: bool = False) -> bytes
```

Format the entire batch as a single FASTA byte string.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `use_indices` | `bool` | If True, uses 0-based integer index as FASTA header (`>0`, `>1`, ...) instead of byte string `ids`. Defaults to False. | `False` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `bytes` | `bytes` | Complete FASTA-formatted byte string containing all sequences. |

#### empty

```python
empty() -> Self
```

Create an empty Sequences object with zero-length arrays.

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Self` | An empty sequences container. |

#### concat

```python
concat(batches: Iterable[Self]) -> Self
```

Concatenate multiple Sequences containers into a single larger collection.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `batches` | `Iterable[Sequences]` | An iterable of sequence batches to combine. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Self` | A combined sequences container. |

#### unique

```python
unique() -> Sequences
```

Return a new Sequences container containing only unique sequences.

Uses a Numba-accelerated 64-bit FNV-1a hash to identify unique sequences while preserving first-occurrence order.

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Sequences` | A new container with duplicate sequences removed. |

#### index\_of

```python
index_of(query_ids: ndarray[tuple[int], dtype[bytes_]] | bytes | bytes_ | Iterable[bytes]) -> ndarray[tuple[int], dtype[int32]] | int
```

Return the integer index or 1D index array corresponding to the given identifier(s).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `query_ids` | `ndarray[bytes_] \| bytes \| bytes_ \| Iterable[bytes]` | Single sequence ID or array/iterable of IDs. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[int32]] \| int` | np.ndarray \| int: Integer index for scalar queries or 1D array of indices for batch queries. |

Raises:

| Type | Description |
| --- | --- |
| `KeyError` | If any requested sequence identifier is not found. |

#### by\_ids

```python
by_ids(query_ids: ndarray[tuple[int], dtype[bytes_]] | bytes | bytes_ | Iterable[bytes]) -> Sequence | Sequences
```

Fetch sequence record(s) matching the specified identifier(s).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `query_ids` | `ndarray[bytes_] \| bytes \| bytes_ \| Iterable[bytes]` | Single sequence ID or 1D array/iterable of IDs. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `Sequence \| Sequences` | Sequence \| Sequences: A scalar `Sequence` if a single byte identifier is passed, or a sub-`Sequences` batch matching the query IDs in order. |

Raises:

| Type | Description |
| --- | --- |
| `KeyError` | If any requested sequence identifier is not found in the container. |

#### from\_bytes

```python
from_bytes(seqs: list[bytes] | tuple[bytes, ...] | Iterable[bytes], ids: tuple[bytes, ...] | ndarray[tuple[int], dtype[bytes_]] | list[bytes] | None = None) -> Sequences
```

Construct Sequences from a collection of raw sequence byte strings.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `seqs` | `Iterable[bytes]` | Sequence byte strings. | *required* |
| `ids` | `tuple[bytes, ...] \| ndarray[bytes_] \| list[bytes] \| None` | Sequence identifiers. Defaults to integer byte strings (b"0", b"1", ...). | `None` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Sequences` | Newly constructed sequences container. |

#### from\_records

```python
from_records(records: list[Sequence] | tuple[Sequence, ...] | Iterable[Sequence]) -> Sequences
```

Construct Sequences from a collection of Sequence objects.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `records` | `Iterable[Sequence]` | Sequence objects. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Sequences` | Newly constructed sequences container. |

#### extract

```python
extract(indices: ndarray[tuple[int], dtype[int32]], starts: ndarray[tuple[int], dtype[int32]], ends: ndarray[tuple[int], dtype[int32]], strands: ndarray[tuple[int], dtype[int8]], new_ids: tuple[bytes, ...] | ndarray[tuple[int], dtype[bytes_]] | list[bytes] | None = None) -> Sequences
```

Vectorized sub-sequence extraction from the batch.

Handles coordinates and reverse-complementation across multiple sequences in parallel using Numba.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `indices` | `ndarray` | 1D array specifying parent sequence index for each extraction. | *required* |
| `starts` | `ndarray` | 0-based start coordinates relative to parent sequence. | *required* |
| `ends` | `ndarray` | 0-based end coordinates relative to parent sequence. | *required* |
| `strands` | `ndarray` | Strand orientations (1 for forward, -1 for reverse-complement). | *required* |
| `new_ids` | `tuple[bytes, ...] \| ndarray \| list[bytes] \| None` | Identifiers for extracted sequences. If None, auto-generates names. | `None` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Sequences` | New collection of extracted sub-sequences. |

#### encode

```python
encode(alphabet: Alphabet) -> ndarray[tuple[int], dtype[uint8]]
```

Encode sequence bytes into dense integer values \[0..K-1\] according to the given Alphabet.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `alphabet` | `Alphabet` | Alphabet containing precomputed kmer lookup table. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[uint8]]` | np.ndarray\[tuple\[int\], np.dtype\[np.uint8\]\]: Array of dense integer indices. |

#### reduce

```python
reduce(alphabet: Alphabet) -> Sequences
```

Vectorized reduction of sequence characters using a reduced Alphabet.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `alphabet` | `Alphabet` | Reduced alphabet containing precomputed lookup tables (e.g. `Alphabet.MMSEQS12`). | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Sequences` | New collection containing reduced ASCII sequence bytes. |

#### translate

```python
translate(code: GeneticCode = bacterial, frames: ndarray[tuple[int], dtype[int8]] | None = None, to_stop: bool = False) -> Sequences
```

Vectorized translation of nucleotide sequences into protein sequences.

Translates sequences according to the provided `GeneticCode` (defaults to NCBI Translation Table 11: `GeneticCode.bacterial`).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `code` | `GeneticCode` | Genetic code translation table to use. Defaults to `GeneticCode.bacterial`. | `bacterial` |
| `frames` | `ndarray[tuple[int], dtype[int8]] \| None` | Reading frame offsets (0, 1, or 2) per sequence. Defaults to frame 0 for all. | `None` |
| `to_stop` | `bool` | If True, truncates translation at the first stop codon (\*). Defaults to False. | `False` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Sequences` | New collection containing translated protein sequences. |

### BacterialTranslationTable

NCBI Translation Table 11 utilities for bacterial codon translation and complementation.

Compatibility wrapper delegating to `GeneticCode` (`GeneticCode.bacterial`).

Methods:

| Name | Description |
| --- | --- |
| `translate` | Translate a nucleotide sequence array or byte string to amino acid byte values. |
| `is_coding` | Check if a byte sequence starts with a valid bacterial start codon and ends with a stop codon. |

#### translate

```python
translate(seq: bytes | bytearray | memoryview | ndarray[tuple[int], dtype[uint8]], to_stop: bool = False) -> ndarray[tuple[int], dtype[uint8]]
```

Translate a nucleotide sequence array or byte string to amino acid byte values.

#### is\_coding

```python
is_coding(seq: bytes) -> bool
```

Check if a byte sequence starts with a valid bacterial start codon and ends with a stop codon.

---

## K-mer &amp; Randstrobe Indices (`serogen.core.seq.kmers`)

## kmers

K-mer indexing, FracMinHash, Randstrobe sketch construction, and alignment seed management.

This module provides sequence sketch indices (`FracMinHashIndex`, `RandstrobeIndex`), alignment seed batch containers (`Seeds`), and Numba JIT parallel search kernels.

Classes:

| Name | Description |
| --- | --- |
| `Seed` | Alignment seed representing a potential matching region between query and target. |
| `Seeds` | Structure-of-Arrays (SoA) batch container for alignment seeds. |
| `KmerRecords` | Single-sequence sketch records slice holding parallel 1D arrays. |
| `BaseKmerIndex` | Data-Oriented Structure-of-Arrays (SoA) container for sequence k-mer sketches. |
| `FracMinHashIndex` | Specialized index for fast sequence comparisons using FracMinHash. |
| `RandstrobeIndex` | Specialized index for fast sequence comparisons using syncmer-linked randstrobes. |

### Seed

Alignment seed representing a potential matching region between query and target.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `query_index` | `int` | Index of the query sequence. |
| `target_index` | `int` | Index of the target sequence. |
| `score` | `int` | Match score (number of shared k-mer hashes or randstrobes). |
| `offset` | `int` | Diagonal offset calculated as `query_pos - target_pos`. |

### Seeds

Bases: `BatchedContainer[Seed, 'Seeds']`

Structure-of-Arrays (SoA) batch container for alignment seeds.

Stores query indices, target indices, scores, and diagonal offsets as 1D NumPy arrays.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `query_indices` | `ndarray[tuple[int], dtype[uint32]]` | 1D array of query sequence indices. |
| `target_indices` | `ndarray[tuple[int], dtype[uint32]]` | 1D array of target sequence indices. |
| `scores` | `ndarray[tuple[int], dtype[uint32]]` | 1D array of alignment match scores. |
| `offsets` | `ndarray[tuple[int], dtype[int32]]` | 1D array of diagonal offset values. |

Methods:

| Name | Description |
| --- | --- |
| `concat` | Concatenate multiple `Seeds` collections into a single batch. |
| `empty` | Create an empty `Seeds` collection. |
| `filter` | Return a new Seeds collection containing only records where the mask is True. |
| `top_hits` | Reduce the batch to only the highest-scoring seed for each query. |
| `extract_sequences` | Extract parallel batches of query and target sequences mapped by this seed batch. |

#### concat

```python
concat(batches: Iterable[Self]) -> Self
```

Concatenate multiple `Seeds` collections into a single batch.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `batches` | `Iterable[Seeds]` | Iterable of `Seeds` objects. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Seeds` | `Self` | Concatenated `Seeds` collection. |

#### empty

```python
empty() -> Self
```

Create an empty `Seeds` collection.

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Seeds` | `Self` | Empty `Seeds` collection. |

#### filter

```python
filter(mask: ndarray[tuple[int], dtype[bool_]]) -> Seeds
```

Return a new Seeds collection containing only records where the mask is True.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `mask` | `ndarray[tuple[int], dtype[bool_]]` | 1D boolean mask array. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Seeds` | `Seeds` | Filtered `Seeds` collection. |

#### top\_hits

```python
top_hits(min_score: int = 1) -> Seeds
```

Reduce the batch to only the highest-scoring seed for each query.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `min_score` | `int` | Minimum match score threshold. Defaults to 1. | `1` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Seeds` | `Seeds` | Filtered `Seeds` collection containing top hit per query. |

#### extract\_sequences

```python
extract_sequences(queries: Sequences, targets: Sequences) -> tuple[Sequences, Sequences]
```

Extract parallel batches of query and target sequences mapped by this seed batch.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `queries` | `Sequences` | Source collection of query sequences. | *required* |
| `targets` | `Sequences` | Source collection of target sequences. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `tuple[Sequences, Sequences]` | tuple\[Sequences, Sequences\]: Paired query and target sequence collections. |

### KmerRecords

Single-sequence sketch records slice holding parallel 1D arrays.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `hashes` | `ndarray[tuple[int], dtype[uint64]]` | 1D array of 64-bit sketch hashes. |
| `seq_indices` | `ndarray[tuple[int], dtype[uint32]]` | 1D array of sequence indices. |
| `positions` | `ndarray[tuple[int], dtype[uint32]]` | 1D array of sequence positions. |

### BaseKmerIndex

Bases: `RaggedArrayContainer[KmerRecords, 'BaseKmerIndex']`

Data-Oriented Structure-of-Arrays (SoA) container for sequence k-mer sketches.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `hashes` | `ndarray[tuple[int], dtype[uint64]]` | 1D array of 64-bit sketch hashes. |
| `seq_indices` | `ndarray[tuple[int], dtype[uint32]]` | 1D array of source sequence indices. |
| `positions` | `ndarray[tuple[int], dtype[uint32]]` | 1D array of start positions in sequences. |
| `offsets` | `ndarray[tuple[int], dtype[int32]]` | 1D array of sequence record start offsets. |
| `lengths` | `ndarray[tuple[int], dtype[int32]]` | 1D array of record counts per sequence. |
| `n_seqs` | `int` | Total number of indexed sequences. |
| `is_sorted` | `bool` | True if records are sorted by hash. |
| `k` | `int` | K-mer length parameter. |
| `alphabet` | `Alphabet` | Alphabet used for sequence encoding. |
| `reduce` | `bool` | True if using a reduced alphabet mapping. |

Methods:

| Name | Description |
| --- | --- |
| `empty` | Create an empty index instance. |
| `concat` | Concatenate multiple index batches into a single batch. |
| `to_sorted` | Return a copy of the index with records sorted by hash. |
| `top_hits` | Find the single best-matching target sequence for each query sequence. |
| `hits` | Find all matching target sequences for each query sequence above a minimum score. |

#### total\_records

```python
total_records: int
```

Total number of k-mer / sketch records across all sequences.

#### empty

```python
empty() -> Self
```

Create an empty index instance.

#### concat

```python
concat(batches: Iterable[Self]) -> Self
```

Concatenate multiple index batches into a single batch.

#### to\_sorted

```python
to_sorted() -> Self
```

Return a copy of the index with records sorted by hash.

#### top\_hits

```python
top_hits(queries: BaseKmerIndex | Sequences | None = None, min_score: int = 1) -> Seeds
```

Find the single best-matching target sequence for each query sequence.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `queries` | `BaseKmerIndex \| Sequences \| None` | Query sequences. If None, queries itself. | `None` |
| `min_score` | `int` | Minimum match score threshold. Defaults to 1. | `1` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Seeds` | `Seeds` | Matched `Seeds` collection. |

#### hits

```python
hits(queries: BaseKmerIndex | Sequences, min_score: int = 1) -> Seeds
```

Find all matching target sequences for each query sequence above a minimum score.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `queries` | `BaseKmerIndex \| Sequences` | Query sequence index or raw sequences. | *required* |
| `min_score` | `int` | Minimum match score threshold. Defaults to 1. | `1` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Seeds` | `Seeds` | Matched `Seeds` collection containing all matches. |

### FracMinHashIndex

Bases: `BaseKmerIndex`

Specialized index for fast sequence comparisons using FracMinHash.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `scaled` | `int` | FracMinHash scale factor (e.g. 100). |
| `canonical` | `bool` | True if canonical k-mers (min of fwd/rev) are hashed. |
| `bits_per_char` | `int` | Alphabet bits per character. |
| `lut` | `ndarray[tuple[int], dtype[uint8]] \| None` | Optional custom lookup table. |

Methods:

| Name | Description |
| --- | --- |
| `empty` | Create an empty FracMinHashIndex. |
| `build` | Build a FracMinHashIndex from sequence batch. |

#### empty

```python
empty() -> Self
```

Create an empty FracMinHashIndex.

#### build

```python
build(batch: Sequences, k: int | None = None, alphabet: Alphabet | str = DNA, scaled: int = 100, canonical: bool | None = None, seed: int = 42, sort_by_hash: bool = False, lut: ndarray[tuple[int], dtype[uint8]] | None = None, bits_per_char: int | None = None, reduce: bool | None = None, **kwargs: object) -> FracMinHashIndex
```

Build a FracMinHashIndex from sequence batch.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `batch` | `Sequences` | Input sequence collection. | *required* |
| `k` | `int \| None` | K-mer length. Defaults to alphabet default\_k. | `None` |
| `alphabet` | `Alphabet \| str` | Alphabet instance or name. Defaults to Alphabet.DNA. | `DNA` |
| `scaled` | `int` | Sampling scale factor. Defaults to 100. | `100` |
| `canonical` | `bool \| None` | True if using canonical k-mers. Defaults to alphabet.supports\_canonical. | `None` |
| `seed` | `int` | Seed for hashing. Defaults to 42. | `42` |
| `sort_by_hash` | `bool` | True to sort output records by hash. Defaults to False. | `False` |
| `lut` | `ndarray \| None` | Optional custom lookup table. | `None` |
| `bits_per_char` | `int \| None` | Bits per character. Defaults to alphabet.bits\_per\_char. | `None` |
| `reduce` | `bool \| None` | True to reduce alphabet. | `None` |
| `**kwargs` | `object` | Additional parameters. | `{}` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `FracMinHashIndex` | `FracMinHashIndex` | Built `FracMinHashIndex` instance. |

### RandstrobeIndex

Bases: `BaseKmerIndex`

Specialized index for fast sequence comparisons using syncmer-linked randstrobes.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `s` | `int` | Sub-k-mer size for open syncmer evaluation. Defaults to 5. |
| `w_min` | `int` | Minimum syncmer offset window bound. Defaults to 1. |
| `w_max` | `int` | Maximum syncmer offset window bound. Defaults to 5. |
| `lut` | `ndarray[tuple[int], dtype[uint8]] \| None` | Optional lookup table. |

Methods:

| Name | Description |
| --- | --- |
| `empty` | Create an empty RandstrobeIndex. |
| `build` | Build a RandstrobeIndex from sequence batch. |

#### empty

```python
empty() -> RandstrobeIndex
```

Create an empty RandstrobeIndex.

#### build

```python
build(batch: Sequences, k: int = 10, s: int = 5, w_min: int = 1, w_max: int = 5, alphabet: Alphabet | str = MMSEQS12, seed: int = 42, sort_by_hash: bool = False, lut: ndarray[tuple[int], dtype[uint8]] | None = None, reduce: bool | None = None, **kwargs: object) -> RandstrobeIndex
```

Build a RandstrobeIndex from sequence batch.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `batch` | `Sequences` | Input sequence collection. | *required* |
| `k` | `int` | K-mer length. Defaults to 10. | `10` |
| `s` | `int` | Sub-k-mer size. Defaults to 5. | `5` |
| `w_min` | `int` | Min syncmer window bound. Defaults to 1. | `1` |
| `w_max` | `int` | Max syncmer window bound. Defaults to 5. | `5` |
| `alphabet` | `Alphabet \| str` | Alphabet instance or name. Defaults to Alphabet.MMSEQS12. | `MMSEQS12` |
| `seed` | `int` | Random seed. Defaults to 42. | `42` |
| `sort_by_hash` | `bool` | True to sort records by hash. Defaults to False. | `False` |
| `lut` | `ndarray \| None` | Optional alphabet lookup table. | `None` |
| `reduce` | `bool \| None` | True to reduce alphabet. | `None` |
| `**kwargs` | `object` | Additional parameters. | `{}` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `RandstrobeIndex` | `RandstrobeIndex` | Constructed `RandstrobeIndex`. |

Raises:

| Type | Description |
| --- | --- |
| `ValueError` | If `s >= k`. |

---

## Pairwise Alignment (`serogen.core.seq.pairwise`)

## pairwise

Pairwise sequence alignment algorithms and containers.

This module provides high-performance pairwise sequence alignment capabilities using a parallelized, banded Smith-Waterman-Gotoh dynamic programming algorithm with affine gap penalties. Alignment results are stored in memory-efficient Structure-of-Arrays (SoA) containers (`PairwiseAlignments`) or scalar records (`PairwiseAlignment`).

**Key Classes**

- `PairwiseAlignment`: Immutable container for a single result.
- `PairwiseAlignments`: Batched SoA container for results.
- `PairwiseAligner`: Banded Smith-Waterman-Gotoh alignment engine.

Classes:

| Name | Description |
| --- | --- |
| `PairwiseAlignment` | A lightweight, immutable container for the results of a single pairwise sequence alignment. |
| `PairwiseAlignments` | A high-performance SoA container for the results of multiple pairwise alignments. |
| `PairwiseAligner` | A high-performance, batched pairwise sequence aligner. |

### PairwiseAlignment

A lightweight, immutable container for the results of a single pairwise sequence alignment.

This class holds summary statistics and coordinates for an alignment between a single query and target sequence. It is typically produced by indexing into a `PairwiseAlignments` collection.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `score` | `int` | Final alignment score calculated using BLOSUM62 and gap penalties. |
| `matches` | `int` | Total number of matching bases. |
| `mismatches` | `int` | Total number of mismatched bases. |
| `gaps` | `int` | Total number of gap characters (insertions or deletions). |
| `q_start` | `int` | 0-based start coordinate on query sequence (inclusive). |
| `q_end` | `int` | 0-based end coordinate on query sequence (exclusive). |
| `t_start` | `int` | 0-based start coordinate on target sequence (inclusive). |
| `t_end` | `int` | 0-based end coordinate on target sequence (exclusive). |

#### pident

```python
pident: float
```

Calculate the percent identity of the aligned region.

Percent identity is defined as `(matches / (matches + mismatches + gaps)) * 100.0`.

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `float` | `float` | Percent identity value between 0.0 and 100.0, or 0.0 if alignment length is zero. |

#### bitscore

```python
bitscore: float
```

Calculate the Karlin-Altschul BLOSUM62 bitscore of the alignment.

Uses standard gapped BLOSUM62 parameters (\\(\\lambda = 0.267, K = 0.041\\)): \\(B = (\\lambda S - \\ln K) / \\ln 2\\) for \\(S \> 0\\), else \\(0.0\\).

### PairwiseAlignments

Bases: `BatchedContainer['PairwiseAlignment', 'PairwiseAlignments']`

A high-performance SoA container for the results of multiple pairwise alignments.

This class stores alignment statistics in a Structure-of-Arrays (SoA) layout using 1D NumPy arrays.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `scores` | `ndarray[tuple[int], dtype[int32]]` | 1D array of alignment scores. |
| `matches` | `ndarray[tuple[int], dtype[int32]]` | 1D array of match counts. |
| `mismatches` | `ndarray[tuple[int], dtype[int32]]` | 1D array of mismatch counts. |
| `gaps` | `ndarray[tuple[int], dtype[int32]]` | 1D array of gap counts. |
| `q_starts` | `ndarray[tuple[int], dtype[int32]]` | 1D array of query start coordinates. |
| `q_ends` | `ndarray[tuple[int], dtype[int32]]` | 1D array of query end coordinates. |
| `t_starts` | `ndarray[tuple[int], dtype[int32]]` | 1D array of target start coordinates. |
| `t_ends` | `ndarray[tuple[int], dtype[int32]]` | 1D array of target end coordinates. |

Methods:

| Name | Description |
| --- | --- |
| `empty` | Create an empty PairwiseAlignments collection with zero-length int32 arrays. |
| `concat` | Concatenate multiple PairwiseAlignments collections into a single batch. |

#### pidents

```python
pidents: ndarray[tuple[int], dtype[float32]]
```

Calculate percent identity for all alignments in the batch in a vectorized manner.

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[float32]]` | np.ndarray\[tuple\[int\], np.float32\]: 1D array of percent identity values. |

#### bitscores

```python
bitscores: ndarray[tuple[int], dtype[float32]]
```

Calculate Karlin-Altschul BLOSUM62 bitscores for all alignments in the batch.

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[float32]]` | np.ndarray\[tuple\[int\], np.dtype\[np.float32\]\]: 1D array of bitscores (\\(\\ge 0.0\\)). |

#### empty

```python
empty() -> Self
```

Create an empty PairwiseAlignments collection with zero-length int32 arrays.

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `PairwiseAlignments` | `Self` | Empty alignment collection. |

#### concat

```python
concat(batches: Iterable[Self]) -> Self
```

Concatenate multiple PairwiseAlignments collections into a single batch.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `batches` | `Iterable[PairwiseAlignments]` | Iterable of alignment collections. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `PairwiseAlignments` | `Self` | Single concatenated alignment collection. |

### PairwiseAligner

A high-performance, batched pairwise sequence aligner.

Uses a parallelized, banded Smith-Waterman-Gotoh algorithm to align pairs of sequences.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `gap_open` | `int` | Penalty for opening a new gap. Defaults to 11. |
| `gap_extend` | `int` | Penalty for extending an existing gap. Defaults to 1. |
| `k` | `int` | Bandwidth parameter (`2*k+1` diagonals). Defaults to 20. |

Methods:

| Name | Description |
| --- | --- |
| `align_seeds` | Convenience method to extract and align specific sequence pairs mapped by seeds. |

#### align\_seeds

```python
align_seeds(queries: Sequences, targets: Sequences, seeds: Seeds) -> PairwiseAlignments
```

Convenience method to extract and align specific sequence pairs mapped by seeds.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `queries` | `Sequences` | Full collection of query sequences. | *required* |
| `targets` | `Sequences` | Full collection of target sequences. | *required* |
| `seeds` | `Seeds` | Seed collection mapping specific query sequences to target sequences. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `PairwiseAlignments` | `PairwiseAlignments` | Alignment results parallel to the provided seeds. |

---

## Sequence Clustering (`serogen.core.seq.clustering`)

## clustering

Sequence clustering algorithms, ragged SoA data structures, and Numba kernels.

Provides high-performance sequence clustering (`Clusterer`) and ragged Structure-of-Arrays cluster containers (`Clusters`, `Cluster`) combining sparse syncmer-linked randstrobe pre-filtering, parallel banded Smith-Waterman-Gotoh alignment, and sub-millisecond Numba greedy set-cover / CD-HIT clustering.

Classes:

| Name | Description |
| --- | --- |
| `Cluster` | Scalar view of a single sequence cluster. |
| `Clusters` | Ragged Structure-of-Arrays (SoA) container for sequence clustering results. |
| `Clusterer` | High-performance sequence clustering engine. |

### Cluster

Scalar view of a single sequence cluster.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `representative` | `int` | Sequence index of the cluster centroid in the source collection. |
| `members` | `ndarray[tuple[int], dtype[int32]]` | 1D array of sequence indices belonging to this cluster. |

### Clusters

Bases: `RaggedArrayContainer[Cluster, 'Clusters']`

Ragged Structure-of-Arrays (SoA) container for sequence clustering results.

Stores centroid representative indices (`representatives`) and variable-length member sequence indices in a flat contiguous array (`members`) indexed by `offsets` and `lengths` for \\(O(1)\\) cluster slicing and member lookup.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `representatives` | `ndarray[tuple[int], dtype[int32]]` | 1D array of sequence indices representing the centroid of each cluster. |
| `members` | `ndarray[tuple[int], dtype[int32]]` | Flat 1D array of member sequence indices concatenated across all clusters. |
| `offsets` | `ndarray[tuple[int], dtype[int32]]` | Starting index into `members` for each cluster. |
| `lengths` | `ndarray[tuple[int], dtype[int32]]` | Number of member sequences in each cluster. |

Methods:

| Name | Description |
| --- | --- |
| `as_csr` | Return a zero-copy \\((C \\times N)\\) sparse CSR cluster-membership incidence matrix. |
| `get_members` | Return 1D array of original sequence indices assigned to the specified cluster ID. |
| `centroids` | Extract the representative centroid sequences from the source collection. |
| `from_assignments` | Construct a `Clusters` container from flat cluster ID assignments. |
| `empty` | Construct an empty 0-length `Clusters` instance. |
| `concat` | Concatenate multiple `Clusters` containers into a single batch. |

#### n\_clusters

```python
n_clusters: int
```

Total number of clusters \\(C\\).

#### n\_seqs

```python
n_seqs: int
```

Total number of clustered sequences \\(N\\).

#### sizes

```python
sizes: ndarray[tuple[int], dtype[int32]]
```

1D array of member counts for each cluster (alias for `lengths`).

#### representative\_indices

```python
representative_indices: ndarray[tuple[int], dtype[int32]]
```

1D array of centroid sequence indices (alias for `representatives`).

#### cluster\_ids

```python
cluster_ids: ndarray[tuple[int], dtype[int32]]
```

1D array mapping each sequence index to its cluster ID \\(c \\in \[0, C-1\]\\).

#### as\_csr

```python
as_csr(n_seqs: int | None = None) -> csr_array
```

Return a zero-copy \\((C \\times N)\\) sparse CSR cluster-membership incidence matrix.

Row \\(c\\) contains `1` at column \\(i\\) for each sequence \\(i \\in \\text{members}\_c\\).

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `n_seqs` | `int \| None` | Total number of sequences \\(N\\) (columns). If `None`, inferred from `max(members) + 1`. | `None` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `csr_array` | `csr_array` | Sparse \\((C \\times N)\\) `uint8` membership matrix. |

#### get\_members

```python
get_members(cluster_id: int) -> ndarray[tuple[int], dtype[int32]]
```

Return 1D array of original sequence indices assigned to the specified cluster ID.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `cluster_id` | `int` | 0-based integer cluster identifier. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[int32]]` | np.ndarray: Zero-copy slice of sequence indices belonging to this cluster. |

#### centroids

```python
centroids(seqs: Sequences) -> Sequences
```

Extract the representative centroid sequences from the source collection.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `seqs` | `Sequences` | Source `Sequences` collection. | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Sequences` | `Sequences` | Sliced collection containing only cluster centroids. |

#### from\_assignments

```python
from_assignments(cluster_ids: ndarray[tuple[int], dtype[int32]], representatives: ndarray[tuple[int], dtype[int32]], sizes: ndarray[tuple[int], dtype[int32]]) -> Self
```

Construct a `Clusters` container from flat cluster ID assignments.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `cluster_ids` | `ndarray[tuple[int], dtype[int32]]` | 1D array mapping each sequence \\(i \\in \[0, N-1\]\\) to cluster ID \\(c \\in \[0, C-1\]\\). | *required* |
| `representatives` | `ndarray[tuple[int], dtype[int32]]` | 1D array of centroid sequence indices (length \\(C\\)). | *required* |
| `sizes` | `ndarray[tuple[int], dtype[int32]]` | 1D array of member counts per cluster (length \\(C\\)). | *required* |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Clusters` | `Self` | Ragged SoA container with \\(O(1)\\) member indexing. |

#### empty

```python
empty() -> Self
```

Construct an empty 0-length `Clusters` instance.

#### concat

```python
concat(batches: Iterable[Self]) -> Self
```

Concatenate multiple `Clusters` containers into a single batch.

### Clusterer

High-performance sequence clustering engine.

Combines sparse syncmer-linked randstrobe pre-filtering (`RandstrobeIndex`), SIMD-parallel banded Smith-Waterman-Gotoh alignment (`PairwiseAligner`), and compiled Numba/SciPy clustering algorithms to group biological sequences.

**Modes**

- `"cdhit"` (default): Length-descending greedy incremental clustering (CD-HIT style). Guarantees that full-length proteins are selected as cluster representatives rather than fragments.
- `"mcl"`: Markov Cluster Algorithm (MCL) on BLOSUM62 alignment bitscores. Sensitive to divergent functional homologs (e.g., glycosyltransferases, polymerases, flippases) via random-walk expansion and inflation (\\(I\\)).
- `"greedy_cover"`: Iterative maximum-uncovered-degree greedy set cover.
- `"upgma"`: Hierarchical average-linkage (UPGMA) clustering via SciPy.
- `"connected_components"`: Transitive closure core components.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `min_identity` | `float` | Minimum pairwise sequence percent identity threshold \\(\[0.0, 100.0\]\\). Defaults to 80.0 (automatically relaxed to 25.0 when `mode="mcl"` and left at default 80.0). | `80.0` |
| `min_coverage` | `float` | Minimum alignment coverage fraction \\(\[0.0, 1.0\]\\) on both query and target. Defaults to 0.0. | `0.0` |
| `min_bitscore` | `float` | Minimum Karlin-Altschul alignment bitscore threshold. Defaults to 0.0 (automatically set to 40.0 when `mode="mcl"` and left at 0.0). | `0.0` |
| `inflation` | `float` | MCL inflation parameter \\(I \> 1.0\\) controlling cluster granularity. Defaults to 2.0. | `2.0` |
| `min_score` | `int` | Minimum shared randstrobe hash hits for alignment candidate seed filtering. Defaults to 2. | `2` |
| `k` | `int` | Strobemer seed length. Defaults to 10. | `10` |
| `s` | `int` | Strobemer sampling stride. Defaults to 5. | `5` |
| `aligner_k` | `int` | Bandwidth parameter (\\(2k + 1\\) diagonals) for banded Gotoh alignment. Defaults to 20. | `20` |
| `mode` | `Literal['cdhit', 'mcl', 'greedy_cover', 'upgma', 'connected_components']` | Clustering algorithm mode. Defaults to `"cdhit"`. | `'cdhit'` |
| `embedding_weight` | `float` | Blend weight \\(\\alpha \\in \[0.0, 1.0\]\\) for active-site motif cosine similarity in MCL edge weighting and role-gated twilight-zone rescue. Defaults to 0.0 (automatically uses 0.25 when `embeddings` are explicitly supplied to `cluster()`). | `0.0` |
| `motif_rescue_threshold` | `float` | Minimum cosine similarity \\(\[0.0, 1.0\]\\) between active-site embeddings required to trigger role-gated twilight-zone identity relaxation. Defaults to 0.75. | `0.75` |

Methods:

| Name | Description |
| --- | --- |
| `cluster` | Cluster an input batch of sequences into non-redundant representative groups. |

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `aligner` | `PairwiseAligner` | Return a configured `PairwiseAligner` instance. |

#### aligner

```python
aligner: PairwiseAligner
```

Return a configured `PairwiseAligner` instance.

#### cluster

```python
cluster(seqs: Sequences, roles: ndarray[tuple[int], dtype[Any]] | Sequence[int] | None = None, embeddings: ndarray[tuple[int, int], dtype[Any]] | None = None) -> Clusters
```

Cluster an input batch of sequences into non-redundant representative groups.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `seqs` | `Sequences` | Input collection of sequences to cluster. | *required* |
| `roles` | `ndarray[tuple[int], dtype[Any]] \| Sequence[int] \| None` | Optional 1D array/sequence of integer `GeneRole` IDs (length \\(N\\)). When provided, prevents clustering across incompatible known roles (`role > 0`) and, in `"mcl"` mode (or when `min_identity < 60.0`), evaluates all intra-role pairs so divergent functional homologs sharing the same role are aligned even without shared exact k-mer seeds. | `None` |
| `embeddings` | `ndarray[tuple[int, int], dtype[Any]] \| None` | Optional 2D array `(N, D)` of sequence representations (e.g., active-site `conv_max` or `task_weighted` features from `GeneRoleClassifier.transform()`). When provided, enables role-gated twilight-zone homology rescue for pairs with cosine similarity `>= self.motif_rescue_threshold` and blends cosine similarity into MCL edge weights. | `None` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `Clusters` | `Clusters` | Ragged SoA container of cluster assignments and centroid representatives. |

---

## Graph Models, Alignment &amp; Layout (`serogen.core.graph`)

## models

Core graph representations, bitfield packing, and vectorized SoA containers.

Classes:

| Name | Description |
| --- | --- |
| `BitField` | Descriptor defining a bitfield slice (shift, width, mask). |
| `GraphNode` | Abstract base protocol for all core nodes. |
| `IntNode` | Base model for core nodes represented as bit-packed primitive integers. |
| `DirectedEdge` | Abstract base class for all directed core edges. |
| `GraphModel` | Protocol and mixin providing core topological algorithms to scalar views representing graphs. |
| `GraphBatch` | Base Structure-of-Arrays (SoA) container for batched graph datasets. |

### BitField

Descriptor defining a bitfield slice (shift, width, mask). Provides safe packing, extraction, and bitmask computation.

Methods:

| Name | Description |
| --- | --- |
| `extract` | Extracts and right-shifts this bitfield's value from an integer. |
| `extract_array` | Extracts and right-shifts this bitfield's value across a numpy array. |
| `pack` | Validates and shifts field\_val into its bit position. |

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `mask` | `int` | Absolute bitmask positioned at field shift. |
| `max_val` | `int` | Maximum unsigned value that fits within this bitfield width. |

#### mask

```python
mask: int
```

Absolute bitmask positioned at field shift.

#### max\_val

```python
max_val: int
```

Maximum unsigned value that fits within this bitfield width.

#### extract

```python
extract(val: int) -> int
```

Extracts and right-shifts this bitfield's value from an integer.

#### extract\_array

```python
extract_array(arr: ndarray) -> ndarray
```

Extracts and right-shifts this bitfield's value across a numpy array.

#### pack

```python
pack(field_val: int) -> int
```

Validates and shifts field\_val into its bit position.

### GraphNode

Bases: `ABC`

Abstract base protocol for all core nodes.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `type_id` | `int` | Semantic integer label used in core adjacency matrices and embeddings. |
| `is_edge_node` | `bool` | Returns True if this node represents an injected edge in a bipartite core. |

#### type\_id

```python
type_id: int
```

Semantic integer label used in core adjacency matrices and embeddings.

#### is\_edge\_node

```python
is_edge_node: bool
```

Returns True if this node represents an injected edge in a bipartite core.

### IntNode

Bases: `int`, `GraphNode`

Base model for core nodes represented as bit-packed primitive integers.

Inherits from Python's built-in `int` and `GraphNode`, enabling zero-allocation integer node semantics across NumPy arrays, SciPy CSR matrices, and core algorithms. Hosts BitField member descriptors that automatically extract bit values when accessed on instances, while providing bitmasking, range validation, and packing at the class level.

Methods:

| Name | Description |
| --- | --- |
| `mask` | Constructs an absolute bitmask covering the specified bitfield names. |
| `mask_excluding` | Constructs a bitmask excluding the specified bitfield names. |
| `pack` | Packs keyword field values into a composite integer. |

#### mask

```python
mask(*field_names: str) -> int
```

Constructs an absolute bitmask covering the specified bitfield names.

#### mask\_excluding

```python
mask_excluding(*field_names: str) -> int
```

Constructs a bitmask excluding the specified bitfield names.

#### pack

```python
pack(**kwargs: int) -> int
```

Packs keyword field values into a composite integer.

### DirectedEdge

Bases: `ABC`

Abstract base class for all directed core edges.

### GraphModel

Bases: `ScalarView`, `Protocol`

Protocol and mixin providing core topological algorithms to scalar views representing graphs. Requires concrete `@dataclass(slots=True, frozen=True)` classes to provide `nodes` and `edges`.

Methods:

| Name | Description |
| --- | --- |
| `as_graph` | Builds a sparse CSR adjacency matrix and node label array. |
| `laplacian_spectrum` | Computes the continuous topological spectrum of the core. |
| `spectral_distance` | Computes the topological Wasserstein Distance (Earth Mover's Distance) |

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `nodes` | `Sequence[Any]` | Ordered sequence of graph nodes. |
| `edges` | `Sequence[DirectedEdge]` | Ordered sequence of directed edges connecting `nodes`. |

#### nodes

```python
nodes: Sequence[Any]
```

Ordered sequence of graph nodes.

#### edges

```python
edges: Sequence[DirectedEdge]
```

Ordered sequence of directed edges connecting `nodes`.

#### as\_graph

```python
as_graph(as_bipartite: bool = False, symmetrize: bool = False) -> tuple[csr_array, ndarray[tuple[int], dtype[uint32]]]
```

Builds a sparse CSR adjacency matrix and node label array.

All biological and genomic models in KBank are strictly directed graphs. By default, returns the canonical directed representation. If a mathematical algorithm requires a symmetric input matrix (e.g. Laplacian spectrum calculation or bidirectional message passing), specify `symmetrize=True`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `as_bipartite` | `bool` | If True, treats each directed edge as an intermediate node, forming a bipartite incidence core where edge weights are 1. If False, edges directly connect primary nodes with edge weights equal to the integer edge type. | `False` |
| `symmetrize` | `bool` | If True, produces a symmetrized (bidirectional) adjacency matrix projection. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `tuple[csr_array, ndarray[tuple[int], dtype[uint32]]]` | A tuple of: - adj: Sparse CSR adjacency matrix of shape (total\_nodes, total\_nodes). - labels: 1D NumPy array of node labels (`np.ndarray[tuple[int], np.dtype[np.uint32]]`). |

#### laplacian\_spectrum

```python
laplacian_spectrum() -> ndarray[tuple[int], dtype[float64]]
```

Computes the continuous topological spectrum of the core.

Constructs the unweighted, symmetrized adjacency matrix, computes the normalized core Laplacian using :func:`scipy.sparse.csgraph.laplacian`, and solves for the sorted eigenvalues using :func:`scipy.linalg.eigvalsh`.

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int], dtype[float64]]` | A 1D sorted NumPy array of eigenvalues (`np.ndarray[tuple[int], np.dtype[np.float64]]`). |

#### spectral\_distance

```python
spectral_distance(other: GraphModel) -> float
```

Computes the topological Wasserstein Distance (Earth Mover's Distance) between this core model and another, comparing skeletal shapes.

Extracts the Laplacian spectra from both graphs and computes their Wasserstein-1 distance using :func:`scipy.stats.wasserstein_distance`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `other` | `GraphModel` | Another GraphModel instance to compare against. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `float` | Wasserstein distance between the two normalized Laplacian spectra as a float. |

### GraphBatch

Bases: `BatchedContainer[T, S]`

Base Structure-of-Arrays (SoA) container for batched graph datasets. Provides block-diagonal CSR adjacency, Wasserstein spectral distance matrices, pan-graph compression, and vectorized SoA array slicing and concatenation.

Methods:

| Name | Description |
| --- | --- |
| `empty` | Create an empty 0-length graph batch. |
| `concat` | Concatenate multiple graph batches into a single contiguous batch. |
| `get_block_diagonal_graph` | Returns a single disconnected CSR core representing the entire batch. |
| `spectral_distance_matrix` | Computes the all-vs-all continuous topological distance matrix across the batch. |
| `as_pan_graph` | Compresses the SoA batch into a unified directed pan-core network. |

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `node_lengths` | `ndarray[tuple[int], dtype[uint32]]` | Number of nodes in each graph in the batch. |
| `edge_lengths` | `ndarray[tuple[int], dtype[uint32]]` | Number of edges in each graph in the batch. |

#### node\_lengths

```python
node_lengths: ndarray[tuple[int], dtype[uint32]]
```

Number of nodes in each graph in the batch.

#### edge\_lengths

```python
edge_lengths: ndarray[tuple[int], dtype[uint32]]
```

Number of edges in each graph in the batch.

#### empty

```python
empty() -> Self
```

Create an empty 0-length graph batch.

#### concat

```python
concat(batches: Iterable[Self]) -> Self
```

Concatenate multiple graph batches into a single contiguous batch.

#### get\_block\_diagonal\_graph

```python
get_block_diagonal_graph(unweighted: bool = False) -> csr_array
```

Returns a single disconnected CSR core representing the entire batch.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `unweighted` | `bool` | If True, sets all non-zero edge weights to 1; otherwise retains the integer edge types. | `False` |

Returns:

| Type | Description |
| --- | --- |
| `csr_array` | Block-diagonal sparse CSR adjacency matrix of shape (total\_nodes, total\_nodes). |

#### spectral\_distance\_matrix

```python
spectral_distance_matrix() -> ndarray[tuple[int, int], dtype[float64]]
```

Computes the all-vs-all continuous topological distance matrix across the batch.

Extracts per-core Laplacian spectra from the block-diagonal CSR core via :func:`scipy.sparse.csgraph.laplacian` and :func:`scipy.linalg.eigvalsh`, then computes pairwise Wasserstein distances using :func:`scipy.stats.wasserstein_distance`.

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int, int], dtype[float64]]` | A dense symmetric matrix (N x N) of Wasserstein distances (`np.ndarray[tuple[int, int], np.dtype[np.float64]]`). |

#### as\_pan\_graph

```python
as_pan_graph(node_mask: int | None = None) -> tuple[csr_array, ndarray[tuple[int], dtype[uint32]], ndarray[tuple[int], dtype[uint32]]]
```

Compresses the SoA batch into a unified directed pan-core network. Merges identical nodes, records node occurrence frequencies, and computes the exact occurrence frequency (count) of each directed transition.

Pan-graphs in KBank are strictly directed consensus networks representing synteny flow and biosynthetic transitions.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `node_mask` | `int \| None` | Optional bitmask to apply to node types before merging. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `tuple[csr_array, ndarray[tuple[int], dtype[uint32]], ndarray[tuple[int], dtype[uint32]]]` | A tuple of: - adj: Sparse CSR pan-core adjacency matrix of shape (num\_pan\_nodes, num\_pan\_nodes) where data values represent transition occurrence counts. - pan\_nodes: 1D array of pan-node integer labels (`np.ndarray[tuple[int], np.dtype[np.uint32]]`). - node\_counts: 1D array of frequencies indicating how many original nodes merged into each pan-node (`np.ndarray[tuple[int], np.dtype[np.uint32]]`). |

## align

Generic bipartite graph alignment framework with pluggable cost strategies and topological embeddings.

Classes:

| Name | Description |
| --- | --- |
| `AlignmentConfig` | Immutable configuration for bipartite graph alignment solvers. |
| `EmbeddingStrategy` | Abstract base strategy for computing continuous topological node embeddings. |
| `WeisfeilerLehmanEmbedding` | Computes generalized continuous Weisfeiler-Lehman topological smoothing. |
| `DegreeProfileEmbedding` | Computes in-degree, out-degree, and total degree profiles for each node. |
| `CostStrategy` | Abstract base strategy for computing semantic node compatibility cost matrices. |
| `ExactMatchCostStrategy` | Isomorphic cost model: 0.0 for identical node types, infinite penalty for mismatches. |
| `CallableCostStrategy` | Adapter wrapping custom user-defined cost functions. |
| `Alignment` | Outcome of bipartite graph alignment containing matched node pairs, costs, and unmatched nodes. |
| `GraphAligner` | Configurable bipartite graph alignment solver using Hungarian assignment. |
| `IsomorphicGraphAligner` | Specialized aligner pre-configured for same-domain structural isomorphism matching. |

### AlignmentConfig

Immutable configuration for bipartite graph alignment solvers.

Methods:

| Name | Description |
| --- | --- |
| `default` | Return default `AlignmentConfig`. |
| `rigid` | Strict alignment prioritizing rigid semantic constraints over topology. |
| `topological` | Relaxed alignment prioritizing topological graph flow smoothing. |

#### default

```python
default() -> Self
```

Return default `AlignmentConfig`.

#### rigid

```python
rigid() -> Self
```

Strict alignment prioritizing rigid semantic constraints over topology.

#### topological

```python
topological() -> Self
```

Relaxed alignment prioritizing topological graph flow smoothing.

### EmbeddingStrategy

Bases: `ABC`

Abstract base strategy for computing continuous topological node embeddings.

Methods:

| Name | Description |
| --- | --- |
| `compute` | Compute node embeddings from sparse adjacency and initial node features. |

#### compute

```python
compute(adj: csr_array, features: ndarray[tuple[int, int], dtype[float64]]) -> ndarray[tuple[int, int], dtype[float64]]
```

Compute node embeddings from sparse adjacency and initial node features.

### WeisfeilerLehmanEmbedding

Bases: `EmbeddingStrategy`

Computes generalized continuous Weisfeiler-Lehman topological smoothing.

Methods:

| Name | Description |
| --- | --- |
| `compute` | Smooth continuous features across sparse graph adjacency. |

#### compute

```python
compute(adj: csr_array, features: ndarray[tuple[int, int], dtype[float64]]) -> ndarray[tuple[int, int], dtype[float64]]
```

Smooth continuous features across sparse graph adjacency.

### DegreeProfileEmbedding

Bases: `EmbeddingStrategy`

Computes in-degree, out-degree, and total degree profiles for each node.

Methods:

| Name | Description |
| --- | --- |
| `compute` | Augment node features with in-degree and out-degree computed from sparse adjacency. |

#### compute

```python
compute(adj: csr_array, features: ndarray[tuple[int, int], dtype[float64]]) -> ndarray[tuple[int, int], dtype[float64]]
```

Augment node features with in-degree and out-degree computed from sparse adjacency.

### CostStrategy

Bases: `ABC`

Abstract base strategy for computing semantic node compatibility cost matrices.

Methods:

| Name | Description |
| --- | --- |
| `compute_cost` | Compute `(N, M)` pairwise node compatibility cost matrix. |

#### compute\_cost

```python
compute_cost(labels_a: ndarray[tuple[int], dtype[Any]], labels_b: ndarray[tuple[int], dtype[Any]], penalty: float = 1000000.0, graph_a: GraphModel | None = None, graph_b: GraphModel | None = None) -> ndarray[tuple[int, int], dtype[float64]]
```

Compute `(N, M)` pairwise node compatibility cost matrix.

### ExactMatchCostStrategy

Bases: `CostStrategy`

Isomorphic cost model: 0.0 for identical node types, infinite penalty for mismatches.

Methods:

| Name | Description |
| --- | --- |
| `compute_cost` | Compute exact equality cost matrix using vectorized broadcasting. |

#### compute\_cost

```python
compute_cost(labels_a: ndarray[tuple[int], dtype[Any]], labels_b: ndarray[tuple[int], dtype[Any]], penalty: float = 1000000.0, graph_a: GraphModel | None = None, graph_b: GraphModel | None = None) -> ndarray[tuple[int, int], dtype[float64]]
```

Compute exact equality cost matrix using vectorized broadcasting.

### CallableCostStrategy

Bases: `CostStrategy`

Adapter wrapping custom user-defined cost functions.

Methods:

| Name | Description |
| --- | --- |
| `compute_cost` | Delegate cost computation to wrapped callable. |

#### compute\_cost

```python
compute_cost(labels_a: ndarray[tuple[int], dtype[Any]], labels_b: ndarray[tuple[int], dtype[Any]], penalty: float = 1000000.0, graph_a: GraphModel | None = None, graph_b: GraphModel | None = None) -> ndarray[tuple[int, int], dtype[float64]]
```

Delegate cost computation to wrapped callable.

### Alignment

Outcome of bipartite graph alignment containing matched node pairs, costs, and unmatched nodes.

### GraphAligner

Configurable bipartite graph alignment solver using Hungarian assignment.

Methods:

| Name | Description |
| --- | --- |
| `align` | Execute bipartite graph alignment between two `GraphModel` instances. |

#### align

```python
align(graph_a: GraphModel, graph_b: GraphModel) -> Alignment
```

Execute bipartite graph alignment between two `GraphModel` instances.

### IsomorphicGraphAligner

Bases: `GraphAligner`

Specialized aligner pre-configured for same-domain structural isomorphism matching.

## layout

Force-directed and spectral graph layout algorithms with Numba-accelerated kernels.

Provides `LayoutEngine` for computing 2D and \\(D\\)-dimensional node coordinates for `GraphModel` instances, `GraphBatch` pan-graphs, and sparse adjacency matrices using the Fruchterman-Reingold spring-electrical algorithm.

Classes:

| Name | Description |
| --- | --- |
| `LayoutEngine` | Configurable graph layout engine with Numba-accelerated Fruchterman-Reingold physics. |

Functions:

| Name | Description |
| --- | --- |
| `rescale_layout` | Rescale node coordinates so the largest centered coordinate magnitude equals `scale`. |

### LayoutEngine

Configurable graph layout engine with Numba-accelerated Fruchterman-Reingold physics.

Supports laying out single `GraphModel` instances, `GraphBatch` collections (via their unified `.as_pan_graph()` representation), or raw SciPy sparse / NumPy adjacency matrices.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `mode` | `LayoutMode` | Layout algorithm (`"fruchterman_reingold"` or shorthand `"fr"`). |
| `dim` | `int` | Coordinate dimensionality (\\(D \\ge 1\\)). Defaults to `2`. |
| `iterations` | `int` | Number of simulated annealing iterations. Defaults to `50`. |
| `k` | `float \| None` | Optimal inter-node spring distance. If `None`, defaults to \\(1 / \\sqrt\[\\text{dim}\]{N}\\). |
| `scale` | `float \| None` | Bounding radius for output rescaling (`[-scale, +scale]`), or `None` to disable rescaling. |
| `center` | `Sequence[float] \| ndarray \| None` | Optional \\(D\\)-dimensional center offset. Defaults to origin. |
| `gravity` | `float` | Central gravity coefficient keeping disconnected components compact. Defaults to `0.05`. |
| `tol` | `float` | Early stopping threshold on maximum node displacement. Defaults to `1e-4`. |
| `init` | `InitMode` | Coordinate initialization strategy (`"random"`, `"circular"`, or `"spectral"`). |
| `use_weights` | `bool` | Whether edge weights scale attractive forces. Defaults to `True`. |
| `as_bipartite` | `bool` | Whether to expand edges as bipartite nodes when laying out a `GraphModel`. |
| `node_mask` | `int \| None` | Optional bitmask passed to `GraphBatch.as_pan_graph(node_mask=...)`. |
| `seed` | `int` | Deterministic random seed for coordinate initialization. Defaults to `42`. |

Methods:

| Name | Description |
| --- | --- |
| `layout` | Compute `(N, dim)` layout coordinates for a graph, batch pan-graph, or adjacency matrix. |

#### layout

```python
layout(graph: GraphModel | GraphBatch[Any, Any] | csr_array | ndarray, *, pos: ndarray | None = None, fixed: Sequence[int] | ndarray | None = None) -> ndarray[tuple[int, int], dtype[float64]]
```

Compute `(N, dim)` layout coordinates for a graph, batch pan-graph, or adjacency matrix.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `graph` | `GraphModel \| GraphBatch[Any, Any] \| csr_array \| ndarray` | Input `GraphModel`, `GraphBatch` (laid out via `.as_pan_graph()`), sparse `csr_array`, or dense 2D adjacency array. | *required* |
| `pos` | `ndarray \| None` | Optional initial `(N, dim)` node coordinates for warm-starting or pinning. | `None` |
| `fixed` | `Sequence[int] \| ndarray \| None` | Optional sequence/array of node indices (or boolean mask of length `N`) whose positions should remain fixed during optimization. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int, int], dtype[float64]]` | 2D NumPy array of shape `(N, dim)` with `float64` coordinates. |

### rescale\_layout

```python
rescale_layout(pos: ndarray[tuple[int, int], dtype[float64]], scale: float = 1.0, center: ndarray[tuple[int], dtype[float64]] | None = None) -> ndarray[tuple[int, int], dtype[float64]]
```

Rescale node coordinates so the largest centered coordinate magnitude equals `scale`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `pos` | `ndarray[tuple[int, int], dtype[float64]]` | `(N, dim)` coordinate array. | *required* |
| `scale` | `float` | Target maximum radius around `center`. | `1.0` |
| `center` | `ndarray[tuple[int], dtype[float64]] \| None` | Optional `(dim,)` center point. Defaults to origin. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int, int], dtype[float64]]` | Rescaled `(N, dim)` coordinate array (`float64`). |

## gnn

Numba-accelerated Relational Message-Passing Neural Network (R-MPNN) primitives.

Provides domain-agnostic CSR relational graph builders, compiled `@njit(parallel=True, fastmath=True)` message-passing forward/backward kernels, factorized bilinear directed edge/slot scorers, log-space Sinkhorn bipartite matching, and the `RelationalMPNN` model class.

Classes:

| Name | Description |
| --- | --- |
| `RelationalCSR` | Compressed Sparse Row (CSR) incoming-edge representation of a multi-relational directed graph. |
| `RelationalMPNN` | Numba-powered Relational Message-Passing Neural Network (R-MPNN) for node &amp; directed tree inference. |

Functions:

| Name | Description |
| --- | --- |
| `build_relational_csr` | Construct a `RelationalCSR` from flat directed edge arrays. |
| `build_multihop_csr` | Build a multi-hop relational CSR graph for a single graph or a ragged batch of graphs. |
| `mpnn_layer_forward` | Parallel relational message-passing forward kernel with residual connection, ReLU, and RMSNorm. |
| `mpnn_layer_backward` | Backward pass through RMSNorm, clamped residual anchor, ReLU, and CSR relational aggregation. |
| `bilinear_edge_scores_forward` | Compute factorized bilinear multi-channel edge logits `S[u, v, c] = sum_k (h_u W_src)_k (h_v W_dst)_k W_chan[c, k] + b_c`. |
| `bilinear_edge_scores_backward` | Backward pass for factorized bilinear multi-channel edge scorer. |
| `sinkhorn_bipartite_matching` | Differentiable log-space Sinkhorn-Knopp operator producing a doubly stochastic soft assignment matrix. |

### RelationalCSR

Compressed Sparse Row (CSR) incoming-edge representation of a multi-relational directed graph.

For each target vertex \\(v \\in \[0, N-1\]\\), the slice `k in range(indptr[v], indptr[v + 1])` enumerates incoming directed edges \\((u\_k \\xrightarrow{r\_k} v)\\) with source vertex `u_k = src_indices[k]`, relation ID `r_k = rel_types[k]`, and normalized aggregation weight `edge_weights[k]`.

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `n_nodes` | `int` | Total number of vertices \\(N\\) (including any appended virtual pool vertices). |
| `n_relations` | `int` | Total number of distinct relation types \\(R\\). |
| `indptr` | `ndarray[tuple[int], dtype[int32]]` | 1D `int32` array of shape `(N + 1,)` indexing incoming edges per target vertex. |
| `src_indices` | `ndarray[tuple[int], dtype[int32]]` | 1D `int32` array of shape `(E,)` of source vertex indices. |
| `rel_types` | `ndarray[tuple[int], dtype[int32]]` | 1D `int32` array of shape `(E,)` of relation type IDs in `[0, R - 1]`. |
| `edge_weights` | `ndarray[tuple[int], dtype[float32]]` | 1D `float32` array of shape `(E,)` of per-edge aggregation weights. |
| `virtual_nodes` | `ndarray[tuple[int], dtype[int32]]` | 1D `int32` array of virtual global pool vertex indices (empty if none). |

### RelationalMPNN

Numba-powered Relational Message-Passing Neural Network (R-MPNN) for node &amp; directed tree inference.

**Architecture**

1. Input projection: \\(h^{(0)} = \\text{RMSNorm}(X W\_{\\text{in}} + b\_{\\text{in}})\\).
2. \\(L\\) Relational Message-Passing layers with residual connections, ReLU, RMSNorm, and optional clamped-node anchor injection (`clamped_mask`) so pre-existing annotations anchor contextual propagation without drifting.
3. Node readout head: \\(Z\_{\\text{node}} = h^{(L)} W\_{\\text{node}} + b\_{\\text{node}}\\) (`(N, num_node_classes)`).
4. Factorized bilinear multi-slot directed edge readout head: \\(S\[u, v, c\] = \\frac{1}{\\sqrt{K}} \\sum\_{k=1}^K (h\_u^{(L)} W\_{\\text{src}})\_k (h\_v^{(L)} W\_{\\text{dst}})\_k W\_{\\text{chan}}\[c, k\] + b\_{\\text{chan}}\[c\]\\) producing `(M, M, num_edge_channels)` logits suitable for decoding via `maximum_spanning_arborescence`.

Methods:

| Name | Description |
| --- | --- |
| `encode` | Run the \\(L\\)-layer R-MPNN encoder and return final node embeddings `(N, hidden_dim)`. |
| `predict_node_logits` | Compute pre-softmax node class logits `(N, num_node_classes)`. |
| `predict_node_proba` | Compute softmax node class probabilities `(N, num_node_classes)`. |
| `score_edges` | Score all directed candidate edges `(u -> v, channel)` among `h_nodes` (or `h_nodes[node_indices]`). |
| `fit_step` | Execute one complete forward + backward + AdamW optimization step on a graph or batch. |
| `save` | Save model weights and hyperparameters to a compressed `.npz` archive (`allow_pickle=False`). |
| `load` | Load a `RelationalMPNN` from a compressed `.npz` archive. |

#### encode

```python
encode(x: ndarray, csr: RelationalCSR, *, clamped_mask: ndarray | None = None) -> ndarray[tuple[int, int], dtype[float32]]
```

Run the \\(L\\)-layer R-MPNN encoder and return final node embeddings `(N, hidden_dim)`.

#### predict\_node\_logits

```python
predict_node_logits(x: ndarray, csr: RelationalCSR, *, clamped_mask: ndarray | None = None) -> ndarray[tuple[int, int], dtype[float32]]
```

Compute pre-softmax node class logits `(N, num_node_classes)`.

#### predict\_node\_proba

```python
predict_node_proba(x: ndarray, csr: RelationalCSR, *, clamped_mask: ndarray | None = None) -> ndarray[tuple[int, int], dtype[float32]]
```

Compute softmax node class probabilities `(N, num_node_classes)`.

#### score\_edges

```python
score_edges(h_nodes: ndarray, node_indices: Sequence[int] | ndarray | None = None) -> ndarray[tuple[int, int, int], dtype[float32]]
```

Score all directed candidate edges `(u -> v, channel)` among `h_nodes` (or `h_nodes[node_indices]`).

Returns:

| Type | Description |
| --- | --- |
| `ndarray[tuple[int, int, int], dtype[float32]]` | np.ndarray: 3D `float32` tensor of shape `(M, M, num_edge_channels)`. |

#### fit\_step

```python
fit_step(x: ndarray, csr: RelationalCSR, *, node_targets: ndarray | None = None, node_weights: ndarray | None = None, edge_node_indices: ndarray | None = None, edge_parent_targets: ndarray | None = None, edge_slot_targets: ndarray | None = None, clamped_mask: ndarray | None = None, lr_scale: float = 1.0) -> float
```

Execute one complete forward + backward + AdamW optimization step on a graph or batch.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `x` | `ndarray` | Input node feature matrix `(N_real, in_dim)` or `(N_total, in_dim)`. | *required* |
| `csr` | `RelationalCSR` | `RelationalCSR` connectivity structure. | *required* |
| `node_targets` | `ndarray \| None` | Optional 1D `int32` array of ground-truth node class indices (`-1` = ignore). | `None` |
| `node_weights` | `ndarray \| None` | Optional 1D `float32` array of per-node loss weights. | `None` |
| `edge_node_indices` | `ndarray \| None` | Optional 1D `int32` array of active tree vertices `[v_0, ..., v_{M-1}]`. | `None` |
| `edge_parent_targets` | `ndarray \| None` | Optional 1D `int32` array of length `M` giving target parent index in `[0, M-1]` for each active tree vertex (`-1` for root or unsupervised vertices). | `None` |
| `edge_slot_targets` | `ndarray \| None` | Optional 1D `int32` array of length `M` giving target slot/channel in `[0, num_edge_channels - 1]` for each active tree vertex (`-1` = marginalize over slots). | `None` |
| `clamped_mask` | `ndarray \| None` | Optional 1D `uint8` / boolean mask of clamped vertices. | `None` |
| `lr_scale` | `float` | Cosine/schedule multiplier on `self.learning_rate`. | `1.0` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `float` | `float` | Total scalar loss for this step. |

#### save

```python
save(path: Path | str) -> Path
```

Save model weights and hyperparameters to a compressed `.npz` archive (`allow_pickle=False`).

#### load

```python
load(path: Path | str) -> Self
```

Load a `RelationalMPNN` from a compressed `.npz` archive.

### build\_relational\_csr

```python
build_relational_csr(n_nodes: int, sources: Sequence[int] | ndarray, targets: Sequence[int] | ndarray, relations: Sequence[int] | ndarray | None = None, *, n_relations: int | None = None, add_self_loops: bool = True, normalize_by_degree: bool = True, virtual_nodes: ndarray | None = None) -> RelationalCSR
```

Construct a `RelationalCSR` from flat directed edge arrays.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `n_nodes` | `int` | Total number of vertices \\(N\\). | *required* |
| `sources` | `Sequence[int] \| ndarray` | 1D array-like of source vertex indices `u`. | *required* |
| `targets` | `Sequence[int] \| ndarray` | 1D array-like of target vertex indices `v`. | *required* |
| `relations` | `Sequence[int] \| ndarray \| None` | Optional 1D array-like of integer relation IDs `r >= 0`. If `None`, all edges receive relation `1` (when `add_self_loops=True`, self-loops receive relation `0`). | `None` |
| `n_relations` | `int \| None` | Total number of relation types \\(R\\). Inferred if `None`. | `None` |
| `add_self_loops` | `bool` | If `True` (default), prepends a self-loop `(v -> v, r=0)` for every vertex. | `True` |
| `normalize_by_degree` | `bool` | If `True` (default), normalizes incoming weights per `(target, relation)` group so each relation's incoming messages average cleanly. | `True` |
| `virtual_nodes` | `ndarray \| None` | Optional 1D `int32` array of virtual global pool vertex indices. | `None` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `RelationalCSR` | `RelationalCSR` | Incoming-edge CSR structure ready for Numba MPNN kernels. |

### build\_multihop\_csr

```python
build_multihop_csr(node_offsets: Sequence[int] | ndarray, edge_sources: Sequence[int] | ndarray, edge_targets: Sequence[int] | ndarray, edge_orientations: Sequence[int] | ndarray | None = None, *, include_2hop: bool = True, add_virtual_pool: bool = True) -> RelationalCSR
```

Build a multi-hop relational CSR graph for a single graph or a ragged batch of graphs.

**Constructs up to 8 directed relation types**

- `0`: Self-loop (`v -> v`)
- `1`: 1-hop forward (`u -> v`, codirectional)
- `2`: 1-hop reverse (`v -> u`, codirectional)
- `3`: 1-hop convergent/divergent (`u <-> v` when `edge_orientations != 0`)
- `4`: 2-hop forward (`u -> w -> v`)
- `5`: 2-hop reverse (`v -> w -> u`)
- `6`: Real vertex to per-graph virtual global pool (`u -> pool_g`)
- `7`: Per-graph virtual global pool to real vertex (`pool_g -> u`)

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `node_offsets` | `Sequence[int] \| ndarray` | 1D array of graph node offsets `[0, n_0, n_0 + n_1, ..., N_real]`. | *required* |
| `edge_sources` | `Sequence[int] \| ndarray` | 1D array of 0-based global source vertex indices in `[0, N_real - 1]`. | *required* |
| `edge_targets` | `Sequence[int] \| ndarray` | 1D array of 0-based global target vertex indices in `[0, N_real - 1]`. | *required* |
| `edge_orientations` | `Sequence[int] \| ndarray \| None` | Optional 1D array of orientation codes (`0` = codirectional, `>0` = conv/div). | `None` |
| `include_2hop` | `bool` | If `True` (default), adds 2-hop forward (`r=4`) and reverse (`r=5`) edges. | `True` |
| `add_virtual_pool` | `bool` | If `True` (default), appends 1 virtual global pool node per graph at indices `[N_real, ..., N_real + G - 1]` connected via relations `6` and `7`. | `True` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `RelationalCSR` | `RelationalCSR` | Multi-hop relational CSR with `n_relations = 8`. |

### mpnn\_layer\_forward

```python
mpnn_layer_forward(h_in: ndarray, indptr: ndarray, src_indices: ndarray, rel_types: ndarray, edge_weights: ndarray, w_rel: ndarray, b_rel: ndarray, clamped_mask: ndarray, clamped_anchor: ndarray, norm_eps: float = 1e-05) -> tuple[ndarray, ndarray, ndarray]
```

Parallel relational message-passing forward kernel with residual connection, ReLU, and RMSNorm.

Returns:

| Type | Description |
| --- | --- |
| `tuple[ndarray, ndarray, ndarray]` | tuple\[np.ndarray, np.ndarray, np.ndarray\]: `(h_out, pre_norm, rms_inv)` for backward pass. |

### mpnn\_layer\_backward

```python
mpnn_layer_backward(d_h_out: ndarray, h_in: ndarray, pre_norm: ndarray, rms_inv: ndarray, indptr: ndarray, src_indices: ndarray, rel_types: ndarray, edge_weights: ndarray, w_rel: ndarray, clamped_mask: ndarray) -> tuple[ndarray, ndarray, ndarray]
```

Backward pass through RMSNorm, clamped residual anchor, ReLU, and CSR relational aggregation.

### bilinear\_edge\_scores\_forward

```python
bilinear_edge_scores_forward(h_nodes: ndarray, w_src: ndarray, w_dst: ndarray, w_chan: ndarray, b_chan: ndarray) -> tuple[ndarray, ndarray, ndarray]
```

Compute factorized bilinear multi-channel edge logits `S[u, v, c] = sum_k (h_u W_src)_k (h_v W_dst)_k W_chan[c, k] + b_c`.

### bilinear\_edge\_scores\_backward

```python
bilinear_edge_scores_backward(d_scores: ndarray, h_nodes: ndarray, u_proj: ndarray, v_proj: ndarray, w_src: ndarray, w_dst: ndarray, w_chan: ndarray) -> tuple[ndarray, ndarray, ndarray, ndarray, ndarray]
```

Backward pass for factorized bilinear multi-channel edge scorer.

### sinkhorn\_bipartite\_matching

```python
sinkhorn_bipartite_matching(log_alpha: ndarray, n_iters: int = 20, tau: float = 1.0) -> ndarray
```

Differentiable log-space Sinkhorn-Knopp operator producing a doubly stochastic soft assignment matrix.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `log_alpha` | `ndarray` | 2D array `(M, K)` of unnormalized affinity logits between \\(M\\) sources and \\(K\\) targets. | *required* |
| `n_iters` | `int` | Number of alternating log-row and log-column normalization iterations. Defaults to `20`. | `20` |
| `tau` | `float` | Entropic temperature \\(\\tau \> 0\\). Smaller \\(\\tau\\) approaches a hard permutation matrix. | `1.0` |

Returns:

| Type | Description |
| --- | --- |
| `ndarray` | np.ndarray: 2D `float32` soft assignment matrix `P` of shape `(M, K)`. |

## arborescence

Directed spanning arborescence solvers (Chu-Liu/Edmonds &amp; Constrained \\(K\\)-Best Branch-and-Bound).

Provides compiled Numba algorithms for finding maximum/minimum weight directed spanning trees (arborescences) rooted at a target node, with optional slot/valence exclusivity constraints and \\(k\\)-best arborescence enumeration:

- `maximum_spanning_arborescence`
- `minimum_spanning_arborescence`
- `k_best_arborescences`
- `ArborescenceResult`

Classes:

| Name | Description |
| --- | --- |
| `ArborescenceResult` | Result of a directed spanning arborescence optimization. |

Functions:

| Name | Description |
| --- | --- |
| `maximum_spanning_arborescence` | Find the maximum-weight directed spanning arborescence rooted at `root`. |
| `minimum_spanning_arborescence` | Find the minimum-cost directed spanning arborescence rooted at `root`. |
| `k_best_arborescences` | Enumerate the top-`k` highest-scoring valid directed spanning arborescences in descending order. |

### ArborescenceResult

Result of a directed spanning arborescence optimization.

Supports both standard 2-tuple unpacking (`parents, score = maximum_spanning_arborescence(...)`) and rich attribute access (`.parents`, `.score`, `.slots`, `.edges`).

Attributes:

| Name | Type | Description |
| --- | --- | --- |
| `parents` | `ndarray[tuple[int], dtype[int32]]` | 1D `int32` array of shape `(N,)` where `parents[v]` is the parent node \\(u\\) of \\(v\\) (`-1` for `root` or excluded nodes). |
| `score` | `float` | Total weight (or cost) of the selected arborescence edges. |
| `slots` | `ndarray[tuple[int], dtype[int32]]` | 1D `int32` array of shape `(N,)` giving the selected channel/slot index \\(s\\) on the incoming edge \\((u \\to v, s)\\) (`0` for 2D inputs, `-1` for `root`). |
| `edges` | `ndarray[tuple[int, int], dtype[int32]]` | 2D `int32` array of shape `(M, 3)` containing `(parent_u, child_v, slot_s)` for each directed edge in the arborescence. |

### maximum\_spanning\_arborescence

```python
maximum_spanning_arborescence(weights: ndarray, root: int = 0, *, edge_groups: ndarray | None = None, required_nodes: ndarray | None = None, slot_exclusivity: bool = True) -> ArborescenceResult
```

Find the maximum-weight directed spanning arborescence rooted at `root`.

Uses Chu-Liu / Edmonds' optimum branching algorithm in \\(O(N^2)\\) time when unconstrained, and automatically switches to compiled Numba branch-and-bound when slot/valence exclusivity constraints (`edge_groups` or 3D `(N, N, S)` tensors with `slot_exclusivity=True`) are active.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `weights` | `ndarray` | 2D array `(N, N)` where `weights[u, v]` is the score of directed edge `u -> v`, or 3D array `(N, N, S)` where `weights[u, v, s]` is the score of `u -> v` via slot `s`. | *required* |
| `root` | `int` | Index of the root vertex (`0 <= root < N`). Defaults to `0`. | `0` |
| `edge_groups` | `ndarray \| None` | Optional integer array of shape matching `weights` assigning exclusivity group IDs (`>= 0`). At most one edge from each non-negative group ID may be selected. (`-1` = unconstrained). | `None` |
| `required_nodes` | `ndarray \| None` | Optional boolean mask `(N,)` or 1D index array specifying which vertices must be spanned by the arborescence. Defaults to all `N` vertices. | `None` |
| `slot_exclusivity` | `bool` | If `True` (default) and `weights` is 3D `(N, N, S)` with `edge_groups=None`, enforces that at most one outgoing edge from parent `u` may use slot `s`. | `True` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `ArborescenceResult` | `ArborescenceResult` | Result object supporting both `parents, score = maximum_spanning_arborescence(...)` |
|  | `ArborescenceResult` | unpacking and `.parents`, `.slots`, `.edges`, `.score` attribute access. |

### minimum\_spanning\_arborescence

```python
minimum_spanning_arborescence(costs: ndarray, root: int = 0, *, edge_groups: ndarray | None = None, required_nodes: ndarray | None = None, slot_exclusivity: bool = True) -> ArborescenceResult
```

Find the minimum-cost directed spanning arborescence rooted at `root`.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `costs` | `ndarray` | 2D `(N, N)` or 3D `(N, N, S)` array of non-negative/real edge costs (use `np.inf` for forbidden edges). | *required* |
| `root` | `int` | Index of the root vertex (`0 <= root < N`). Defaults to `0`. | `0` |
| `edge_groups` | `ndarray \| None` | Optional exclusivity group IDs (`-1` = unconstrained, `>= 0` = at most one edge per group). | `None` |
| `required_nodes` | `ndarray \| None` | Optional boolean mask or index array of vertices to span. | `None` |
| `slot_exclusivity` | `bool` | Enforce `(parent, slot)` exclusivity on 3D inputs when `True`. | `True` |

Returns:

| Name | Type | Description |
| --- | --- | --- |
| `ArborescenceResult` | `ArborescenceResult` | Minimum-cost arborescence (`parents, min_cost = minimum_spanning_arborescence(...)`). |

### k\_best\_arborescences

```python
k_best_arborescences(weights: ndarray, root: int = 0, k: int = 5, *, edge_groups: ndarray | None = None, required_nodes: ndarray | None = None, slot_exclusivity: bool = True) -> list[ArborescenceResult]
```

Enumerate the top-`k` highest-scoring valid directed spanning arborescences in descending order.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `weights` | `ndarray` | 2D `(N, N)` or 3D `(N, N, S)` array of directed edge scores `u -> v`. | *required* |
| `root` | `int` | Index of the root vertex (`0 <= root < N`). Defaults to `0`. | `0` |
| `k` | `int` | Number of top arborescences to return (`k >= 1`). Defaults to `5`. | `5` |
| `edge_groups` | `ndarray \| None` | Optional integer array of exclusivity group IDs (`>= 0`). | `None` |
| `required_nodes` | `ndarray \| None` | Optional boolean mask or 1D index array of vertices that must be spanned. | `None` |
| `slot_exclusivity` | `bool` | If `True` (default) and `weights` is 3D, enforces `(parent, slot)` exclusivity. | `True` |

Returns:

| Type | Description |
| --- | --- |
| `list[ArborescenceResult]` | list\[ArborescenceResult\]: Up to `k` valid arborescences ordered from highest to lowest score. |
