Skip to main content

cellassign

CI PyPI version Python versions License Ruff DOI

Lightweight marker-based assignment of cell categories in AnnData objects.

cellassign assigns cell-group or cluster-level labels using user-defined marker gene sets. It is designed for single-cell workflows where cells have already been clustered, and where a simple marker-based annotation layer is useful.

The package works directly on AnnData objects and uses the precomputed neighbour graph stored in adata.obsp["connectivities"].

Installation

Install the package from PyPI:

pip install cellassign

For development:

git clone https://github.com/alexmascension/cell_asign.git
cd cell_asign
pip install -e ".[dev]"

To install optional Scanpy support for examples and integration tests:

pip install -e ".[dev,scanpy]"

Quick start

import cellassign as ca

markers = {
    "T_cells": ["CD3D", "CD3E", "TRAC", "IL7R"],
    "B_cells": ["MS4A1", "CD79A"],
    "Myeloid": ["LYZ", "S100A8", "FCGR3A", "LST1"],
}

ca.assign_cats(
    adata,
    markers,
    column_groupby="leiden",
    key_added="cell_type_marker",
)

This adds the assigned category to:

adata.obs["cell_type_marker"]

It also adds per-category and summary score columns to adata.obs.

We recommend runnning clustering with two resolution parameters: the first one should be high, to obtain a fine clustering (many clusters) and assign thus the same category to several clusters at once. If the first resolution is too coarse you might risk assigning clusters "wrong", in the sense that splitting a large cluster into smaller clusters may assign other unexpected clusters, or unexplored clusters that require a more thorough inspection.

Expected input

assign_cats expects an AnnData object with:

  • marker genes present in adata.var_names;
  • a grouping column in adata.obs, such as "leiden" or "louvain";
  • a precomputed neighbour graph in adata.obsp["connectivities"].

For example, in a Scanpy workflow:

import scanpy as sc

sc.pp.neighbors(adata)
sc.tl.leiden(adata)

Then run:

ca.assign_cats(
    adata,
    markers,
    column_groupby="leiden",
    key_added="cell_type_marker",
)

How it works

For each marker gene, cellassign:

  1. extracts marker expression from the AnnData object;
  2. smooths expression over the cell-cell neighbour graph;
  3. rank-normalises positive expression values;
  4. averages marker scores per category;
  5. aggregates cell-level scores at the group or cluster level;
  6. assigns each group to the category with the highest score.

The final label is mapped back to all cells in the group.

This makes the method less sensitive to noisy expression in individual cells, while keeping the annotation logic simple and interpretable.

Main function

ca.assign_cats(
    adata,
    dict_cats,
    column_groupby="leiden",
    quantile_gene_sel=0.7,
    do_return=False,
    intermediate_states=False,
    diff=0.05,
    key_added="assigned_cats",
    min_score=0.6,
    others_name="unassigned",
    verbose=True,
)

Parameters

adata AnnData object containing expression data, cell metadata, and a neighbour graph.

dict_cats Dictionary mapping category names to marker genes.

{
    "T_cells": ["CD3D", "CD3E"],
    "B_cells": ["MS4A1", "CD79A"],
}

column_groupby Column in adata.obs containing the groups or clusters to assign.

quantile_gene_sel Quantile used to aggregate cell-level category scores within each group.

do_return If True, returns the per-group category score table.

intermediate_states If True, groups with similarly high category scores are labelled as intermediate states, for example "T_cells/NK_cells".

diff Maximum score difference from the best category for inclusion in an intermediate-state label.

key_added Name of the output column added to adata.obs.

min_score Groups with maximum score below this value are assigned to others_name.

others_name Label used for low-confidence assignments.

verbose If True, prints marker genes that are missing from adata.var_names.

Outputs

The function modifies adata in place.

Main output:

adata.obs[key_added]

Additional score columns:

adata.obs[f"{key_added}_max"]
adata.obs[f"{key_added}_mean"]
adata.obs[f"{key_added}_std"]
adata.obs[f"{key_added}_CV"]
adata.obs[f"{key_added}_{category}"]

Run parameters and missing marker genes are stored in:

adata.uns["cell_assign"][key_added]

If do_return=True, the function also returns a pandas.DataFrame with per-group category scores.

scores = ca.assign_cats(
    adata,
    markers,
    column_groupby="leiden",
    key_added="cell_type_marker",
    do_return=True,
)

Example with intermediate states

ca.assign_cats(
    adata,
    markers,
    column_groupby="leiden",
    key_added="cell_type_marker",
    intermediate_states=True,
    diff=0.05,
)

Groups with several categories close to the maximum score are labelled with joined names, such as:

T_cells/NK_cells

Recommendations (based on experience)

  • Do you have unknown clusters? Try lowering min_score. If they continue, or are assigned to populations that you know are incorrect, it's likely it is a new population.
  • Try to go with specific markers. Broad markers may lead to assignment of novel populations to "broad-spectrum" populations. Sometimes a marker with lower expression but which ensures not being expressed in other cell types can be a better marker.
  • Try to use a similar number of markers. Populations with discordant numbers of markers (an order of magnitude, or even 2x if marker expression is broad) may lead to a bias of assignment to the population with greater ammount of markers.
  • Results depend on quantile_gene_sel. Try several values to see how robust the assignment is. If it varies a lot, probably a few markers are leading the lack of robustness.

Citation

If you use cellassign, please cite this repository:

@software{cellassign,
  author = {Ascensión, Alex M.},
  title = {cellassign: marker-based cell category assignment for AnnData objects},
  url = {https://github.com/alexmascension/cell_asign},
  version = {1.0.1}
}

Ascensión, Alex M. (2026). cellassign: Lightweight marker-based assignment of cell categories in AnnData objects.. Zenodo. https://doi.org/10.5281/zenodo.21264220

A CITATION.cff file is also provided for citation managers and GitHub citation metadata.

License

This project is licensed under the MIT License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cellassign-1.0.1.tar.gz (14.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cellassign-1.0.1-py3-none-any.whl (9.6 kB view details)

Uploaded Python 3

File details

Details for the file cellassign-1.0.1.tar.gz.

File metadata

  • Download URL: cellassign-1.0.1.tar.gz
  • Upload date:
  • Size: 14.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for cellassign-1.0.1.tar.gz
Algorithm Hash digest
SHA256 7b440165a5d4fd6f46dfbbb049d2927af4e911053d903b90f182311b8a841897
MD5 f9a067f5a0314dfb9328d8a15e1224cf
BLAKE2b-256 9b09dfcffb5dd56f47debfa55839a1cc1c98948928fbdfcf529b978ea66873d7

See more details on using hashes here.

File details

Details for the file cellassign-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: cellassign-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 9.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for cellassign-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b405fb8579cd97249cb15500a8b1913f96dfdea01ffa093fcd7dea263fcfe699
MD5 2f9fc7fe56c9edb49f8e6fda203e95a7
BLAKE2b-256 ca7475b575b321cacff9084708c183fa113d2ebf78e8740904ec7c31c268cec8

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 files

0.1.2

1 file

0.1.1

1 file

0.1.0

1 file

0.0.2

1 file

0.0.1

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page