omicverse-single-cell-cellvote-consensus

Installation
SKILL.md

OmicVerse Single-Cell — CellVote Multi-Annotator Consensus

Goal

Take an annotated AnnData that already has labels from two or more annotators (e.g. obs['scsa_annotation'], obs['gpt_celltype'], obs['gbi_celltype']) and produce a per-cluster consensus label in obs['CellVote_celltype']. The class wraps the upstream annotators (so you can populate them via the same object) and arbitrates by either calling an LLM with the per-cluster candidate set + the cluster's marker genes (online; requires API key) or running a deterministic local-majority vote on lower-cased candidates (offline; tutorial-canonical demo).

CellVote is OmicVerse's own consensus layer; it's distinct from single-popv-annotation (POPV is a separate Bayesian voting tool from a different group). CellVote can include POPV as one of its inputs but is not a wrapper for POPV.

Quick Workflow

  1. Ensure each candidate annotator's labels are populated in obs columns (e.g. scsa_annotation, gpt_celltype, gbi_celltype). Either run the annotators yourself (see Branch Selection for the pre-baked cv.scsa_anno() / cv.gpt_anno() / cv.gbi_anno() etc.) or import labels from elsewhere.
  2. Compute cluster-level marker genes — marker_dict[cluster_id] = [top_genes...]. CellVote uses these to give the LLM (or the local arbitrator) biological context per cluster.
  3. Construct: cv = CellVote(adata). Stores the AnnData reference; doesn't run anything yet.
  4. Vote (online, LLM): final_map = cv.vote(clusters_key='leiden', cluster_markers=marker_dict, celltype_keys=['scsa_annotation', 'gpt_celltype', 'gbi_celltype'], species='human', organization='PBMC', provider='openai', model='gpt-4o-mini', api_key='sk-...', result_key='CellVote_celltype'). Calls the LLM once per cluster with the candidate labels + markers + species/organization context; LLM returns a single arbitrated label. Result lands in adata.obs['CellVote_celltype'].
  5. Vote (offline, local majority): monkey-patch omicverse.single._cellvote.get_cluster_celltype = local_fn before calling cv.vote(...). The local function takes the same (cluster_celltypes, cluster_markers, species, organization, model, base_url, provider, api_key) signature and returns a dict mapping cluster → consensus label. The tutorial provides a one-line pd.Series.value_counts().idxmax() implementation that's deterministic and free.
  6. Inspect: compare obs[['leiden', 'scsa_annotation', 'gpt_celltype', 'gbi_celltype', 'CellVote_celltype']].head() and the per-cluster summary obs.groupby('leiden')[annot_cols].agg(lambda s: s.value_counts().index[0]).

Interface Summary

Installs
1
GitHub Stars
13
First Seen
Jul 22, 2026
omicverse-single-cell-cellvote-consensus — omicverse/omicverse-skills