Source code for vdjtools.model.model

"""The :class:`Model` container — a manifest plus its polars marginal and germline tables."""
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

import polars as pl

from .schema import Manifest, validate_tables


[docs] @dataclass(slots=True) class Model: """A V(D)J recombination model: declared graph + tidy polars tables. Args: manifest: Locus metadata and the recombination Bayes net. tables: Event name -> its long-format marginal ``pl.DataFrame``. genomic: ``"genes_v"`` / ``"genes_j"`` / (VDJ) ``"genes_d"`` -> germline reference frame. training: Optional EM training log, ``{"runs": [...]}`` — one entry per inference run, so a warm-start refit appends rather than overwrites. Set by :func:`~vdjtools.model.infer.infer` / :func:`~vdjtools.model.infer.infer_native`, persisted alongside the model as ``training.json``, and read back as a table by :func:`~vdjtools.model.infer.training_frame`. ``None`` for a model that was never fitted here (every bundled model, and anything imported from OLGA). """ manifest: Manifest tables: dict[str, pl.DataFrame] genomic: dict[str, pl.DataFrame] training: dict | None = None @property def locus(self) -> str: return self.manifest.locus @property def organism(self) -> str: return self.manifest.organism @property def chain_type(self) -> str: return self.manifest.chain_type
[docs] def validate(self, *, tol: float = 1e-5) -> "Model": """Assert every event table has the right columns and normalizes; returns ``self``.""" validate_tables(self.manifest, self.tables, tol=tol) return self
[docs] def save(self, path: str | Path, *, fmt: str = "parquet") -> None: """Write the model to a directory (``manifest.json`` + one file per table).""" from .io import save_model save_model(self, path, fmt=fmt)
[docs] @classmethod def load(cls, path: str | Path) -> "Model": """Load a model previously written by :meth:`save`.""" from .io import load_model return load_model(path)