CyteOnto class#

CyteOnto compares cell type labels in Cell Ontology space. from_config() creates it and makes sure that the descriptions and embeddings of the Cell Ontology terms are on disk. compare() scores author labels against the labels of one or more algorithms and returns a DataFrame, and compare_anndata() reads the algorithm labels from adata.obs. cache_stats(), clear_run() and purge_stale() manage the caches of comparison runs.

from cyteonto import CyteOnto

cyto = await CyteOnto.from_config(agent=agent, embedding=embedding, llm=llm)
df = await cyto.compare(
    author_labels=["alveolar macrophage", "regulatory T cell"],
    algorithms={"method_a": ["lung macrophage", "Treg"]},
    run_id="lung_v1",
)

from_config(), compare() and compare_anndata() are coroutines: await them in a notebook, or run them with asyncio.run() in a script. The Python quickstart runs these steps, Read the results describes the DataFrame, and Caching and runs describes what each call saves on disk.

class cyteonto.CyteOnto(agent, embedding, llm, data_dir=None, user_dir=None, max_description_concurrency=100, use_pubmed_tool=True, reasoning=False, fallback_agent=None, fallback_embedding=None, fallback_llm=None)#

Compare two sets of cell type annotations against the Cell Ontology.

Typical use:

cyto = await CyteOnto.from_config(agent=agent, embedding=embd_cfg, llm=llm_cfg)
results = await cyto.compare(
    run_id="sample_run",
    author_labels=[...],
    algorithms={"algo1": [...], "algo2": [...]},
)

Set up paths and cache keys without loading the ontology or calling a model.

Parameters:
  • agent (Agent) – pydantic-ai agent whose model describes cell types and splits compound labels.

  • embedding (EmbdConfig) – Embedding provider and model. When embedding.apiKey is None, the key is read from the provider’s environment variable, such as NEBIUS_API_KEY, or else from EMBEDDING_MODEL_API_KEY.

  • llm (LlmConfig) – Provider and model of agent, which name the description caches. llm.model must equal agent.model.model_name.

  • data_dir (str | Path | None, default: None) – Directory with the Cell Ontology files and the ontology caches. Defaults to the data directory inside the installed package.

  • user_dir (str | Path | None, default: None) – Directory for the caches of comparison runs. Defaults to <data_dir>/user_files.

  • max_description_concurrency (int, default: 100) – Maximum number of LLM requests that run at the same time.

  • use_pubmed_tool (bool, default: True) – Let the agent search PubMed abstracts while it describes a label.

  • reasoning (bool, default: False) – Leave the model’s reasoning mode as the provider sets it. When False, the requests ask the provider to turn reasoning off.

  • fallback_agent (Agent | None, default: None) – Agent that describes the labels whose description is still blank after the primary agent’s retries.

  • fallback_embedding (EmbdConfig | None, default: None) – Embedding configuration to use when the primary embedding provider fails, unless it equals embedding. The instance first loads the ontology embeddings of this model, or makes them from the ontology descriptions, and then keeps embedding with it. If that step fails, the call raises and the instance keeps the primary model.

  • fallback_llm (LlmConfig | None, default: None) – Provider and model of fallback_agent. It is reported in model_pair_usage; descriptions from the fallback agent are cached under llm.

Raises:

ValueError – If no embedding API key is found for a provider other than ollama, or if llm.model differs from the agent’s model name.

usage: cyteonto.AgentUsage#

The requests and tokens of the successful LLM calls of this instance, to describe and to split labels, including those of from_config(). Failed attempts and embedding requests are not counted.

model_pair_usage: cyteonto.ModelPairUsage#

Whether the primary or the fallback LLM and embedding models were used.

async classmethod from_config(agent, embedding, llm, data_dir=None, user_dir=None, force_regenerate=False, max_description_concurrency=100, use_pubmed_tool=True, reasoning=False, fallback_agent=None, fallback_embedding=None, fallback_llm=None)#

Create a CyteOnto and make sure the ontology embeddings are on disk.

Takes the arguments of CyteOnto and force_regenerate. Loads the descriptions of the Cell Ontology terms for llm from data_dir and checks that the term embeddings for llm and embedding exist. Terms without a description are described with agent, and fallback_agent if given, and then every term is embedded again. When every term has a description and the embeddings file was made after the descriptions last changed, no model is called. If embedding fails to embed the terms, the instance checks that fallback_embedding works and switches to it and its ontology embeddings, which are made if they are missing.

Parameters:

force_regenerate (bool, default: False) – Delete the ontology descriptions of llm, which all model pairs with this LLM share, and their embeddings with embedding and fallback_embedding first. The descriptions and the embeddings with embedding are then made again for every term, and those with fallback_embedding at the next failover.

Raises:
  • ValueError – For the same reasons as the constructor.

  • FileNotFoundError – If cell_to_cell_ontology.csv, cell_to_cell_ontology_enriched.csv or cl.owl is missing from <data_dir>/cell_ontology.

  • RuntimeError – If the ontology CSV cannot be read, or the term embeddings cannot be made or saved.

Return type:

CyteOnto

async compare(author_labels, algorithms, *, run_id=None, metric='cosine_kernel', metric_params=None, min_match_similarity=0.1, use_cache=True, compound_scoring='max')#

Compare author labels with the labels of one or more algorithms.

Labels are lowercased, compound labels are split into cell types, and each label or part is described, embedded and matched to its closest Cell Ontology term. Each author label is then scored against the algorithm label at the same position.

