GitHub View CyteType

Python client

Preprocess AnnData, run CyteType annotation, and read results in Python.

Use the Python client with Scanpy/AnnData objects.

Preprocessing your data

CyteType requires differential expression results computed per cluster before submission.

import scanpy as sc

# Assumes adata already has normalized counts in adata.X
# and cluster labels in adata.obs["leiden"]

sc.tl.rank_genes_groups(
    adata,
    groupby="leiden",
    method="wilcoxon",
    key_added="rank_genes_leiden",
    n_genes=100,
)

# If gene symbols are stored separately from var_names:
# adata.var["gene_symbols"] = adata.var_names  # or set during load

Initializing the annotator

The initialization step validates your data and precomputes expression percentages. This can take a few minutes on large datasets but only needs to run once per object.

from cytetype import CyteType

annotator = CyteType(
    adata,
    group_key="leiden",             # column in adata.obs with cluster labels
    rank_key="rank_genes_leiden",   # key in adata.uns with DE results
    gene_symbols_column="gene_symbols",  # column in adata.var with gene symbols
    n_top_genes=50,                 # top marker genes per cluster
    aggregate_metadata=True,        # include obs metadata in context
    min_percentage=10,              # min % threshold for metadata
    coordinates_key="X_umap",      # key in adata.obsm for UMAP coordinates
    max_cells_per_group=1000,       # cells sampled per cluster for visualization
    auth_token=None,                # Bearer token (if your deployment requires one)
)

Running annotation

The study_context is the most important parameter for annotation quality. Describe your tissue, organism, disease state, and experimental setup in one or two sentences.

adata = annotator.run(
    study_context="Human colorectal cancer biopsy, tumor microenvironment, 10X Genomics 5' scRNA-seq, treatment-naive patients",
    metadata={
        "Study": "My TME atlas",
        "GEO": "https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE123456",
        "DOI": "https://doi.org/10.1038/example"
    },
    n_parallel_clusters=4,          # increase for faster annotation (watch rate limits)
    results_prefix="cytetype",      # prefix for result columns
    timeout_seconds=7200,
    show_progress=True,
)

Accessing results

After a successful run, annotations are stored in your object and can be accessed immediately.

# Annotation columns added to adata.obs:
# cytetype_annotation_leiden       — cell type label
# cytetype_cellOntologyTerm_leiden — Cell Ontology term name
# cytetype_cellOntologyTermID_leiden — CL:xxxxxxx ID
# cytetype_cellState_leiden        — functional state

import json
results = json.loads(adata.uns["cytetype_results"]["result"])

for ann in results["annotations"]:
    print(ann["clusterId"], ann["annotation"], ann["ontologyTermID"])

# If you need to re-fetch results after disconnecting:
results = annotator.get_results()

💡 Tip: Jobs continue running on the server even after your local session disconnects. Use annotator.get_results() to retrieve results after reconnecting.

Custom LLM configuration

By default CyteType uses its own hosted model. You can bring your own LLM from any supported provider.

# Single LLM configuration
adata = annotator.run(
    study_context="...",
    llm_configs=[{
        "provider": "openai",
        "name": "gpt-4o",
        "apiKey": "sk-...",
        "baseUrl": "https://api.openai.com/v1",   # optional
        "modelSettings": {"temperature": 0.0, "max_tokens": 4096}
    }]
)

# Multiple providers (different agents can use different models)
adata = annotator.run(
    study_context="...",
    llm_configs=[
        {
            "provider": "anthropic",
            "name": "claude-3-5-sonnet-20241022",
            "apiKey": "sk-ant-...",
            "targetAgents": ["annotator", "reviewer"]
        },
        {
            "provider": "openai",
            "name": "gpt-4o-mini",
            "apiKey": "sk-...",
            "targetAgents": ["summarizer", "clinician"]
        }
    ]
)

# AWS Bedrock
adata = annotator.run(
    study_context="...",
    llm_configs=[{
        "provider": "bedrock",
        "name": "us.anthropic.claude-3-5-sonnet-20241022-v2:0",
        "awsAccessKeyId": "AKIA...",
        "awsSecretAccessKey": "...",
        "awsDefaultRegion": "us-east-1"
    }]
)

Supported providers: anthropic, bedrock, fireworks, google, groq, huggingface, mistral, openai, openrouter, vertex, xai.

Authentication

For deployments that require a bearer token (private or enterprise instances):

# Pass at initialization (applies to all run() calls)
annotator = CyteType(adata, group_key="leiden", auth_token="your-token")

# Or override at run time
adata = annotator.run(study_context="...", auth_token="your-token")

Learn more

R client

Dashboard

Understanding your report