Metadata-Version: 2.4
Name: cellconsensus
Version: 1.1.0
Summary: Hierarchical unsupervised cell type annotation from consensus markers
Author: tansey-lab
Author-email: Antoine de Mathelin <antoine.demat@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/tansey-lab/cellconsensus
Project-URL: Repository, https://github.com/tansey-lab/cellconsensus
Project-URL: Issues, https://github.com/tansey-lab/cellconsensus/issues
Keywords: single-cell,scRNA-seq,cell-type-annotation,consensus-markers,bioinformatics
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: pandas
Requires-Dist: scanpy
Requires-Dist: scipy
Requires-Dist: pynndescent
Dynamic: license-file

# CellConsensus

> ⚠️ **Heavy development.** API and outputs are evolving rapidly — breaking changes between versions should be expected. Pin a specific version if you need stability.

Hierarchical unsupervised cell type annotation from consensus marker genes — three levels of granularity, no reference atlas required, plus user-defined gene-set and cell-type scoring.

📖 Full README with figures and demo video: <https://github.com/tansey-lab/cellconsensus>

## Explore the database

Browse the underlying consensus marker database — per-cell-type marker lists, sources, and gene rankings — at **<http://cellconsensus.org/>**.

The same database is exposed as an MCP server so AI assistants can query it conversationally (e.g. *"what are the markers for memory CD8+ T cells?"*, *"what is the cell type for this set of marker genes: LST1, FCER1G, AIF1, FTH1, IFITM2?"*):

```
https://wrbcaolmpdeefznfkqpj.supabase.co/functions/v1/mcp
```

**Claude:** Settings → Connectors → Add custom connector → paste the URL above.
**ChatGPT:** Settings → Apps → Advanced settings → enable Developer mode → Create Connector → paste the URL above.

## Installation

```bash
pip install cellconsensus
```

Or the latest development version from GitHub:

```bash
pip install git+https://github.com/tansey-lab/cellconsensus.git
```

## Usage

```python
from cellconsensus import CellConsensus
import scanpy as sc

adata = sc.read_h5ad("my_data.h5ad")

cc = CellConsensus()
cc.fit(adata, include_cancer=True, cancer_types=["lung_adenocarcinoma"])

labels_lvl1 = cc.predict(level=1)   # "T cell", "myeloid cell", ...
labels_lvl2 = cc.predict(level=2)   # "CD4+ T cell", "macrophage", ...
labels_lvl3 = cc.predict(level=3)   # "memory CD4+ T cell", ...

# Per-cell × per-type score matrix (DataFrame, n_cells x n_lvl1_types)
S = cc.score_matrix(level=1)

# Save / reload
cc.save("model.pkl")
cc2 = CellConsensus.load("model.pkl")
```

`cancer_types` accepts any key from `cellconsensus.list_cancer_types()` (120 entries including `lung_adenocarcinoma`, `breast_carcinoma`, `melanoma`, …). Omit `include_cancer` for normal-tissue-only fits. The available cell-type keys at each level are listed by `cellconsensus.load_cell_type(level=1|2|3)`.

## Per-cell-type scores

`predict_score` returns the continuous score for any cell type (at any level) or any cancer type, reduced the same way as fit (NN smoothing for `ccc`, per-cluster averaging for `precomputed`). Use `load_cell_type(level=N)` to see the available cell-type keys; `list_cancer_types()` for cancer keys.

```python
from cellconsensus import load_cell_type, list_cancer_types

load_cell_type(level=1)   # {'t_cell': 'T cell', 'myeloid_cell': 'myeloid cell', ...}
load_cell_type(level=2)   # 44 subtypes
load_cell_type(level=3)   # 76 fine-grained types

# Single key, list, or mixed cell type + cancer in one call:
cc.predict_score("t_cell")                       # L1 T-cell score per cell
cc.predict_score(["nk", "monocyte"], level=2)    # two L2 scores
cc.predict_score(["t_cell", "melanoma"])         # mixed; cancer auto-detected
```

## Custom gene signatures

Score cells against any user-supplied marker list — pooled the same way as the built-in references (NN-graph smoothing for `ccc`, per-cluster averaging for `precomputed`), so the result is directly comparable to entries of `score_matrix`.

```python
sig = {"WT1": 10, "CCND1": 8, "CD99": 7, "NCAM1": 6, "MKI67": 5}
df = cc.predict_gene_set(list(sig.keys()), weights=sig, name="my_sig")
adata.obs["my_sig_score"] = df["my_sig"].values
```

`weights` accepts a list, a dict (missing entries default to 1.0), or `None` for uniform. Negative weights are allowed (anti-markers).

## Bringing your own clusters

Already have clusters (Leiden, or anything else)? Pass `clustering="precomputed"` with the `obs` column that holds the labels. CellConsensus uses the **same three-level taxonomy** as the default `ccc` mode — it just averages the marker scores across all cells in each cluster (no NN smoothing) and labels every cluster by the argmax. Clusters are never split: each one gets a single label per level, gaining precision from level 1 to level 3.

```python
import scanpy as sc

sc.pp.neighbors(adata)
sc.tl.leiden(adata, key_added="my_clusters")   # your clustering, your way

cc = CellConsensus(clustering="precomputed", cluster_key="my_clusters")
cc.fit(adata)
cc.predict(level=1)   # "T cell", "myeloid cell", ...
cc.predict(level=3)   # "memory CD4+ T cell", ...
```