Parameters:
  • author_labels (list[str]) – Reference labels, one per item, such as a cell or a cluster.

  • algorithms (dict[str, list[str]] | Sequence[tuple[str, list[str]]]) – Mapping {algo_name: labels} (or sequence of pairs). Each label list must be the same length as author_labels. Algorithm names must be unique, and "author" is reserved.

  • run_id (str | None, default: None) – Unique identifier for this comparison. Used to namespace user caches on disk and to tag each result row. Reuse the same run_id across calls to benefit from caching; pass it to clear_run to delete the descriptions and embeddings. If None, an id of the form run-<uuid4> is generated and logged.

  • metric (str, default: 'cosine_kernel') – Similarity metric for each pair of matched terms: cosine_kernel, cosine_direct, path, set:jaccard, set:cosine, set:weighted_jaccard, weighted:num_ancestors, weighted:specificity, weighted:embedding_cosine or simple. Other names fall back to simple.

  • metric_params (dict[str, Any] | None, default: None) – Parameters of cosine_kernel: the center, width and amplitude of its Gaussian. Other metrics ignore them.

  • min_match_similarity (float, default: 0.1) – Lowest cosine similarity between a label and its closest Cell Ontology term at which the label counts as matched.

  • use_cache (bool, default: True) – When True, reuse the label decompositions, descriptions and embeddings saved for run_id. When False, generate them again.

  • compound_scoring (Literal['max', 'hungarian_mean'], default: 'max') – How to reduce the m×n part score matrix for compound pairs. "max" takes the maximum entry; "hungarian_mean" uses Hungarian assignment mean with a coverage penalty when m != n.

Return type:

DataFrame

Returns:

DataFrame with one row per (algorithm, pair_index) combination. The run_id column is populated with the id used for this call (the caller-provided value or the auto-generated UUID).

Raises:
  • ValueError – If compound_scoring is invalid, algorithms is empty, an algorithm name is repeated or is "author", or a label list differs in length from author_labels.

  • RuntimeError – If labels cannot be embedded, or, at an embedding failover, the ontology embeddings of the fallback model cannot be made or saved; the instance then keeps the primary model.

  • FileNotFoundError – If the ontology embeddings of the model pair are missing, or, at an embedding failover, both those of the fallback model and the ontology descriptions to make them from. Run from_config first.

async compare_anndata(author_labels, anndata_objects, target_columns, author_column, *, run_id=None, algorithm_names=None, metric='cosine_kernel', metric_params=None, min_match_similarity=0.1, use_cache=True, compound_scoring='max')#

Pull algorithm labels out of adata.obs and delegate to compare.

Each column in target_columns becomes one algorithm. Its values are converted to strings, so missing values become labels such as "nan".

Parameters:
  • author_labels (list[str]) – Reference labels, one per row of adata.obs.

  • anndata_objects (Sequence[Any]) – AnnData objects to read the columns from, each with one row per author label. An object without author_column in obs is skipped with a warning. With several objects, each algorithm name ends with the position of its object, such as pred_0 and pred_1.

  • target_columns (list[str]) – Columns of adata.obs with the algorithm labels. A missing column is skipped with a warning.

  • author_column (str) – Column that each object must have in obs. Only its presence is checked; the author labels come from author_labels.

  • run_id (str | None, default: None) – As in compare: pass one to reuse caches, or None to let the call generate and log one.

  • algorithm_names (list[str] | None, default: None) – Names of the algorithms in the results, one per target column. Defaults to the column names.

  • metric (str, default: 'cosine_kernel') – As in compare.

  • metric_params (dict[str, Any] | None, default: None) – As in compare.

  • min_match_similarity (float, default: 0.1) – As in compare.

  • use_cache (bool, default: True) – As in compare.

  • compound_scoring (Literal['max', 'hungarian_mean'], default: 'max') – As in compare.

Return type:

DataFrame

Returns:

The DataFrame that compare returns.

Raises:

ValueError – If algorithm_names and target_columns differ in length, or for the reasons that compare raises it, such as an object whose number of rows differs from author_labels.

cache_stats(run_id=None)#

Summarise on-disk user embedding caches.

Parameters:

run_id (str | None, default: None) – If given, restrict stats to that run. Otherwise aggregates across all runs under user_dir/embeddings.

Return type:

dict[str, Any]

Returns:

A dict with root (the directory searched), total_files (the number of NPZ files), total_size_mb and stale_files (NPZ files that cannot be loaded, such as files without inline labels).

clear_run(run_id, kind=None, identifier=None)#

Delete user embeddings and descriptions for a run.

The label decompositions of the run are kept.

Parameters:
  • run_id (str) – The run identifier used in compare(...).

  • kind (str | None, default: None) – "author" or "algorithm". If omitted, all kinds under run_id are removed.

  • identifier (str | None, default: None) – When kind is given, restrict to a single identifier (e.g. one algorithm name) and to the files of the current model pair. Ignored if kind is None.

Return type:

int

Returns:

Number of files removed.

Raises:

ValueError – If kind is not "author", "algorithm" or None.

purge_stale(run_id=None)#

Delete user NPZ files that cannot be loaded (such as the stale format).

Files in the stale format lack the inline labels.

Parameters:

run_id (str | None, default: None) – If given, only delete files of that run.

Return type:

int

Returns:

Number of files removed.