cellassign
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:
- extracts marker expression from the
AnnDataobject; - smooths expression over the cell-cell neighbour graph;
- rank-normalises positive expression values;
- averages marker scores per category;
- aggregates cell-level scores at the group or cluster level;
- 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b440165a5d4fd6f46dfbbb049d2927af4e911053d903b90f182311b8a841897
|
|
| MD5 |
f9a067f5a0314dfb9328d8a15e1224cf
|
|
| BLAKE2b-256 |
9b09dfcffb5dd56f47debfa55839a1cc1c98948928fbdfcf529b978ea66873d7
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b405fb8579cd97249cb15500a8b1913f96dfdea01ffa093fcd7dea263fcfe699
|
|
| MD5 |
2f9fc7fe56c9edb49f8e6fda203e95a7
|
|
| BLAKE2b-256 |
ca7475b575b321cacff9084708c183fa113d2ebf78e8740904ec7c31c268cec8
|